commit 21de8138fee88f812099d8b0b71d8280f4f6ba4e from: Stefan Sperling via: Thomas Adam date: Mon Sep 05 16:46:35 2022 UTC detect packed vs. on-disk reference collision when listing refs ok op@ commit - d68b973725ce0a2c7b1f5094448a444d4f2effdc commit + 21de8138fee88f812099d8b0b71d8280f4f6ba4e blob - 2e6723491391ba8acccf1a7f0ef9085db6cba827 blob + 3a699c9c2d5c9bc7d891ae0c0e65af894a4e653e --- lib/reference.c +++ lib/reference.c @@ -860,6 +860,27 @@ got_reflist_insert(struct got_reflist_entry **newp, new->ref = ref; *newp = new; + if (cmp_cb != got_ref_cmp_by_name && + (new->ref->flags & GOT_REF_IS_PACKED)) { + /* + * If we are not sorting elements by name then we must still + * detect collisions between a packed ref and an on-disk ref + * using the same name. On-disk refs take precedence and are + * already present on the list before packed refs get added. + */ + TAILQ_FOREACH(re, refs, entry) { + err = got_ref_cmp_by_name(NULL, &cmp, + re->ref, new->ref); + if (err) + return err; + if (cmp == 0) { + free(new); + *newp = NULL; + return NULL; + } + } + } + /* * We must de-duplicate entries on insert because packed-refs may * contain redundant entries. On-disk refs take precedence. blob - a025c5170abf06b7f707406ee2d9193c3fa6ff43 blob + cab7171d5632c0bdf72e14e1d6dda98d3a4ce810 --- regress/cmdline/branch.sh +++ regress/cmdline/branch.sh @@ -498,7 +498,45 @@ test_branch_show() { test_done "$testroot" "$ret" } + +test_branch_packed_ref_collision() { + local testroot=`test_init branch_packed_ref_collision` + local commit_id=`git_show_head $testroot/repo` + got br -r $testroot/repo zoo > $testroot/stdout + got co -b zoo $testroot/repo $testroot/wt > /dev/null + echo "modified alpha" > $testroot/wt/alpha + + # sleep in order to ensure that a significant fraction of time + # passes between commits; required for got branch -t option below + sleep 1 + + (cd $testroot/wt && got commit -m "modified alpha" >/dev/null) + local commit_id2=`git_show_branch_head $testroot/repo zoo` + + # Fabricate a packed reference which points to an older commit + # and collides with the existing on-disk reference + echo '# pack-refs with: peeled fully-peeled sorted' > \ + $testroot/repo/.git/packed-refs + echo "$commit_id refs/heads/zoo" >> $testroot/repo/.git/packed-refs + + # Bug: This command used to show both packed and on-disk + # variants of ref/heads/zoo: + (cd $testroot/wt && got br -lt > $testroot/stdout) + + echo "* zoo: $commit_id2" > $testroot/stdout.expected + echo " master: $commit_id" >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + test_done "$testroot" "$ret" +} + test_parseargs "$@" run_test test_branch_create run_test test_branch_list @@ -506,3 +544,4 @@ run_test test_branch_delete run_test test_branch_delete_current_branch run_test test_branch_delete_packed run_test test_branch_show +run_test test_branch_packed_ref_collision