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 functionmaint
commit
2b69d3116f
|
@ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
|
||||||
* remote no-such-ref' would silently succeed without issuing
|
* remote no-such-ref' would silently succeed without issuing
|
||||||
* an error.
|
* an error.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < nr_sought; i++) {
|
ret |= report_unmatched_refs(sought, nr_sought);
|
||||||
if (!sought[i] || sought[i]->matched)
|
|
||||||
continue;
|
|
||||||
error("no such remote ref %s", sought[i]->name);
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ref) {
|
while (ref) {
|
||||||
printf("%s %s\n",
|
printf("%s %s\n",
|
||||||
|
|
51
fetch-pack.c
51
fetch-pack.c
|
@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
|
||||||
break; /* definitely do not have it */
|
break; /* definitely do not have it */
|
||||||
else if (cmp == 0) {
|
else if (cmp == 0) {
|
||||||
keep = 1; /* definitely have it */
|
keep = 1; /* definitely have it */
|
||||||
sought[i]->matched = 1;
|
sought[i]->match_status = REF_MATCHED;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append unmatched requests to the list */
|
/* Append unmatched requests to the list */
|
||||||
if ((allow_unadvertised_object_request &
|
for (i = 0; i < nr_sought; i++) {
|
||||||
(ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
|
unsigned char sha1[20];
|
||||||
for (i = 0; i < nr_sought; i++) {
|
|
||||||
unsigned char sha1[20];
|
|
||||||
|
|
||||||
ref = sought[i];
|
ref = sought[i];
|
||||||
if (ref->matched)
|
if (ref->match_status != REF_NOT_MATCHED)
|
||||||
continue;
|
continue;
|
||||||
if (get_sha1_hex(ref->name, sha1) ||
|
if (get_sha1_hex(ref->name, sha1) ||
|
||||||
ref->name[40] != '\0' ||
|
ref->name[40] != '\0' ||
|
||||||
hashcmp(sha1, ref->old_oid.hash))
|
hashcmp(sha1, ref->old_oid.hash))
|
||||||
continue;
|
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 = copy_ref(ref);
|
||||||
newtail = &(*newtail)->next;
|
newtail = &(*newtail)->next;
|
||||||
|
} else {
|
||||||
|
ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*refs = newlist;
|
*refs = newlist;
|
||||||
|
@ -1094,3 +1096,26 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
|
||||||
clear_shallow_info(&si);
|
clear_shallow_info(&si);
|
||||||
return ref_cpy;
|
return ref_cpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int report_unmatched_refs(struct ref **sought, int nr_sought)
|
||||||
|
{
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < nr_sought; i++) {
|
||||||
|
if (!sought[i])
|
||||||
|
continue;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -45,4 +45,10 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
|
||||||
struct sha1_array *shallow,
|
struct sha1_array *shallow,
|
||||||
char **pack_lockfile);
|
char **pack_lockfile);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print an appropriate error message for each sought ref that wasn't
|
||||||
|
* matched. Return 0 if all sought refs were matched, otherwise 1.
|
||||||
|
*/
|
||||||
|
int report_unmatched_refs(struct ref **sought, int nr_sought);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
9
remote.h
9
remote.h
|
@ -89,8 +89,13 @@ struct ref {
|
||||||
force:1,
|
force:1,
|
||||||
forced_update:1,
|
forced_update:1,
|
||||||
expect_old_sha1:1,
|
expect_old_sha1:1,
|
||||||
deletion:1,
|
deletion:1;
|
||||||
matched: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
|
* Order is important here, as we write to FETCH_HEAD
|
||||||
|
|
|
@ -484,7 +484,7 @@ test_expect_success 'test lonely missing ref' '
|
||||||
cd client &&
|
cd client &&
|
||||||
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
|
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy
|
||||||
) >/dev/null 2>error-m &&
|
) >/dev/null 2>error-m &&
|
||||||
test_cmp expect-error error-m
|
test_i18ncmp expect-error error-m
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'test missing ref after existing' '
|
test_expect_success 'test missing ref after existing' '
|
||||||
|
@ -492,7 +492,7 @@ test_expect_success 'test missing ref after existing' '
|
||||||
cd client &&
|
cd client &&
|
||||||
test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
|
test_must_fail git fetch-pack --no-progress .. refs/heads/A refs/heads/xyzzy
|
||||||
) >/dev/null 2>error-em &&
|
) >/dev/null 2>error-em &&
|
||||||
test_cmp expect-error error-em
|
test_i18ncmp expect-error error-em
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'test missing ref before existing' '
|
test_expect_success 'test missing ref before existing' '
|
||||||
|
@ -500,7 +500,7 @@ test_expect_success 'test missing ref before existing' '
|
||||||
cd client &&
|
cd client &&
|
||||||
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
|
test_must_fail git fetch-pack --no-progress .. refs/heads/xyzzy refs/heads/A
|
||||||
) >/dev/null 2>error-me &&
|
) >/dev/null 2>error-me &&
|
||||||
test_cmp expect-error error-me
|
test_i18ncmp expect-error error-me
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'test --all, --depth, and explicit head' '
|
test_expect_success 'test --all, --depth, and explicit head' '
|
||||||
|
|
|
@ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' '
|
||||||
test_must_fail git cat-file -t $the_commit &&
|
test_must_fail git cat-file -t $the_commit &&
|
||||||
|
|
||||||
# fetching the hidden object should fail by default
|
# fetching the hidden object should fail by default
|
||||||
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
|
test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
|
||||||
|
test_i18ngrep "Server does not allow request for unadvertised object" err &&
|
||||||
test_must_fail git rev-parse --verify refs/heads/copy &&
|
test_must_fail git rev-parse --verify refs/heads/copy &&
|
||||||
|
|
||||||
# the server side can allow it to succeed
|
# the server side can allow it to succeed
|
||||||
|
|
14
transport.c
14
transport.c
|
@ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
|
||||||
static int fetch_refs_via_pack(struct transport *transport,
|
static int fetch_refs_via_pack(struct transport *transport,
|
||||||
int nr_heads, struct ref **to_fetch)
|
int nr_heads, struct ref **to_fetch)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
struct git_transport_data *data = transport->data;
|
struct git_transport_data *data = transport->data;
|
||||||
struct ref *refs;
|
struct ref *refs;
|
||||||
char *dest = xstrdup(transport->url);
|
char *dest = xstrdup(transport->url);
|
||||||
|
@ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport,
|
||||||
&transport->pack_lockfile);
|
&transport->pack_lockfile);
|
||||||
close(data->fd[0]);
|
close(data->fd[0]);
|
||||||
close(data->fd[1]);
|
close(data->fd[1]);
|
||||||
if (finish_connect(data->conn)) {
|
if (finish_connect(data->conn))
|
||||||
free_refs(refs);
|
ret = -1;
|
||||||
refs = NULL;
|
|
||||||
}
|
|
||||||
data->conn = NULL;
|
data->conn = NULL;
|
||||||
data->got_remote_heads = 0;
|
data->got_remote_heads = 0;
|
||||||
data->options.self_contained_and_connected =
|
data->options.self_contained_and_connected =
|
||||||
args.self_contained_and_connected;
|
args.self_contained_and_connected;
|
||||||
|
|
||||||
|
if (refs == NULL)
|
||||||
|
ret = -1;
|
||||||
|
if (report_unmatched_refs(to_fetch, nr_heads))
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
free_refs(refs_tmp);
|
free_refs(refs_tmp);
|
||||||
free_refs(refs);
|
free_refs(refs);
|
||||||
free(dest);
|
free(dest);
|
||||||
return (refs ? 0 : -1);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_had_errors(struct ref *ref)
|
static int push_had_errors(struct ref *ref)
|
||||||
|
|
Loading…
Reference in New Issue