]> git.ipfire.org Git - thirdparty/git.git/commitdiff
pack-objects: fix error when packing same pack twice
authorPatrick Steinhardt <ps@pks.im>
Fri, 14 Apr 2023 06:01:49 +0000 (08:01 +0200)
committerJunio C Hamano <gitster@pobox.com>
Fri, 14 Apr 2023 17:27:51 +0000 (10:27 -0700)
When passed the same packfile twice via `--stdin-packs` we return an
error that the packfile supposedly was not found. This is because when
reading packs into the list of included or excluded packfiles, we will
happily re-add packfiles even if they are part of the lists already. And
while the list can now contain duplicates, we will only set the `util`
pointer of the first list entry to the `packed_git` structure. We notice
that at a later point when checking that all list entries have their
`util` pointer set and die with an error.

While this is kind of a nonsensical request, this scenario can be hit
when doing geometric repacks. When a repository is connected to an
alternate object directory and both have the exact same packfile then
both would get added to the geometric sequence. And when we then decide
to perform the repack, we will invoke git-pack-objects(1) with the same
packfile twice.

Fix this bug by removing any duplicates from both the included and
excluded packs.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/pack-objects.c
t/t5331-pack-objects-stdin.sh
t/t7703-repack-geometric.sh

index 74a167a180cd4080919d8c3a614c098ad96a2b42..c97ae1b6d00115f8ec2a0fe04d5f831274b3002f 100644 (file)
@@ -3344,7 +3344,9 @@ static void read_packs_list_from_stdin(void)
        }
 
        string_list_sort(&include_packs);
+       string_list_remove_duplicates(&include_packs, 0);
        string_list_sort(&exclude_packs);
+       string_list_remove_duplicates(&exclude_packs, 0);
 
        for (p = get_all_packs(the_repository); p; p = p->next) {
                const char *pack_name = pack_basename(p);
index d5eece5899b892400a508eb20af1f6ddba989e85..71c8a4a6356558bb0d9abc4d9d87e12f30f25f61 100755 (executable)
@@ -7,6 +7,12 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
 TEST_PASSES_SANITIZE_LEAK=true
 . ./test-lib.sh
 
+packed_objects () {
+       git show-index <"$1" >tmp-object-list &&
+       cut -d' ' -f2 tmp-object-list | sort &&
+       rm tmp-object-list
+ }
+
 test_expect_success 'setup for --stdin-packs tests' '
        git init stdin-packs &&
        (
@@ -142,4 +148,25 @@ test_expect_success '--stdin-packs with broken links' '
        )
 '
 
+test_expect_success 'pack-objects --stdin with duplicate packfile' '
+       test_when_finished "rm -fr repo" &&
+
+       git init repo &&
+       (
+               cd repo &&
+               test_commit "commit" &&
+               git repack -ad &&
+
+               {
+                       basename .git/objects/pack/pack-*.pack &&
+                       basename .git/objects/pack/pack-*.pack
+               } >packfiles &&
+
+               git pack-objects --stdin-packs generated-pack <packfiles &&
+               packed_objects .git/objects/pack/pack-*.idx >expect &&
+               packed_objects generated-pack-*.idx >actual &&
+               test_cmp expect actual
+       )
+'
+
 test_done
index 9dd002437ff4666f7da90cb1849bd85f7cedcb68..a358dfb7bdcbf93144c8d27f13de630a770c9627 100755 (executable)
@@ -336,4 +336,29 @@ test_expect_success '--geometric --with-midx with no local objects' '
        test_dir_is_empty member/$packdir
 '
 
+test_expect_success '--geometric with same pack in main and alternate ODB' '
+       test_when_finished "rm -fr shared member" &&
+
+       # Create a repository with a single packfile that acts as alternate
+       # object database.
+       git init shared &&
+       test_commit -C shared "shared-objects" &&
+       git -C shared repack -ad &&
+
+       # We create the member repository as an exact copy so that it has the
+       # same packfile.
+       cp -r shared member &&
+       test-tool path-utils real_path shared/.git/objects >member/.git/objects/info/alternates &&
+       find shared/.git/objects -type f >expected-files &&
+
+       # Verify that we can repack objects as expected without observing any
+       # error. Having the same packfile in both ODBs used to cause an error
+       # in git-pack-objects(1).
+       git -C member repack --geometric 2 2>err &&
+       test_must_be_empty err &&
+       # Nothing should have changed.
+       find shared/.git/objects -type f >actual-files &&
+       test_cmp expected-files actual-files
+'
+
 test_done