Teach pack-objects an option to imply the revision machinery's new '--no-kept-objects' option when doing a reachability traversal. When '--assume-kept-packs-closed' is given as an argument to pack-objects, it behaves differently (i.e., passes different options to the ensuing revision walk) depending on whether or not other arguments are passed: - If the caller also specifies a '--keep-pack' argument (to mark a pack as kept in-core), then assume that this combination means to stop traversal only at in-core packs. - If instead the caller passes '--honor-pack-keep', then assume that the caller wants to stop traversal only at packs with a corresponding .keep file (consistent with the original meaning which only refers to packs with a .keep file). - If both '--keep-pack' and '--honor-pack-keep' are passed, then assume the caller wants to stop traversal at either kind of kept pack. Signed-off-by: Taylor Blau <me@xxxxxxxxxxxx> --- Documentation/git-pack-objects.txt | 11 ++++++ builtin/pack-objects.c | 13 +++++++ t/t6114-keep-packs.sh | 59 ++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 54d715ead1..cbe08e7415 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -135,6 +135,17 @@ depth is 4095. leading directory (e.g. `pack-123.pack`). The option could be specified multiple times to keep multiple packs. +--assume-kept-packs-closed:: + This flag causes `git rev-list` to halt the object traversal + when it encounters an object found in a kept pack. This is + dissimilar to `--honor-pack-keep`, which only prunes unwanted + results after the full traversal is completed. ++ +Without any `--keep-pack=<pack-name>` arguments, only packs with an +on-disk `*.keep` files are used when considering when to halt the +traversal. If other packs are artificially marked as "kept" with +`--keep-pack`, then those are considered as well. + --incremental:: This flag causes an object already in a pack to be ignored even if it would have otherwise been packed. diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 2a00358f34..a5dcd66f52 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -78,6 +78,7 @@ static int have_non_local_packs; static int incremental; static int ignore_packed_keep_on_disk; static int ignore_packed_keep_in_core; +static int assume_kept_packs_closed; static int allow_ofs_delta; static struct pack_idx_option pack_idx_opts; static const char *base_name; @@ -3542,6 +3543,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("create packs suitable for shallow fetches")), OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep_on_disk, N_("ignore packs that have companion .keep file")), + OPT_BOOL(0, "assume-kept-packs-closed", &assume_kept_packs_closed, + N_("assume the union of kept packs is closed under reachability")), OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"), N_("ignore this pack")), OPT_INTEGER(0, "compression", &pack_compression_level, @@ -3631,6 +3634,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) use_internal_rev_list = 1; strvec_push(&rp, "--unpacked"); } + if (assume_kept_packs_closed) + use_internal_rev_list = 1; if (exclude_promisor_objects) { use_internal_rev_list = 1; @@ -3711,6 +3716,14 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (!p) /* no keep-able packs found */ ignore_packed_keep_on_disk = 0; } + if (assume_kept_packs_closed) { + if (ignore_packed_keep_on_disk && ignore_packed_keep_in_core) + strvec_push(&rp, "--no-kept-objects"); + else if (ignore_packed_keep_on_disk) + strvec_push(&rp, "--no-kept-objects=on-disk"); + else if (ignore_packed_keep_in_core) + strvec_push(&rp, "--no-kept-objects=in-core"); + } if (local) { /* * unlike ignore_packed_keep_on_disk above, we do not diff --git a/t/t6114-keep-packs.sh b/t/t6114-keep-packs.sh index 9239d8aa46..0861305a04 100755 --- a/t/t6114-keep-packs.sh +++ b/t/t6114-keep-packs.sh @@ -66,4 +66,63 @@ test_expect_success '--no-kept-objects excludes kept non-MIDX object' ' test_cmp expect actual ' +test_expect_success '--no-kept-objects can respect only in-core keep packs' ' + test_when_finished "rm -fr actual-*.idx actual-*.pack" && + ( + git rev-list --objects --no-object-names packed..kept && + git rev-list --objects --no-object-names loose + ) | sort >expect && + + git pack-objects \ + --assume-kept-packs-closed \ + --keep-pack=pack-$MISC_PACK.pack \ + --all actual </dev/null && + idx_objects actual-*.idx >actual && + + test_cmp expect actual +' + +test_expect_success 'setup additional --no-kept-objects tests' ' + test_commit additional && + + ADDITIONAL_PACK=$(git pack-objects --revs .git/objects/pack/pack <<-EOF + refs/tags/additional + ^refs/tags/kept + EOF + ) +' + +test_expect_success '--no-kept-objects can respect only on-disk keep packs' ' + test_when_finished "rm -fr actual-*.idx actual-*.pack" && + ( + git rev-list --objects --no-object-names kept..additional && + git rev-list --objects --no-object-names packed + ) | sort >expect && + + git pack-objects \ + --assume-kept-packs-closed \ + --honor-pack-keep \ + --all actual </dev/null && + idx_objects actual-*.idx >actual && + + test_cmp expect actual +' + +test_expect_success '--no-kept-objects can respect mixed kept packs' ' + test_when_finished "rm -fr actual-*.idx actual-*.pack" && + ( + git rev-list --objects --no-object-names kept..additional && + git rev-list --objects --no-object-names loose + ) | sort >expect && + + git pack-objects \ + --assume-kept-packs-closed \ + --honor-pack-keep \ + --keep-pack=pack-$MISC_PACK.pack \ + --all actual </dev/null && + idx_objects actual-*.idx >actual && + + test_cmp expect actual +' + test_done -- 2.30.0.138.g6d7191ea01