multi-pack-index: prepare for 'expire' subcommand
authorDerrick Stolee <dstolee@microsoft.com>
Mon, 10 Jun 2019 23:35:23 +0000 (16:35 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 11 Jun 2019 17:34:40 +0000 (10:34 -0700)
The multi-pack-index tracks objects in a collection of pack-files.
Only one copy of each object is indexed, using the modified time
of the pack-files to determine tie-breakers. It is possible to
have a pack-file with no referenced objects because all objects
have a duplicate in a newer pack-file.

Introduce a new 'expire' subcommand to the multi-pack-index builtin.
This subcommand will delete these unused pack-files and rewrite the
multi-pack-index to no longer refer to those files. More details
about the specifics will follow as the method is implemented.

Add a test that verifies the 'expire' subcommand is correctly wired,
but will still be valid when the verb is implemented. Specifically,
create a set of packs that should all have referenced objects and
should not be removed during an 'expire' operation. The packs are
created carefully to ensure they have a specific order when sorted
by size. This will be important in a later test.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-multi-pack-index.txt
builtin/multi-pack-index.c
midx.c
midx.h
t/t5319-multi-pack-index.sh
index 1af406aca219221f6299bbb28672dccefd6e4ab8..6186c4c9369a9c5c57096f19fa9e428d662d5a5e 100644 (file)
@@ -31,6 +31,11 @@ write::
 verify::
        Verify the contents of the MIDX file.
 
+expire::
+       Delete the pack-files that are tracked  by the MIDX file, but
+       have no objects referenced by the MIDX. Rewrite the MIDX file
+       afterward to remove all references to these pack-files.
+
 
 EXAMPLES
 --------
index 72dfd3dadc7bf8037d4bd11d24aabca6a56a5fa8..ad10d4051214a78a086faaf6310b765f8f371f0c 100644 (file)
@@ -6,7 +6,7 @@
 #include "trace2.h"
 
 static char const * const builtin_multi_pack_index_usage[] = {
-       N_("git multi-pack-index [--object-dir=<dir>] (write|verify)"),
+       N_("git multi-pack-index [--object-dir=<dir>] (write|verify|expire)"),
        NULL
 };
 
@@ -47,6 +47,8 @@ int cmd_multi_pack_index(int argc, const char **argv,
                return write_midx_file(opts.object_dir);
        if (!strcmp(argv[0], "verify"))
                return verify_midx_file(the_repository, opts.object_dir);
+       if (!strcmp(argv[0], "expire"))
+               return expire_midx_packs(the_repository, opts.object_dir);
 
        die(_("unrecognized verb: %s"), argv[0]);
 }
diff --git a/midx.c b/midx.c
index e7e1fe4d65ac3be54154e44ff07cd6122011405c..3b7da1a3603e1f9a49c666cffb1d2784c22e0348 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -1140,3 +1140,8 @@ int verify_midx_file(struct repository *r, const char *object_dir)
 
        return verify_midx_error;
 }
+
+int expire_midx_packs(struct repository *r, const char *object_dir)
+{
+       return 0;
+}
diff --git a/midx.h b/midx.h
index 3eb29731f2b1e8e96a116a683fd8baad1020a46b..505f1431b7e309371aec7cdd7f1d6b56013b33f7 100644 (file)
--- a/midx.h
+++ b/midx.h
@@ -50,6 +50,7 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i
 int write_midx_file(const char *object_dir);
 void clear_midx_file(struct repository *r);
 int verify_midx_file(struct repository *r, const char *object_dir);
+int expire_midx_packs(struct repository *r, const char *object_dir);
 
 void close_midx(struct multi_pack_index *m);
 
index 1ebf19ec3cd559dbf9ae7205a225d6e49368a8d2..1b2d32f4756ffe1147fae5d707acb4a57df1012a 100755 (executable)
@@ -363,4 +363,53 @@ test_expect_success 'verify incorrect 64-bit offset' '
                "incorrect object offset"
 '
 
+test_expect_success 'setup expire tests' '
+       mkdir dup &&
+       (
+               cd dup &&
+               git init &&
+               test-tool genrandom "data" 4096 >large_file.txt &&
+               git update-index --add large_file.txt &&
+               for i in $(test_seq 1 20)
+               do
+                       test_commit $i
+               done &&
+               git branch A HEAD &&
+               git branch B HEAD~8 &&
+               git branch C HEAD~13 &&
+               git branch D HEAD~16 &&
+               git branch E HEAD~18 &&
+               git pack-objects --revs .git/objects/pack/pack-A <<-EOF &&
+               refs/heads/A
+               ^refs/heads/B
+               EOF
+               git pack-objects --revs .git/objects/pack/pack-B <<-EOF &&
+               refs/heads/B
+               ^refs/heads/C
+               EOF
+               git pack-objects --revs .git/objects/pack/pack-C <<-EOF &&
+               refs/heads/C
+               ^refs/heads/D
+               EOF
+               git pack-objects --revs .git/objects/pack/pack-D <<-EOF &&
+               refs/heads/D
+               ^refs/heads/E
+               EOF
+               git pack-objects --revs .git/objects/pack/pack-E <<-EOF &&
+               refs/heads/E
+               EOF
+               git multi-pack-index write
+       )
+'
+
+test_expect_success 'expire does not remove any packs' '
+       (
+               cd dup &&
+               ls .git/objects/pack >expect &&
+               git multi-pack-index expire &&
+               ls .git/objects/pack >actual &&
+               test_cmp expect actual
+       )
+'
+
 test_done