Skip to content

Commit 6d40b24

Browse files
committed
Merge branch 'jt/connected-show-missing-from-which-side' into seen
* jt/connected-show-missing-from-which-side: connected: distinguish local/remote bad objects
2 parents d72a22e + 4e99ebc commit 6d40b24

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-3
lines changed

builtin/fetch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
11381138

11391139
rm = ref_map;
11401140
if (check_connected(iterate_ref_map, &rm, &opt)) {
1141-
rc = error(_("%s did not send all necessary objects\n"), url);
1141+
rc = error(_("connectivity check failed for %s\n"), url);
11421142
goto abort;
11431143
}
11441144
}

connected.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ int check_connected(oid_iterate_fn fn, void *cb_data,
9494
strvec_push(&rev_list.args, opt->shallow_file);
9595
}
9696
strvec_push(&rev_list.args,"rev-list");
97+
strvec_push(&rev_list.args, "--detailed-bad-object");
9798
strvec_push(&rev_list.args, "--objects");
9899
strvec_push(&rev_list.args, "--stdin");
99100
if (has_promisor_remote())

revision.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,16 @@ void add_head_to_pending(struct rev_info *revs)
367367
add_pending_object(revs, obj, "HEAD");
368368
}
369369

370+
static void NORETURN bad_object(struct rev_info *revs, const char *name,
371+
unsigned int flags)
372+
{
373+
if (!revs->detailed_bad_object)
374+
die("bad object %s", name);
375+
if (flags & UNINTERESTING)
376+
die("bad object %s (from local object store)", name);
377+
die("bad object %s (from remote)", name);
378+
}
379+
370380
static struct object *get_reference(struct rev_info *revs, const char *name,
371381
const struct object_id *oid,
372382
unsigned int flags)
@@ -390,7 +400,7 @@ static struct object *get_reference(struct rev_info *revs, const char *name,
390400
return object;
391401
if (revs->exclude_promisor_objects && is_promisor_object(oid))
392402
return NULL;
393-
die("bad object %s", name);
403+
bad_object(revs, name, flags);
394404
}
395405
object->flags |= flags;
396406
return object;
@@ -426,7 +436,7 @@ static struct commit *handle_commit(struct rev_info *revs,
426436
if (revs->exclude_promisor_objects &&
427437
is_promisor_object(&tag->tagged->oid))
428438
return NULL;
429-
die("bad object %s", oid_to_hex(&tag->tagged->oid));
439+
bad_object(revs, oid_to_hex(&tag->tagged->oid), flags);
430440
}
431441
object->flags |= flags;
432442
/*
@@ -2540,6 +2550,8 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
25402550
if (fetch_if_missing)
25412551
BUG("exclude_promisor_objects can only be used when fetch_if_missing is 0");
25422552
revs->exclude_promisor_objects = 1;
2553+
} else if (!strcmp(arg, "--detailed-bad-object")) {
2554+
revs->detailed_bad_object = 1;
25432555
} else {
25442556
int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);
25452557
if (!opts)

revision.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ struct rev_info {
328328

329329
/* Location where temporary objects for remerge-diff are written. */
330330
struct tmp_objdir *remerge_objdir;
331+
332+
/* Error reporting info */
333+
unsigned detailed_bad_object : 1;
331334
};
332335

333336
/**

t/t5518-fetch-exit-status.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,46 @@ test_expect_success 'forced update' '
3838
3939
'
4040

41+
. "$TEST_DIRECTORY"/lib-httpd.sh
42+
start_httpd
43+
44+
test_expect_success 'connectivity check failure due to missing local object' '
45+
SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
46+
test_when_finished "rm -rf \"$SERVER\" client" &&
47+
test_create_repo "$SERVER" &&
48+
test_commit -C "$SERVER" foo &&
49+
50+
test_create_repo client &&
51+
test_commit -C client bar &&
52+
53+
# Simulate missing client objects.
54+
rm -rf client/.git/objects/* &&
55+
test_must_fail git -C client fetch $HTTPD_URL/smart/server 2>err &&
56+
grep "(from local object store)" err &&
57+
! grep "(from remote)" err &&
58+
grep "error: connectivity check failed for" err
59+
'
60+
61+
test_expect_success 'connectivity check failure due to missing remote object' '
62+
SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" &&
63+
test_when_finished "rm -rf \"$SERVER\" client" &&
64+
test_create_repo "$SERVER" &&
65+
test_commit -C "$SERVER" foo &&
66+
git -C "$SERVER" config uploadpack.allowRefInWant true &&
67+
SERVER_HEAD=$(git -C "$SERVER" rev-parse HEAD) &&
68+
SERVER_FAKE_HEAD=$(echo $SERVER_HEAD | tr "0123456789abcdef" "123456789abcdef0") &&
69+
70+
test_create_repo client &&
71+
72+
# Make the server claim that it has $SERVER_FAKE_HEAD as
73+
# refs/heads/main. The server still sends $SERVER_HEAD in the packfile,
74+
# so the client will see $SERVER_FAKE_HEAD as missing.
75+
echo "s=$SERVER_HEAD refs/heads/main=$SERVER_FAKE_HEAD refs/heads/main= if /wanted-refs/../packfile/" >"$HTTPD_ROOT_PATH/one-time-perl" &&
76+
77+
test_must_fail git -C client fetch $HTTPD_URL/one_time_perl/server refs/heads/main 2>err &&
78+
grep "(from remote)" err &&
79+
! grep "(from local object store)" err &&
80+
grep "error: connectivity check failed for" err
81+
'
82+
4183
test_done

0 commit comments

Comments
 (0)