Skip to content

Commit 414c823

Browse files
pks-tgitster
authored andcommitted
builtin/repack: fix --keep-unreachable when there are no packs
The "--keep-unreachable" flag is supposed to append any unreachable objects to the newly written pack. This flag is explicitly documented as appending both packed and loose unreachable objects to the new packfile. And while this works alright when repacking with preexisting packfiles, it stops working when the repository does not have any packfiles at all. The root cause are the conditions used to decide whether or not we want to append "--pack-loose-unreachable" to git-pack-objects(1). There are a couple of conditions here: - `has_existing_non_kept_packs()` checks whether there are existing packfiles. This condition makes sense to guard "--keep-pack=", "--unpack-unreachable" and "--keep-unreachable", because all of these flags only make sense in combination with existing packfiles. But it does not make sense to disable `--pack-loose-unreachable` when there aren't any preexisting packfiles, as loose objects can be packed into the new packfile regardless of that. - `delete_redundant` checks whether we want to delete any objects or packs that are about to become redundant. The documentation of `--keep-unreachable` explicitly says that `git repack -ad` needs to be executed for the flag to have an effect. It is not immediately obvious why such redundant objects need to be deleted in order for "--pack-unreachable-objects" to be effective. But as things are working as documented this is nothing we'll change for now. - `pack_everything & PACK_CRUFT` checks that we're not creating a cruft pack. This condition makes sense in the context of "--pack-loose-unreachable", as unreachable objects would end up in the cruft pack anyway. So while the second and third condition are sensible, it does not make any sense to condition `--pack-loose-unreachable` on the existence of packfiles. Fix the bug by splitting out the "--pack-loose-unreachable" and only making it depend on the second and third condition. Like this, loose unreachable objects will be packed regardless of any preexisting packfiles. Signed-off-by: Patrick Steinhardt <[email protected]> Acked-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f93ff17 commit 414c823

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

builtin/repack.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1370,9 +1370,12 @@ int cmd_repack(int argc,
13701370
"--unpack-unreachable");
13711371
} else if (keep_unreachable) {
13721372
strvec_push(&cmd.args, "--keep-unreachable");
1373-
strvec_push(&cmd.args, "--pack-loose-unreachable");
13741373
}
13751374
}
1375+
1376+
if (keep_unreachable && delete_redundant &&
1377+
!(pack_everything & PACK_CRUFT))
1378+
strvec_push(&cmd.args, "--pack-loose-unreachable");
13761379
} else if (geometry.split_factor) {
13771380
strvec_push(&cmd.args, "--stdin-packs");
13781381
strvec_push(&cmd.args, "--unpacked");

t/t7701-repack-unpack-unreachable.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,20 @@ test_expect_success 'repack -k packs unreachable loose objects' '
195195
git cat-file -p $sha1
196196
'
197197

198+
test_expect_success 'repack -k packs unreachable loose objects without existing packfiles' '
199+
test_when_finished "rm -rf repo" &&
200+
git init repo &&
201+
(
202+
cd repo &&
203+
204+
oid=$(echo would-be-deleted-loose | git hash-object -w --stdin) &&
205+
objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") &&
206+
test_path_is_file $objpath &&
207+
208+
git repack -ad --keep-unreachable &&
209+
test_path_is_missing $objpath &&
210+
git cat-file -p $oid
211+
)
212+
'
213+
198214
test_done

0 commit comments

Comments
 (0)