Merge branch 'jk/fetch-reachability-error-fix'

Code clean-up and a fix for "git fetch" by an explicit object name
(as opposed to fetching refs by name).

* jk/fetch-reachability-error-fix:
  fetch: do not consider peeled tags as advertised tips
  remote.c: make singular free_ref() public
  fetch: use free_refs()
  pkt-line: prepare buffer before handling ERR packets
  upload-pack: send ERR packet for non-tip objects
  t5530: check protocol response for "not our ref"
  t5516: drop ok=sigpipe from unreachable-want tests
This commit is contained in:
Junio C Hamano
2019-04-25 16:41:23 +09:00
7 changed files with 59 additions and 25 deletions

View File

@ -573,9 +573,14 @@ static void filter_refs(struct fetch_pack_args *args,
next = ref->next; next = ref->next;
if (starts_with(ref->name, "refs/") && if (starts_with(ref->name, "refs/") &&
check_refname_format(ref->name, 0)) check_refname_format(ref->name, 0)) {
; /* trash */ /*
else { * trash or a peeled value; do not even add it to
* unmatched list
*/
free_one_ref(ref);
continue;
} else {
while (i < nr_sought) { while (i < nr_sought) {
int cmp = strcmp(ref->name, sought[i]->name); int cmp = strcmp(ref->name, sought[i]->name);
if (cmp < 0) if (cmp < 0)
@ -630,10 +635,7 @@ static void filter_refs(struct fetch_pack_args *args,
} }
oidset_clear(&tip_oids); oidset_clear(&tip_oids);
for (ref = unmatched; ref; ref = next) { free_refs(unmatched);
next = ref->next;
free(ref);
}
*refs = newlist; *refs = newlist;
} }

View File

@ -350,16 +350,17 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
return PACKET_READ_EOF; return PACKET_READ_EOF;
} }
if ((options & PACKET_READ_DIE_ON_ERR_PACKET) &&
starts_with(buffer, "ERR "))
die(_("remote error: %s"), buffer + 4);
if ((options & PACKET_READ_CHOMP_NEWLINE) && if ((options & PACKET_READ_CHOMP_NEWLINE) &&
len && buffer[len-1] == '\n') len && buffer[len-1] == '\n')
len--; len--;
buffer[len] = 0; buffer[len] = 0;
packet_trace(buffer, len, 0); packet_trace(buffer, len, 0);
if ((options & PACKET_READ_DIE_ON_ERR_PACKET) &&
starts_with(buffer, "ERR "))
die(_("remote error: %s"), buffer + 4);
*pktlen = len; *pktlen = len;
return PACKET_READ_NORMAL; return PACKET_READ_NORMAL;
} }

View File

@ -820,11 +820,11 @@ struct ref *copy_ref_list(const struct ref *ref)
return ret; return ret;
} }
static void free_ref(struct ref *ref) void free_one_ref(struct ref *ref)
{ {
if (!ref) if (!ref)
return; return;
free_ref(ref->peer_ref); free_one_ref(ref->peer_ref);
free(ref->remote_status); free(ref->remote_status);
free(ref->symref); free(ref->symref);
free(ref); free(ref);
@ -835,7 +835,7 @@ void free_refs(struct ref *ref)
struct ref *next; struct ref *next;
while (ref) { while (ref) {
next = ref->next; next = ref->next;
free_ref(ref); free_one_ref(ref);
ref = next; ref = next;
} }
} }

View File

@ -131,8 +131,10 @@ int ref_compare_name(const void *, const void *);
int check_ref_type(const struct ref *ref, int flags); int check_ref_type(const struct ref *ref, int flags);
/* /*
* Frees the entire list and peers of elements. * Free a single ref and its peer, or an entire list of refs and their peers,
* respectively.
*/ */
void free_one_ref(struct ref *ref);
void free_refs(struct ref *ref); void free_refs(struct ref *ref);
struct oid_array; struct oid_array;

View File

@ -1241,9 +1241,9 @@ do
cd shallow && cd shallow &&
# Some protocol versions (e.g. 2) support fetching # Some protocol versions (e.g. 2) support fetching
# unadvertised objects, so restrict this test to v0. # unadvertised objects, so restrict this test to v0.
test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \ test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
git fetch ../testrepo/.git $SHA1_3 && git fetch ../testrepo/.git $SHA1_3 &&
test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \ test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
git fetch ../testrepo/.git $SHA1_1 && git fetch ../testrepo/.git $SHA1_1 &&
git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true && git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&
git fetch ../testrepo/.git $SHA1_1 && git fetch ../testrepo/.git $SHA1_1 &&
@ -1251,8 +1251,9 @@ do
test_must_fail git cat-file commit $SHA1_2 && test_must_fail git cat-file commit $SHA1_2 &&
git fetch ../testrepo/.git $SHA1_2 && git fetch ../testrepo/.git $SHA1_2 &&
git cat-file commit $SHA1_2 && git cat-file commit $SHA1_2 &&
test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \ test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
git fetch ../testrepo/.git $SHA1_3 git fetch ../testrepo/.git $SHA1_3 2>err &&
test_i18ngrep "remote error:.*not our ref.*$SHA1_3\$" err
) )
' '
done done
@ -1284,6 +1285,17 @@ test_expect_success 'fetch follows tags by default' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'peeled advertisements are not considered ref tips' '
mk_empty testrepo &&
git -C testrepo commit --allow-empty -m one &&
git -C testrepo commit --allow-empty -m two &&
git -C testrepo tag -m foo mytag HEAD^ &&
oid=$(git -C testrepo rev-parse mytag^{commit}) &&
test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
git fetch testrepo $oid 2>err &&
test_i18ngrep "Server does not allow request for unadvertised object" err
'
test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' ' test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' '
mk_test testrepo heads/master && mk_test testrepo heads/master &&
rm -fr src dst && rm -fr src dst &&

View File

@ -57,13 +57,25 @@ test_expect_success 'upload-pack fails due to error in rev-list' '
grep "bad tree object" output.err grep "bad tree object" output.err
' '
test_expect_success 'upload-pack error message when bad ref requested' ' test_expect_success 'upload-pack fails due to bad want (no object)' '
printf "0045want %s multi_ack_detailed\n00000009done\n0000" \ printf "0045want %s multi_ack_detailed\n00000009done\n0000" \
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" >input && "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" >input &&
test_must_fail git upload-pack . <input >output 2>output.err && test_must_fail git upload-pack . <input >output 2>output.err &&
grep -q "not our ref" output.err && grep "not our ref" output.err &&
! grep -q multi_ack_detailed output.err grep "ERR" output &&
! grep multi_ack_detailed output.err
'
test_expect_success 'upload-pack fails due to bad want (not tip)' '
oid=$(echo an object we have | git hash-object -w --stdin) &&
printf "0045want %s multi_ack_detailed\n00000009done\n0000" \
"$oid" >input &&
test_must_fail git upload-pack . <input >output 2>output.err &&
grep "not our ref" output.err &&
grep "ERR" output &&
! grep multi_ack_detailed output.err
' '
test_expect_success 'upload-pack fails due to error in pack-objects enumeration' ' test_expect_success 'upload-pack fails due to error in pack-objects enumeration' '

View File

@ -592,7 +592,8 @@ error:
return 1; return 1;
} }
static void check_non_tip(struct object_array *want_obj) static void check_non_tip(struct object_array *want_obj,
struct packet_writer *writer)
{ {
int i; int i;
@ -611,9 +612,13 @@ error:
/* Pick one of them (we know there at least is one) */ /* Pick one of them (we know there at least is one) */
for (i = 0; i < want_obj->nr; i++) { for (i = 0; i < want_obj->nr; i++) {
struct object *o = want_obj->objects[i].item; struct object *o = want_obj->objects[i].item;
if (!is_our_ref(o)) if (!is_our_ref(o)) {
packet_writer_error(writer,
"upload-pack: not our ref %s",
oid_to_hex(&o->oid));
die("git upload-pack: not our ref %s", die("git upload-pack: not our ref %s",
oid_to_hex(&o->oid)); oid_to_hex(&o->oid));
}
} }
} }
@ -936,7 +941,7 @@ static void receive_needs(struct packet_reader *reader, struct object_array *wan
* by another process that handled the initial request. * by another process that handled the initial request.
*/ */
if (has_non_tip) if (has_non_tip)
check_non_tip(want_obj); check_non_tip(want_obj, &writer);
if (!use_sideband && daemon_mode) if (!use_sideband && daemon_mode)
no_progress = 1; no_progress = 1;