Skip to content

Commit 2b69d31

Browse files
committed
Merge branch 'mm/fetch-show-error-message-on-unadvertised-object' into maint
"git fetch" that requests a commit by object name, when the other side does not allow such an request, failed without much explanation. * mm/fetch-show-error-message-on-unadvertised-object: fetch-pack: add specific error for fetching an unadvertised object fetch_refs_via_pack: call report_unmatched_refs fetch-pack: move code to report unmatched refs to a function
2 parents 41534b6 + d56583d commit 2b69d31

File tree

7 files changed

+66
-30
lines changed

7 files changed

+66
-30
lines changed

builtin/fetch-pack.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
219219
* remote no-such-ref' would silently succeed without issuing
220220
* an error.
221221
*/
222-
for (i = 0; i < nr_sought; i++) {
223-
if (!sought[i] || sought[i]->matched)
224-
continue;
225-
error("no such remote ref %s", sought[i]->name);
226-
ret = 1;
227-
}
222+
ret |= report_unmatched_refs(sought, nr_sought);
228223

229224
while (ref) {
230225
printf("%s %s\n",

fetch-pack.c

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
578578
break; /* definitely do not have it */
579579
else if (cmp == 0) {
580580
keep = 1; /* definitely have it */
581-
sought[i]->matched = 1;
581+
sought[i]->match_status = REF_MATCHED;
582582
}
583583
i++;
584584
}
@@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
598598
}
599599

600600
/* Append unmatched requests to the list */
601-
if ((allow_unadvertised_object_request &
602-
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
603-
for (i = 0; i < nr_sought; i++) {
604-
unsigned char sha1[20];
601+
for (i = 0; i < nr_sought; i++) {
602+
unsigned char sha1[20];
605603

606-
ref = sought[i];
607-
if (ref->matched)
608-
continue;
609-
if (get_sha1_hex(ref->name, sha1) ||
610-
ref->name[40] != '\0' ||
611-
hashcmp(sha1, ref->old_oid.hash))
612-
continue;
604+
ref = sought[i];
605+
if (ref->match_status != REF_NOT_MATCHED)
606+
continue;
607+
if (get_sha1_hex(ref->name, sha1) ||
608+
ref->name[40] != '\0' ||
609+
hashcmp(sha1, ref->old_oid.hash))
610+
continue;
613611

614-
ref->matched = 1;
612+
if ((allow_unadvertised_object_request &
613+
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
614+
ref->match_status = REF_MATCHED;
615615
*newtail = copy_ref(ref);
616616
newtail = &(*newtail)->next;
617+
} else {
618+
ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
617619
}
618620
}
619621
*refs = newlist;
@@ -1094,3 +1096,26 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
10941096
clear_shallow_info(&si);
10951097
return ref_cpy;
10961098
}
1099+
1100+
int report_unmatched_refs(struct ref **sought, int nr_sought)
1101+
{
1102+
int i, ret = 0;
1103+
1104+
for (i = 0; i < nr_sought; i++) {
1105+
if (!sought[i])
1106+
continue;
1107+
switch (sought[i]->match_status) {
1108+
case REF_MATCHED:
1109+
continue;
1110+
case REF_NOT_MATCHED:
1111+
error(_("no such remote ref %s"), sought[i]->name);
1112+
break;
1113+
case REF_UNADVERTISED_NOT_ALLOWED:
1114+
error(_("Server does not allow request for unadvertised object %s"),
1115+
sought[i]->name);
1116+
break;
1117+
}
1118+
ret = 1;
1119+
}
1120+
return ret;
1121+
}

fetch-pack.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,10 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
4545
struct sha1_array *shallow,
4646
char **pack_lockfile);
4747

48+
/*
49+
* Print an appropriate error message for each sought ref that wasn't
50+
* matched. Return 0 if all sought refs were matched, otherwise 1.
51+
*/
52+
int report_unmatched_refs(struct ref **sought, int nr_sought);
53+
4854
#endif

remote.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,13 @@ struct ref {
8989
force:1,
9090
forced_update:1,
9191
expect_old_sha1:1,
92-
deletion:1,
93-
matched:1;
92+
deletion:1;
93+
94+
enum {
95+
REF_NOT_MATCHED = 0, /* initial value */
96+
REF_MATCHED,
97+
REF_UNADVERTISED_NOT_ALLOWED
98+
} match_status;
9499

95100
/*
96101
* Order is important here, as we write to FETCH_HEAD

t/t5500-fetch-pack.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,23 +484,23 @@ test_expect_success 'test lonely missing ref' '
484484
cd client &&
485485
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
486486
) >/dev/null 2>error-m &&
487-
test_cmp expect-error error-m
487+
test_i18ncmp expect-error error-m
488488
'
489489

490490
test_expect_success 'test missing ref after existing' '
491491
(
492492
cd client &&
493493
test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
494494
) >/dev/null 2>error-em &&
495-
test_cmp expect-error error-em
495+
test_i18ncmp expect-error error-em
496496
'
497497

498498
test_expect_success 'test missing ref before existing' '
499499
(
500500
cd client &&
501501
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
502502
) >/dev/null 2>error-me &&
503-
test_cmp expect-error error-me
503+
test_i18ncmp expect-error error-me
504504
'
505505

506506
test_expect_success 'test --all, --depth, and explicit head' '

t/t5516-fetch-push.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' '
10981098
test_must_fail git cat-file -t $the_commit &&
10991099
11001100
# fetching the hidden object should fail by default
1101-
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
1101+
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
1102+
test_i18ngrep "Server does not allow request for unadvertised object" err &&
11021103
test_must_fail git rev-parse --verify refs/heads/copy &&
11031104
11041105
# the server side can allow it to succeed

transport.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
204204
static int fetch_refs_via_pack(struct transport *transport,
205205
int nr_heads, struct ref **to_fetch)
206206
{
207+
int ret = 0;
207208
struct git_transport_data *data = transport->data;
208209
struct ref *refs;
209210
char *dest = xstrdup(transport->url);
@@ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport,
241242
&transport->pack_lockfile);
242243
close(data->fd[0]);
243244
close(data->fd[1]);
244-
if (finish_connect(data->conn)) {
245-
free_refs(refs);
246-
refs = NULL;
247-
}
245+
if (finish_connect(data->conn))
246+
ret = -1;
248247
data->conn = NULL;
249248
data->got_remote_heads = 0;
250249
data->options.self_contained_and_connected =
251250
args.self_contained_and_connected;
252251

252+
if (refs == NULL)
253+
ret = -1;
254+
if (report_unmatched_refs(to_fetch, nr_heads))
255+
ret = -1;
256+
253257
free_refs(refs_tmp);
254258
free_refs(refs);
255259
free(dest);
256-
return (refs ? 0 : -1);
260+
return ret;
257261
}
258262

259263
static int push_had_errors(struct ref *ref)

0 commit comments

Comments
 (0)