fetch-pack: add specific error for fetching an unadvertised object

Enhance filter_refs (which decides whether a request for an unadvertised
object should be sent to the server) to record a new match status on the
"struct ref" when a request is not allowed, and have
report_unmatched_refs check for this status and print a special error
message, "Server does not allow request for unadvertised object".

Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Matt McCutchen 2017-02-22 11:05:57 -05:00 коммит произвёл Junio C Hamano
Родитель e70a65c5d8
Коммит d56583ded6
3 изменённых файлов: 35 добавлений и 18 удалений

Просмотреть файл

@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
break; /* definitely do not have it */
else if (cmp == 0) {
keep = 1; /* definitely have it */
sought[i]->matched = 1;
sought[i]->match_status = REF_MATCHED;
}
i++;
}
@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
}
/* Append unmatched requests to the list */
if ((allow_unadvertised_object_request &
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
for (i = 0; i < nr_sought; i++) {
unsigned char sha1[20];
for (i = 0; i < nr_sought; i++) {
unsigned char sha1[20];
ref = sought[i];
if (ref->matched)
continue;
if (get_sha1_hex(ref->name, sha1) ||
ref->name[40] != '\0' ||
hashcmp(sha1, ref->old_oid.hash))
continue;
ref = sought[i];
if (ref->match_status != REF_NOT_MATCHED)
continue;
if (get_sha1_hex(ref->name, sha1) ||
ref->name[40] != '\0' ||
hashcmp(sha1, ref->old_oid.hash))
continue;
ref->matched = 1;
if ((allow_unadvertised_object_request &
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
ref->match_status = REF_MATCHED;
*newtail = copy_ref(ref);
newtail = &(*newtail)->next;
} else {
ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
}
}
*refs = newlist;
@ -1100,9 +1102,19 @@ int report_unmatched_refs(struct ref **sought, int nr_sought)
int i, ret = 0;
for (i = 0; i < nr_sought; i++) {
if (!sought[i] || sought[i]->matched)
if (!sought[i])
continue;
error(_("no such remote ref %s"), sought[i]->name);
switch (sought[i]->match_status) {
case REF_MATCHED:
continue;
case REF_NOT_MATCHED:
error(_("no such remote ref %s"), sought[i]->name);
break;
case REF_UNADVERTISED_NOT_ALLOWED:
error(_("Server does not allow request for unadvertised object %s"),
sought[i]->name);
break;
}
ret = 1;
}
return ret;

Просмотреть файл

@ -89,8 +89,13 @@ struct ref {
force:1,
forced_update:1,
expect_old_sha1:1,
deletion:1,
matched:1;
deletion:1;
enum {
REF_NOT_MATCHED = 0, /* initial value */
REF_MATCHED,
REF_UNADVERTISED_NOT_ALLOWED
} match_status;
/*
* Order is important here, as we write to FETCH_HEAD

Просмотреть файл

@ -1099,7 +1099,7 @@ test_expect_success 'fetch exact SHA1' '
# fetching the hidden object should fail by default
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
test_i18ngrep "no such remote ref" err &&
test_i18ngrep "Server does not allow request for unadvertised object" err &&
test_must_fail git rev-parse --verify refs/heads/copy &&
# the server side can allow it to succeed