summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/receive-pack.c4
-rwxr-xr-xt/t5400-send-pack.sh38
2 files changed, 41 insertions, 1 deletions
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index c23b0cce86..9ed8fbbfad 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -268,6 +268,8 @@ static int show_ref_cb(const char *path_full, const struct object_id *oid,
if (oidset_insert(seen, oid))
return 0;
path = ".have";
+ } else {
+ oidset_insert(seen, oid);
}
show_ref(path, oid->hash);
return 0;
@@ -289,9 +291,9 @@ static void write_head_info(void)
{
static struct oidset seen = OIDSET_INIT;
+ for_each_ref(show_ref_cb, &seen);
for_each_alternate_ref(show_one_alternate_ref, &seen);
oidset_clear(&seen);
- for_each_ref(show_ref_cb, &seen);
if (!sent_capabilities)
show_ref("capabilities^{}", null_sha1);
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 305ca7a930..3331e0f534 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -255,4 +255,42 @@ test_expect_success 'deny pushing to delete current branch' '
)
'
+extract_ref_advertisement () {
+ perl -lne '
+ # \\ is there to skip capabilities after \0
+ /push< ([^\\]+)/ or next;
+ exit 0 if $1 eq "0000";
+ print $1;
+ '
+}
+
+test_expect_success 'receive-pack de-dupes .have lines' '
+ git init shared &&
+ git -C shared commit --allow-empty -m both &&
+ git clone -s shared fork &&
+ (
+ cd shared &&
+ git checkout -b only-shared &&
+ git commit --allow-empty -m only-shared &&
+ git update-ref refs/heads/foo HEAD
+ ) &&
+
+ # Notable things in this expectation:
+ # - local refs are not de-duped
+ # - .have does not duplicate locals
+ # - .have does not duplicate itself
+ local=$(git -C fork rev-parse HEAD) &&
+ shared=$(git -C shared rev-parse only-shared) &&
+ cat >expect <<-EOF &&
+ $local refs/heads/master
+ $local refs/remotes/origin/HEAD
+ $local refs/remotes/origin/master
+ $shared .have
+ EOF
+
+ GIT_TRACE_PACKET=$(pwd)/trace git push fork HEAD:foo &&
+ extract_ref_advertisement <trace >refs &&
+ test_cmp expect refs
+'
+
test_done