There may be multiple MIDX files in a single pack directory. The primary file is pointed to by a pointer file "midx-head" that contains an OID. The MIDX file to load is then given by "midx-<OID>.midx". This head file will be especially important when the MIDX files are extended to be incremental and we expect multiple MIDX files at any point. Signed-off-by: Derrick Stolee <dstolee@xxxxxxxxxxxxx> --- Documentation/git-midx.txt | 19 ++++++++++++++++++- builtin/midx.c | 32 ++++++++++++++++++++++++++++++-- midx.c | 31 +++++++++++++++++++++++++++++++ midx.h | 3 +++ t/t5318-midx.sh | 33 ++++++++++++++++++++++----------- 5 files changed, 104 insertions(+), 14 deletions(-) diff --git a/Documentation/git-midx.txt b/Documentation/git-midx.txt index 17464222c1..01f79cbba5 100644 --- a/Documentation/git-midx.txt +++ b/Documentation/git-midx.txt @@ -9,7 +9,7 @@ git-midx - Write and verify multi-pack-indexes (MIDX files). SYNOPSIS -------- [verse] -'git midx' --write [--pack-dir <pack_dir>] +'git midx' --write <options> [--pack-dir <pack_dir>] DESCRIPTION ----------- @@ -26,15 +26,32 @@ OPTIONS If specified, write a new midx file to the pack directory using the packfiles present. Outputs the hash of the result midx file. +--update-head:: + If specified with --write, update the midx-head file to point to + the written midx file. + EXAMPLES -------- +* Read the midx-head file and output the OID of the head MIDX file. ++ +------------------------------------------------ +$ git midx +------------------------------------------------ + * Write a MIDX file for the packfiles in your local .git folder. + ------------------------------------------------ $ git midx --write ------------------------------------------------ +* Write a MIDX file for the packfiles in your local .git folder and +* update the midx-head file. ++ +------------------------------------------------ +$ git midx --write --update-head +------------------------------------------------ + * Write a MIDX file for the packfiles in a different folder + --------------------------------------------------------- diff --git a/builtin/midx.c b/builtin/midx.c index 4aae14cf8e..84ce6588a2 100644 --- a/builtin/midx.c +++ b/builtin/midx.c @@ -9,13 +9,17 @@ #include "midx.h" static char const * const builtin_midx_usage[] = { - N_("git midx --write [--pack-dir <packdir>]"), + N_("git midx [--pack-dir <packdir>]"), + N_("git midx --write [--update-head] [--pack-dir <packdir>]"), NULL }; static struct opts_midx { const char *pack_dir; int write; + int update_head; + int has_existing; + struct object_id old_midx_oid; } opts; static int build_midx_from_packs( @@ -109,6 +113,22 @@ static int build_midx_from_packs( return 0; } +static void update_head_file(const char *pack_dir, const char *midx_id) +{ + int fd; + struct lock_file lk = LOCK_INIT; + char *head_path = get_midx_head_filename(pack_dir); + + fd = hold_lock_file_for_update(&lk, head_path, LOCK_DIE_ON_ERROR); + FREE_AND_NULL(head_path); + + if (fd < 0) + die_errno("unable to open midx-head"); + + write_in_full(fd, midx_id, GIT_MAX_HEXSZ); + commit_lock_file(&lk); +} + static int midx_write(void) { const char **pack_names = NULL; @@ -152,6 +172,9 @@ static int midx_write(void) printf("%s\n", midx_id); + if (opts.update_head) + update_head_file(opts.pack_dir, midx_id); + cleanup: if (pack_names) FREE_AND_NULL(pack_names); @@ -166,6 +189,8 @@ int cmd_midx(int argc, const char **argv, const char *prefix) N_("The pack directory containing set of packfile and pack-index pairs.") }, OPT_BOOL('w', "write", &opts.write, N_("write midx file")), + OPT_BOOL('u', "update-head", &opts.update_head, + N_("update midx-head to written midx file")), OPT_END(), }; @@ -187,9 +212,12 @@ int cmd_midx(int argc, const char **argv, const char *prefix) opts.pack_dir = strbuf_detach(&path, NULL); } + opts.has_existing = !!get_midx_head_oid(opts.pack_dir, &opts.old_midx_oid); + if (opts.write) return midx_write(); - usage_with_options(builtin_midx_usage, builtin_midx_options); + if (opts.has_existing) + printf("%s\n", oid_to_hex(&opts.old_midx_oid)); return 0; } diff --git a/midx.c b/midx.c index 5c320726ed..f4178c1b81 100644 --- a/midx.c +++ b/midx.c @@ -34,6 +34,37 @@ char* get_midx_filename_oid(const char *pack_dir, return strbuf_detach(&head_path, NULL); } +char *get_midx_head_filename(const char *pack_dir) +{ + struct strbuf head_filename = STRBUF_INIT; + strbuf_addstr(&head_filename, pack_dir); + strbuf_addstr(&head_filename, "/midx-head"); + return strbuf_detach(&head_filename, NULL); +} + +struct object_id *get_midx_head_oid(const char *pack_dir, + struct object_id *oid) +{ + char oid_hex[GIT_MAX_HEXSZ + 1]; + FILE *f; + char *head_filename = get_midx_head_filename(pack_dir); + + f = fopen(head_filename, "r"); + FREE_AND_NULL(head_filename); + + if (!f) + return 0; + + if (!fgets(oid_hex, sizeof(oid_hex), f)) + die("failed to read midx-head"); + + fclose(f); + + if (get_oid_hex(oid_hex, oid)) + return 0; + return oid; +} + struct pack_midx_details_internal { uint32_t pack_int_id; uint32_t internal_offset; diff --git a/midx.h b/midx.h index 4b00463651..9d9ab85261 100644 --- a/midx.h +++ b/midx.h @@ -7,6 +7,9 @@ extern char *get_midx_filename_oid(const char *pack_dir, struct object_id *oid); +extern char *get_midx_head_filename(const char *pack_dir); + +extern struct object_id *get_midx_head_oid(const char *pack_dir, struct object_id *oid); struct pack_midx_entry { struct object_id oid; diff --git a/t/t5318-midx.sh b/t/t5318-midx.sh index 869bbea29c..b66efcdce9 100755 --- a/t/t5318-midx.sh +++ b/t/t5318-midx.sh @@ -29,13 +29,16 @@ test_expect_success 'create objects' \ test_expect_success 'write-midx from index version 1' \ 'pack1=$(git rev-list --all --objects | git pack-objects --index-version=1 ${packdir}/test-1) && midx1=$(git midx --write) && - test_path_is_file ${packdir}/midx-${midx1}.midx' + test_path_is_file ${packdir}/midx-${midx1}.midx && + test_path_is_missing ${packdir}/midx-head' test_expect_success 'write-midx from index version 2' \ 'rm "${packdir}/test-1-${pack1}.pack" && pack2=$(git rev-list --all --objects | git pack-objects --index-version=2 ${packdir}/test-2) && - midx2=$(git midx --write) && - test_path_is_file ${packdir}/midx-${midx2}.midx' + midx2=$(git midx --write --update-head) && + test_path_is_file ${packdir}/midx-${midx2}.midx && + test_path_is_file ${packdir}/midx-head && + test $(cat ${packdir}/midx-head) = "$midx2"' test_expect_success 'Create more objects' \ 'for i in $(test_seq 100) @@ -49,8 +52,10 @@ test_expect_success 'Create more objects' \ test_expect_success 'write-midx with two packs' \ 'pack3=$(git rev-list --objects commit2 ^commit1 | git pack-objects --index-version=2 ${packdir}/test-3) && - midx3=$(git midx --write) && - test_path_is_file ${packdir}/midx-${midx3}.midx' + midx3=$(git midx --write --update-head) && + test_path_is_file ${packdir}/midx-${midx3}.midx && + test_path_is_file ${packdir}/midx-head && + test $(cat ${packdir}/midx-head) = "$midx3"' test_expect_success 'Add more packs' \ 'for j in $(test_seq 10) @@ -77,13 +82,17 @@ test_expect_success 'Add more packs' \ done' test_expect_success 'write-midx with twelve packs' \ - 'midx4=$(git midx --write) && - test_path_is_file ${packdir}/midx-${midx4}.midx' + 'midx4=$(git midx --write --update-head) && + test_path_is_file ${packdir}/midx-${midx4}.midx && + test_path_is_file ${packdir}/midx-head && + test $(cat ${packdir}/midx-head) = "$midx4"' test_expect_success 'write-midx with no new packs' \ - 'midx5=$(git midx --write) && + 'midx5=$(git midx --write --update-head) && test_path_is_file ${packdir}/midx-${midx5}.midx && - test "a$midx4" = "a$midx5"' + test "a$midx4" = "a$midx5" && + test_path_is_file ${packdir}/midx-head && + test $(cat ${packdir}/midx-head) = "$midx4"' test_expect_success 'create bare repo' \ 'cd .. && @@ -94,7 +103,9 @@ test_expect_success 'create bare repo' \ baredir=objects/pack' test_expect_success 'write-midx in bare repo' \ - 'midxbare=$(git midx --write) && - test_path_is_file ${baredir}/midx-${midxbare}.midx' + 'midxbare=$(git midx --write --update-head) && + test_path_is_file ${baredir}/midx-${midxbare}.midx && + test_path_is_file ${baredir}/midx-head && + test $(cat ${baredir}/midx-head) = "$midxbare"' test_done -- 2.15.0