midx: expose `write_midx_file_only()` publicly

Expose a variant of the write_midx_file() function which ignores packs that aren't included in an explicit "allow" list. This will be used in an upcoming patch to power a new `--stdin-packs` mode of `git multi-pack-index write` for callers that only want to include certain packs in a MIDX (and ignore any packs which may have happened to enter the repository independently, e.g., from pushes). Those patches will provide test coverage for this new function. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Taylor Blau committed Sep 28, 2021 at 21:55 UTC 56d863e9799c9d440eba3e61346662745a58ab21
2 files changed +58 -8
midx.c
+49 -8
@@ -475,6 +475,8 @@ struct write_midx_context {
475 uint32_t num_large_offsets;
476
477 int preferred_pack_idx;
478 +
479 + struct string_list *to_include;
480 };
481
482 static void add_pack_to_midx(const char *full_path, size_t full_path_len,
@@ -484,8 +486,26 @@ static void add_pack_to_midx(const char *full_path, size_t full_path_len,
486
487 if (ends_with(file_name, ".idx")) {
488 display_progress(ctx->progress, ++ctx->pack_paths_checked);
489 + /*
490 + * Note that at most one of ctx->m and ctx->to_include are set,
491 + * so we are testing midx_contains_pack() and
492 + * string_list_has_string() independently (guarded by the
493 + * appropriate NULL checks).
494 + *
495 + * We could support passing to_include while reusing an existing
496 + * MIDX, but don't currently since the reuse process drags
497 + * forward all packs from an existing MIDX (without checking
498 + * whether or not they appear in the to_include list).
499 + *
500 + * If we added support for that, these next two conditional
501 + * should be performed independently (likely checking
502 + * to_include before the existing MIDX).
503 + */
504 if (ctx->m && midx_contains_pack(ctx->m, file_name))
505 return;
506 + else if (ctx->to_include &&
507 + !string_list_has_string(ctx->to_include, file_name))
508 + return;
509
510 ALLOC_GROW(ctx->info, ctx->nr + 1, ctx->alloc);
511
@@ -1058,6 +1078,7 @@ cleanup:
1078 }
1079
1080 static int write_midx_internal(const char *object_dir,
1081 + struct string_list *packs_to_include,
1082 struct string_list *packs_to_drop,
1083 const char *preferred_pack_name,
1084 unsigned flags)
@@ -1082,10 +1103,17 @@ static int write_midx_internal(const char *object_dir,
1103 die_errno(_("unable to create leading directories of %s"),
1104 midx_name);
1105
1085 - for (cur = get_multi_pack_index(the_repository); cur; cur = cur->next) {
1086 - if (!strcmp(object_dir, cur->object_dir)) {
1087 - ctx.m = cur;
1088 - break;
1106 + if (!packs_to_include) {
1107 + /*
1108 + * Only reference an existing MIDX when not filtering which
1109 + * packs to include, since all packs and objects are copied
1110 + * blindly from an existing MIDX if one is present.
1111 + */
1112 + for (cur = get_multi_pack_index(the_repository); cur; cur = cur->next) {
1113 + if (!strcmp(object_dir, cur->object_dir)) {
1114 + ctx.m = cur;
1115 + break;
1116 + }
1117 }
1118 }
1119
@@ -1136,10 +1164,13 @@ static int write_midx_internal(const char *object_dir,
1164 else
1165 ctx.progress = NULL;
1166
1167 + ctx.to_include = packs_to_include;
1168 +
1169 for_each_file_in_pack_dir(object_dir, add_pack_to_midx, &ctx);
1170 stop_progress(&ctx.progress);
1171
1142 - if (ctx.m && ctx.nr == ctx.m->num_packs && !packs_to_drop) {
1172 + if ((ctx.m && ctx.nr == ctx.m->num_packs) &&
1173 + !(packs_to_include || packs_to_drop)) {
1174 struct bitmap_index *bitmap_git;
1175 int bitmap_exists;
1176 int want_bitmap = flags & MIDX_WRITE_BITMAP;
@@ -1380,7 +1411,17 @@ int write_midx_file(const char *object_dir,
1411 const char *preferred_pack_name,
1412 unsigned flags)
1413 {
1383 - return write_midx_internal(object_dir, NULL, preferred_pack_name, flags);
1414 + return write_midx_internal(object_dir, NULL, NULL, preferred_pack_name,
1415 + flags);
1416 +}
1417 +
1418 +int write_midx_file_only(const char *object_dir,
1419 + struct string_list *packs_to_include,
1420 + const char *preferred_pack_name,
1421 + unsigned flags)
1422 +{
1423 + return write_midx_internal(object_dir, packs_to_include, NULL,
1424 + preferred_pack_name, flags);
1425 }
1426
1427 struct clear_midx_data {
@@ -1660,7 +1701,7 @@ int expire_midx_packs(struct repository *r, const char *object_dir, unsigned fla
1701 free(count);
1702
1703 if (packs_to_drop.nr) {
1663 - result = write_midx_internal(object_dir, &packs_to_drop, NULL, flags);
1704 + result = write_midx_internal(object_dir, NULL, &packs_to_drop, NULL, flags);
1705 m = NULL;
1706 }
1707
@@ -1851,7 +1892,7 @@ int midx_repack(struct repository *r, const char *object_dir, size_t batch_size,
1892 goto cleanup;
1893 }
1894
1854 - result = write_midx_internal(object_dir, NULL, NULL, flags);
1895 + result = write_midx_internal(object_dir, NULL, NULL, NULL, flags);
1896 m = NULL;
1897
1898 cleanup:
midx.h
+9
@@ -2,6 +2,7 @@
2 #define MIDX_H
3
4 #include "repository.h"
5 +#include "string-list.h"
6
7 struct object_id;
8 struct pack_entry;
@@ -62,6 +63,14 @@ int midx_contains_pack(struct multi_pack_index *m, const char *idx_or_pack_name)
63 int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, int local);
64
65 int write_midx_file(const char *object_dir, const char *preferred_pack_name, unsigned flags);
66 +/*
67 + * Variant of write_midx_file which writes a MIDX containing only the packs
68 + * specified in packs_to_include.
69 + */
70 +int write_midx_file_only(const char *object_dir,
71 + struct string_list *packs_to_include,
72 + const char *preferred_pack_name,
73 + unsigned flags);
74 void clear_midx_file(struct repository *r);
75 int verify_midx_file(struct repository *r, const char *object_dir, unsigned flags);
76 int expire_midx_packs(struct repository *r, const char *object_dir, unsigned flags);