The new --max-commit-count option behaves similarly to --max-object-count, when used together with --stdout: It limits the number of commits in the pack written to stdout. If the pack would exceed this limit, pack-objects will abort with an error message. Unlike --max-pack-size and --max-object-count, --max-commit-count must always be used together with --stdout. This is because using the commit count to split packs is not at all a good heuristic, since Git does not necessarily distribute commit objects uniformly across packs. Documentation and tests are included. Signed-off-by: Johan Herland <johan@xxxxxxxxxxx> --- Documentation/git-pack-objects.txt | 8 ++++++++ builtin/pack-objects.c | 24 +++++++++++++++++++++--- t/t5300-pack-object.sh | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 20c8551..e43904e 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -113,6 +113,14 @@ base-name:: The default is unlimited, unless the config variable `pack.packSizeLimit` is set. +--max-commit-count=<n>:: + This option is only useful together with --stdout. + Specifies the maximum number of commits allowed in the created + pack. If the number of commits would exceed the given limit, + pack-objects will fail with an error message. + The number can be suffixed with "k", "m", or "g". + The default is unlimited. + --honor-pack-keep:: This flag causes an object already in a local pack that has a .keep file to be ignored, even if it would have diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index f402a84..f0fc187 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -61,7 +61,7 @@ struct object_entry { */ static struct object_entry *objects; static struct pack_idx_entry **written_list; -static uint32_t nr_objects, nr_alloc, nr_result, nr_written; +static uint32_t nr_objects, nr_alloc, nr_result, nr_commits, nr_written; static int non_empty; static int reuse_delta = 1, reuse_object = 1; @@ -653,8 +653,11 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, if (ix >= 0) { if (exclude) { entry = objects + object_ix[ix] - 1; - if (!entry->preferred_base) + if (!entry->preferred_base) { nr_result--; + if (entry->type == OBJ_COMMIT) + nr_commits--; + } entry->preferred_base = 1; } return 0; @@ -694,8 +697,11 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type, entry->type = type; if (exclude) entry->preferred_base = 1; - else + else { nr_result++; + if (type == OBJ_COMMIT) + nr_commits++; + } if (found_pack) { entry->in_pack = found_pack; entry->in_pack_offset = found_offset; @@ -2125,6 +2131,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) const char **rp_av; int rp_ac_alloc = 64; int rp_ac; + unsigned long commit_count_limit = 0; read_replace_refs = 0; @@ -2179,6 +2186,11 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) usage(pack_usage); continue; } + if (!prefixcmp(arg, "--max-commit-count=")) { + if (!git_parse_ulong(arg+19, &commit_count_limit)) + usage(pack_usage); + continue; + } if (!prefixcmp(arg, "--window=")) { char *end; window = strtoul(arg+9, &end, 0); @@ -2322,6 +2334,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) pack_size_limit = 1024*1024; } + if (!pack_to_stdout && commit_count_limit) + die("--max-commit-count is only useful together with --stdout."); + if (!pack_to_stdout && thin) die("--thin cannot be used to build an indexable pack."); @@ -2348,6 +2363,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (non_empty && !nr_result) return 0; + if (pack_to_stdout && commit_count_limit && commit_count_limit < nr_commits) + die("unable to make pack within the commit count limit" + " (%lu commits)", commit_count_limit); if (nr_result) prepare_pack(window, depth); write_pack_file(); diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 602806d..80df631 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -396,6 +396,40 @@ test_expect_success 'verify resulting packs' ' git verify-pack test-11-*.pack ' +test_expect_success 'make a few more commits' ' + git reset --hard $commit && + echo "change" > file && + git add file && + git commit -m second && + commit2=`git rev-parse --verify HEAD` && + echo "more change" >> file && + git commit -a -m third && + commit3=`git rev-parse --verify HEAD` && + echo "even more change" >> file && + git commit -a -m fourth && + commit4=`git rev-parse --verify HEAD` && { + echo $commit && + echo $commit2 && + echo $commit3 && + echo $commit4 + } >>commit-list +' + +test_expect_success '--stdout works with large enough --max-commit-count' ' + git pack-objects --revs --stdout --max-commit-count=4 <commit-list >test-17.pack && + git index-pack --strict test-17.pack +' + +test_expect_success 'verify resulting pack' ' + git verify-pack test-17.pack +' + +test_expect_success '--stdout fails when pack exceeds --max-commit-count' ' + test_must_fail git pack-objects --revs --stdout --max-commit-count=3 <commit-list >test-18.pack 2>errs && + test_must_fail git index-pack --strict test-18.pack && + grep -q "commit count limit" errs +' + # # WARNING! # -- 1.7.5.rc1.3.g4d7b -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html