[PATCH v2 00/49] repack: prepare for incremental MIDX-based repacking

Taylor Blau
2025-10-15T22:27:00Z

Note to the maintainer:

* This series has been rebased on to 'master' (which is 4b71b29477
(The seventeenth batch, 2025-10-10) at the time of writing) to
avoid semantic conflicts now that ps/packfile-store has been
merged.

This is a relatively small reroll of my series to clean up the repack
builtin by introducing a repack.h API, which is the first of ~three
series that will implement incremental MIDX/bitmap-based repacking.

A range-diff is included below for convenience, but the changes since
v1 are generally limited to the following:

* Wording tweaks and a couple of minor typo fixes.

* Dropping explicit casts out of 'void *'.

* Clarification in commit "builtin/repack.c: introduce `struct
write_pack_opts`" that additional cleanup follows in the upcoming
patches.

* Marking parts of the new API as const where possible.

* Using 'bool' as the return type and simplifying the implementation
of `write_pack_opts_is_local()`.

* Avoid shadowing "struct write_pack_opts opts" in `cmd_repack()`.

Outside of that, the series is unchanged, and I am hopeful that this
round looks good to reviewers so that we can move on to the more
interesting parts of incremental MIDX/bitmap repacking ;-).

Thanks in advance for your (re-)review!

Taylor Blau (49):
builtin/repack.c: avoid "the_repository" in `cmd_repack()`
builtin/repack.c: avoid "the_repository" in existing packs API
builtin/repack.c: avoid "the_repository" when taking a ref snapshot
builtin/repack.c: avoid "the_repository" when removing packs
builtin/repack.c: avoid "the_repository" when repacking promisor
objects
builtin/repack.c: avoid "the_hash_algo" when deleting packs
builtin/repack.c: avoid "the_hash_algo" in `write_oid()`
builtin/repack: avoid "the_hash_algo" in `repack_promisor_objects()`
builtin/repack.c: avoid "the_hash_algo" in `finish_pack_objects_cmd()`
builtin/repack.c: avoid using `hash_to_hex()` in pack geometry
repack: introduce new compilation unit
builtin/repack.c: pass both pack_objects args to repack_config
repack: move 'delta_base_offset' to 'struct pack_objects_args'
repack: remove 'prepare_pack_objects' from the builtin
builtin/repack.c: rename many 'struct existing_packs' functions
repack: remove 'remove_redundant_pack' from the builtin
builtin/repack.c: pass "packdir" when removing packs
builtin/repack.c: avoid unnecessary numeric casts in existing_packs
repack: remove 'existing_packs' API from the builtin
builtin/repack.c: rename "struct generated_pack_data"
builtin/repack.c: factor out "generated_pack_install"
builtin/repack.c: pass "packtmp" to `generated_pack_populate()`
builtin/repack.c: provide pack locations to `generated_pack_install()`
repack: remove 'generated_pack' API from the builtin
builtin/repack.c: pass "packtmp" to `repack_promisor_objects()`
builtin/repack.c: remove "repack_promisor_objects()" from the builtin
builtin/repack.c: rename various pack_geometry functions
builtin/repack.c: pass 'pack_kept_objects' to `pack_geometry_init()`
builtin/repack.c: pass 'packdir' to `pack_geometry_remove_redundant()`
repack: remove pack_geometry API from the builtin
builtin/repack.c: remove ref snapshotting from builtin
builtin/repack.c: extract opts struct for
'write_midx_included_packs()'
builtin/repack.c: use a string_list for 'midx_pack_names'
repack: keep track of MIDX pack names using existing_packs
builtin/repack.c: reorder `remove_redundant_bitmaps()`
builtin/repack.c: inline `remove_redundant_bitmaps()`
builtin/repack.c: pass `repack_write_midx_opts` to
`midx_included_packs`
builtin/repack.c: inline packs within `write_midx_included_packs()`
repack: 'write_midx_included_packs' API from the builtin
builtin/repack.c: introduce `struct write_pack_opts`
builtin/repack.c: use `write_pack_opts` within `write_cruft_pack()`
repack: move `find_pack_prefix()` out of the builtin
repack: extract `write_pack_opts_is_local()`
builtin/repack.c: pass `write_pack_opts` to
`finish_pack_objects_cmd()`
repack: move `finish_pack_objects_cmd()` out of the builtin
repack: move `pack_kept_objects` to `struct pack_objects_args`
repack: move `write_filtered_pack()` out of the builtin
repack: move `write_cruft_pack()` out of the builtin
builtin/repack.c: clean up unused `#include`s

Makefile | 6 +
builtin/repack.c | 1356 +++------------------------------------------
meson.build | 6 +
repack-cruft.c | 99 ++++
repack-filtered.c | 51 ++
repack-geometry.c | 233 ++++++++
repack-midx.c | 372 +++++++++++++
repack-promisor.c | 102 ++++
repack.c | 360 ++++++++++++
repack.h | 146 +++++
10 files changed, 1467 insertions(+), 1264 deletions(-)
create mode 100644 repack-cruft.c
create mode 100644 repack-filtered.c
create mode 100644 repack-geometry.c
create mode 100644 repack-midx.c
create mode 100644 repack-promisor.c
create mode 100644 repack.c
create mode 100644 repack.h

Range-diff against v1:
1: aa03aea8ed = 1: fc2b686c49 builtin/repack.c: avoid "the_repository" in `cmd_repack()`
2: 664a67c936 = 2: 14a65d7c6d builtin/repack.c: avoid "the_repository" in existing packs API
3: 866e43b0cd = 3: ff72cd499b builtin/repack.c: avoid "the_repository" when taking a ref snapshot
4: f404dfa34f = 4: 75f23ba211 builtin/repack.c: avoid "the_repository" when removing packs
5: 6190eeb066 = 5: 0914ca113f builtin/repack.c: avoid "the_repository" when repacking promisor objects
6: 2f97882ace = 6: 238f3d87a0 builtin/repack.c: avoid "the_hash_algo" when deleting packs
7: 37a7dea848 = 7: ca3c8a782a builtin/repack.c: avoid "the_hash_algo" in `write_oid()`
8: f5a87f2a65 = 8: 34b503618a builtin/repack: avoid "the_hash_algo" in `repack_promisor_objects()`
9: f16dfbf0c7 = 9: cd43a60620 builtin/repack.c: avoid "the_hash_algo" in `finish_pack_objects_cmd()`
10: de4886466c = 10: c6787c865d builtin/repack.c: avoid using `hash_to_hex()` in pack geometry
11: fe3328eb3d = 11: 87f2903e75 repack: introduce new compilation unit
12: 75386eed60 = 12: a812bd3dcb builtin/repack.c: pass both pack_objects args to repack_config
13: 06347b6ab2 = 13: f2d1fa51e3 repack: move 'delta_base_offset' to 'struct pack_objects_args'
14: 2d9022385d = 14: 0c32c3c9b6 repack: remove 'prepare_pack_objects' from the builtin
15: 02e26f78ac = 15: a9767dc42d builtin/repack.c: rename many 'struct existing_packs' functions
16: d0a40e8e57 = 16: 4edbcb5893 repack: remove 'remove_redundant_pack' from the builtin
17: df75c3130b = 17: 4e2a152ebb builtin/repack.c: pass "packdir" when removing packs
18: f413f958eb = 18: 46aa154b76 builtin/repack.c: avoid unnecessary numeric casts in existing_packs
19: ae267fcc82 ! 19: 0c6dea2800 repack: remove 'existing_packs' API from the builtin
@@ Commit message
end of a repack operation.

Now that the prerequisite refactoring is complete, this API is isolated
- enough that it can be moved out to repack.ch and removed from the
+ enough that it can be moved out to repack.[ch] and removed from the
builtin entirely.

As a result, some of its functions become static within repack.c,
20: ee3e1233f5 = 20: 53d5b1053f builtin/repack.c: rename "struct generated_pack_data"
21: 96d27261e7 ! 21: 196b92d052 builtin/repack.c: factor our "generated_pack_install"
@@ Metadata
Author: Taylor Blau <me@ttaylorr.com>

## Commit message ##
- builtin/repack.c: factor our "generated_pack_install"
+ builtin/repack.c: factor out "generated_pack_install"

Once all new packs are known to exist, 'repack' installs their contents
from their temporary location into their permanent one. This is a
@@ builtin/repack.c: int cmd_repack(int argc,
- }
- }
+ for_each_string_list_item(item, &names)
-+ generated_pack_install((struct generated_pack *)item->util,
-+ item->string);
++ generated_pack_install(item->util, item->string);
/* End of pack replacement. */

if (delete_redundant && pack_everything & ALL_INTO_ONE)
22: ab0dc66683 = 22: acd9a83ed0 builtin/repack.c: pass "packtmp" to `generated_pack_populate()`
23: e9d525d83a ! 23: 2b81a26a84 builtin/repack.c: provide pack locations to `generated_pack_install()`
@@ builtin/repack.c: static int generated_pack_has_ext(const struct generated_pack
int ext;
for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
@@ builtin/repack.c: int cmd_repack(int argc,
+ * Ok we have prepared all new packfiles.
*/
for_each_string_list_item(item, &names)
- generated_pack_install((struct generated_pack *)item->util,
-- item->string);
-+ item->string, packdir, packtmp);
+- generated_pack_install(item->util, item->string);
++ generated_pack_install(item->util, item->string, packdir,
++ packtmp);
/* End of pack replacement. */

if (delete_redundant && pack_everything & ALL_INTO_ONE)
24: 9979b77979 = 24: 69003f4561 repack: remove 'generated_pack' API from the builtin
25: 67effcb4ea = 25: ca030322cf builtin/repack.c: pass "packtmp" to `repack_promisor_objects()`
26: 3ba6e86f61 ! 26: 1050b856a5 builtin/repack.c: remove "repack_promisor_objects()" from the builtin
@@ repack-promisor.c (new)
@@
+#include "git-compat-util.h"
+#include "repack.h"
-+#include "run-command.h"
+#include "hex.h"
-+#include "repository.h"
++#include "pack.h"
+#include "packfile.h"
+#include "path.h"
-+#include "pack.h"
++#include "repository.h"
++#include "run-command.h"
+
+struct write_oid_context {
+ struct child_process *cmd;
27: dd67366476 ! 27: 0b2fa0cf62 builtin/repack.c: rename various pack_geometry functions
@@ Commit message
builtin/repack.c: rename various pack_geometry functions

Rename functions which work with 'struct pack_geometry' to begin with
- "pack_geometry_".
+ "pack_geometry_". While we're at it, change `free_pack_geometry()` to
+ instead be named `pack_geometry_release()` to match our conventions, and
+ make clear that that function frees the contents of the struct, not the
+ memory allocated to hold the struct itself.

Signed-off-by: Taylor Blau <me@ttaylorr.com>

28: 8408fd8474 = 28: a3d99c4852 builtin/repack.c: pass 'pack_kept_objects' to `pack_geometry_init()`
29: 76be98b386 = 29: 0a2a72ea22 builtin/repack.c: pass 'packdir' to `pack_geometry_remove_redundant()`
30: 54a2feaea9 ! 30: 9172e9a515 repack: remove pack_geometry API from the builtin
@@ repack-geometry.c (new)
+
+#include "git-compat-util.h"
+#include "repack.h"
++#include "repository.h"
+#include "hex.h"
+#include "packfile.h"
+
31: 06ca4ab5b7 = 31: 5b15d83e65 builtin/repack.c: remove ref snapshotting from builtin
32: 3b7e204a40 = 32: 077f06c935 builtin/repack.c: extract opts struct for 'write_midx_included_packs()'
33: 8844529759 = 33: 40ce496de2 builtin/repack.c: use a string_list for 'midx_pack_names'
34: ccf2c6a517 = 34: ec3a8a7dd2 repack: keep track of MIDX pack names using existing_packs
35: 85d229fff5 = 35: 8042860b26 builtin/repack.c: reorder `remove_redundant_bitmaps()`
36: 2bf732009a = 36: af06f60e63 builtin/repack.c: inline `remove_redundant_bitmaps()`
37: 60659a7549 = 37: 668f4edc9e builtin/repack.c: pass `repack_write_midx_opts` to `midx_included_packs`
38: c2c7ca9f9e ! 38: 5bd43e96f2 builtin/repack.c: inline packs within `write_midx_included_packs()`
@@ Commit message
write_midx_included_packs(&included_packs, ...);
}

- in the future, let's have each function which writes a MIDX be
+ in the future, let's have each function that writes a MIDX be
responsible for itself computing the list of included packs. Inline the
declaration and initialization of `included_packs` into the
`write_midx_included_packs()` function itself, and repeat that pattern
39: c28891443b = 39: 794122266d repack: 'write_midx_included_packs' API from the builtin
40: 1091096186 ! 40: 0cb6e78856 builtin/repack.c: introduce `struct write_pack_opts`
@@ Commit message
of the same type, and provide a unified interface for the two functions
mentioned earlier.

+ (Note that "pack_prefix" can be derived on the fly as a function of
+ "packdir" and "packtmp", making it unnecessary to store "pack_prefix"
+ explicitly. This commit ignores that potential cleanup in the name of
+ doing as few things as possible, but a later commit will make that
+ change.)
+
Signed-off-by: Taylor Blau <me@ttaylorr.com>

## builtin/repack.c ##
@@ builtin/repack.c: static int finish_pack_objects_cmd(const struct git_hash_algo
-static int write_filtered_pack(const struct pack_objects_args *args,
- const char *destination,
- const char *pack_prefix,
-+static int write_filtered_pack(struct write_pack_opts *opts,
++static int write_filtered_pack(const struct write_pack_opts *opts,
struct existing_packs *existing,
struct string_list *names)
{
41: 7826afc173 ! 41: 1a9b578fdd builtin/repack.c: use `write_pack_opts` within `write_cruft_pack()`
@@ builtin/repack.c: static void combine_small_cruft_packs(FILE *in, size_t combine
-static int write_cruft_pack(const struct pack_objects_args *args,
- const char *destination,
- const char *pack_prefix,
-+static int write_cruft_pack(struct write_pack_opts *opts,
++static int write_cruft_pack(const struct write_pack_opts *opts,
const char *cruft_expiration,
unsigned long combine_cruft_below_size,
struct string_list *names,
42: c50ffce078 ! 42: 43116b8942 repack: move `find_pack_prefix()` out of the builtin
@@ Commit message
Signed-off-by: Taylor Blau <me@ttaylorr.com>

## builtin/repack.c ##
-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,
const char *caret;
const char *scratch;
int local = skip_prefix(opts->destination, opts->packdir, &scratch);
@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,

prepare_pack_objects(&cmd, opts->po_args, opts->destination);

-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,
*/
in = xfdopen(cmd.in, "w");
for_each_string_list_item(item, names)
@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
for_each_string_list_item(item, &existing->non_kept_packs)
fprintf(in, "%s.pack\n", item->string);
for_each_string_list_item(item, &existing->cruft_packs)
-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
int ret;
const char *scratch;
int local = skip_prefix(opts->destination, opts->packdir, &scratch);
@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,

prepare_pack_objects(&cmd, opts->po_args, opts->destination);

-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
*/
in = xfdopen(cmd.in, "w");
for_each_string_list_item(item, names)
@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
if (combine_cruft_below_size && !cruft_expiration) {
combine_small_cruft_packs(in, combine_cruft_below_size,
existing);
-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
local);
}

@@ repack.c: void repack_remove_redundant_pack(struct repository *repo, const char
strbuf_release(&buf);
}

-+const char *write_pack_opts_pack_prefix(struct write_pack_opts *opts)
++const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts)
+{
+ const char *pack_prefix;
+ if (!skip_prefix(opts->packtmp, opts->packdir, &pack_prefix))
@@ repack.h: void repack_remove_redundant_pack(struct repository *repo, const char
const char *packtmp;
};

-+const char *write_pack_opts_pack_prefix(struct write_pack_opts *opts);
++const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts);
+
struct repository;
struct packed_git;
43: 1fbe3d0d7f ! 43: 5e3b615993 repack: extract `write_pack_opts_is_local()`
@@ Commit message

Extract that function and make it visible within the repack.h API, and
use it within both `write_cruft_pack()` and `write_filtered_pack()`.
+ While we're at it, match our modern conventions by returning a "bool"
+ instead of "int", and use `starts_with()` instead of `skip_prefix()` to
+ avoid storing the dummy "scratch" variable.

The remaining duplication (that is, that both `write_cruft_pack()` and
`write_filtered_pack()` still both call `write_pack_opts_is_local()`)
@@ Commit message
Signed-off-by: Taylor Blau <me@ttaylorr.com>

## builtin/repack.c ##
-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,
FILE *in;
int ret;
const char *caret;
- const char *scratch;
- int local = skip_prefix(opts->destination, opts->packdir, &scratch);
-+ int local = write_pack_opts_is_local(opts);
++ bool local = write_pack_opts_is_local(opts);
const char *pack_prefix = write_pack_opts_pack_prefix(opts);

prepare_pack_objects(&cmd, opts->po_args, opts->destination);
-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
struct string_list_item *item;
FILE *in;
int ret;
- const char *scratch;
- int local = skip_prefix(opts->destination, opts->packdir, &scratch);
-+ int local = write_pack_opts_is_local(opts);
++ bool local = write_pack_opts_is_local(opts);
const char *pack_prefix = write_pack_opts_pack_prefix(opts);

prepare_pack_objects(&cmd, opts->po_args, opts->destination);

## repack.c ##
-@@ repack.c: const char *write_pack_opts_pack_prefix(struct write_pack_opts *opts)
+@@ repack.c: const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts)
return pack_prefix;
}

-+int write_pack_opts_is_local(struct write_pack_opts *opts)
++bool write_pack_opts_is_local(const struct write_pack_opts *opts)
+{
-+ const char *scratch;
-+ return skip_prefix(opts->destination, opts->packdir, &scratch);
++ return starts_with(opts->destination, opts->packdir);
+}
+
#define DELETE_PACK 1
@@ repack.h
@@ repack.h: struct write_pack_opts {
};

- const char *write_pack_opts_pack_prefix(struct write_pack_opts *opts);
-+int write_pack_opts_is_local(struct write_pack_opts *opts);
+ const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts);
++bool write_pack_opts_is_local(const struct write_pack_opts *opts);

struct repository;
struct packed_git;
44: 11f78993f1 ! 44: fcbe44d8bb builtin/repack.c: pass `write_pack_opts` to `finish_pack_objects_cmd()`
@@ builtin/repack.c: static int repack_config(const char *var, const char *value,
}

static int finish_pack_objects_cmd(const struct git_hash_algo *algop,
-+ struct write_pack_opts *opts,
++ const struct write_pack_opts *opts,
struct child_process *cmd,
- struct string_list *names,
- int local)
+ struct string_list *names)
{
FILE *out;
-+ int local = write_pack_opts_is_local(opts);
++ bool local = write_pack_opts_is_local(opts);
struct strbuf line = STRBUF_INIT;

out = xfdopen(cmd->out, "r");
@@ builtin/repack.c: static int finish_pack_objects_cmd(const struct git_hash_algo
}
}
fclose(out);
-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,
FILE *in;
int ret;
const char *caret;
-- int local = write_pack_opts_is_local(opts);
+- bool local = write_pack_opts_is_local(opts);
const char *pack_prefix = write_pack_opts_pack_prefix(opts);

prepare_pack_objects(&cmd, opts->po_args, opts->destination);
-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,
fprintf(in, "%s%s.pack\n", caret, item->string);
fclose(in);

@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
}

static void combine_small_cruft_packs(FILE *in, size_t combine_cruft_below_size,
-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
struct string_list_item *item;
FILE *in;
int ret;
-- int local = write_pack_opts_is_local(opts);
+- bool local = write_pack_opts_is_local(opts);
const char *pack_prefix = write_pack_opts_pack_prefix(opts);

prepare_pack_objects(&cmd, opts->po_args, opts->destination);
-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
fprintf(in, "%s.pack\n", item->string);
fclose(in);

@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
}

int cmd_repack(int argc,
-@@ builtin/repack.c: int cmd_repack(int argc,
- struct existing_packs existing = EXISTING_PACKS_INIT;
- struct pack_geometry geometry = { 0 };
- struct tempfile *refs_snapshot = NULL;
-+ struct write_pack_opts opts = { 0 };
- int i, ret;
- int show_progress;
-
@@ builtin/repack.c: int cmd_repack(int argc,
fclose(in);
}

- ret = finish_pack_objects_cmd(repo->hash_algo, &cmd, &names, 1);
-+ opts.packdir = packdir;
-+ opts.destination = packdir;
-+ opts.packtmp = packtmp;
-+ ret = finish_pack_objects_cmd(repo->hash_algo, &opts, &cmd, &names);
- if (ret)
- goto cleanup;
+- if (ret)
+- goto cleanup;
++ {
++ struct write_pack_opts opts = {
++ .packdir = packdir,
++ .destination = packdir,
++ .packtmp = packtmp,
++ };
++ ret = finish_pack_objects_cmd(repo->hash_algo, &opts, &cmd,
++ &names);
++ if (ret)
++ goto cleanup;
++ }

+ if (!names.nr) {
+ if (!po_args.quiet)
45: a38d14e411 ! 45: 244260c6ab repack: move `finish_pack_objects_cmd()` out of the builtin
@@ builtin/repack.c: static int repack_config(const char *var, const char *value,
}

-static int finish_pack_objects_cmd(const struct git_hash_algo *algop,
-- struct write_pack_opts *opts,
+- const struct write_pack_opts *opts,
- struct child_process *cmd,
- struct string_list *names)
-{
- FILE *out;
-- int local = write_pack_opts_is_local(opts);
+- bool local = write_pack_opts_is_local(opts);
- struct strbuf line = STRBUF_INIT;
-
- out = xfdopen(cmd->out, "r");
@@ builtin/repack.c: static int repack_config(const char *var, const char *value,
- return finish_command(cmd);
-}
-
- static int write_filtered_pack(struct write_pack_opts *opts,
+ static int write_filtered_pack(const struct write_pack_opts *opts,
struct existing_packs *existing,
struct string_list *names)

## repack.c ##
-@@ repack.c: int write_pack_opts_is_local(struct write_pack_opts *opts)
- return skip_prefix(opts->destination, opts->packdir, &scratch);
+@@ repack.c: bool write_pack_opts_is_local(const struct write_pack_opts *opts)
+ return starts_with(opts->destination, opts->packdir);
}

+int finish_pack_objects_cmd(const struct git_hash_algo *algop,
-+ struct write_pack_opts *opts,
++ const struct write_pack_opts *opts,
+ struct child_process *cmd,
+ struct string_list *names)
+{
+ FILE *out;
-+ int local = write_pack_opts_is_local(opts);
++ bool local = write_pack_opts_is_local(opts);
+ struct strbuf line = STRBUF_INIT;
+
+ out = xfdopen(cmd->out, "r");
@@ repack.c: int write_pack_opts_is_local(struct write_pack_opts *opts)

## repack.h ##
@@ repack.h: struct write_pack_opts {
- const char *write_pack_opts_pack_prefix(struct write_pack_opts *opts);
- int write_pack_opts_is_local(struct write_pack_opts *opts);
+ const char *write_pack_opts_pack_prefix(const struct write_pack_opts *opts);
+ bool write_pack_opts_is_local(const struct write_pack_opts *opts);

+int finish_pack_objects_cmd(const struct git_hash_algo *algop,
-+ struct write_pack_opts *opts,
++ const struct write_pack_opts *opts,
+ struct child_process *cmd,
+ struct string_list *names);
+
46: 2d9a879bb0 ! 46: dbc317af27 repack: move `pack_kept_objects` to `struct pack_objects_args`
@@ builtin/repack.c: static int repack_config(const char *var, const char *value,
return 0;
}
if (!strcmp(var, "repack.writebitmaps") ||
-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,

strvec_push(&cmd.args, "--stdin-packs");

@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
for_each_string_list_item(item, &existing->kept_packs)
strvec_pushf(&cmd.args, "--keep-pack=%s", item->string);

-@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_filtered_pack(const struct write_pack_opts *opts,
fprintf(in, "%s.pack\n", item->string);
for_each_string_list_item(item, &existing->cruft_packs)
fprintf(in, "%s.pack\n", item->string);
@@ builtin/repack.c: static int write_filtered_pack(struct write_pack_opts *opts,
for_each_string_list_item(item, &existing->kept_packs)
fprintf(in, "%s%s.pack\n", caret, item->string);
fclose(in);
-@@ builtin/repack.c: static int write_cruft_pack(struct write_pack_opts *opts,
+@@ builtin/repack.c: static int write_cruft_pack(const struct write_pack_opts *opts,
strvec_pushf(&cmd.args, "--cruft-expiration=%s",
cruft_expiration);

47: d0df139717 ! 47: 7523345056 repack: move `write_filtered_pack()` out of the builtin
@@ builtin/repack.c: static int repack_config(const char *var, const char *value,
return git_default_config(var, value, ctx, cb);
}

--static int write_filtered_pack(struct write_pack_opts *opts,
+-static int write_filtered_pack(const struct write_pack_opts *opts,
- struct existing_packs *existing,
- struct string_list *names)
-{
@@ repack-filtered.c (new)
+#include "run-command.h"
+#include "string-list.h"
+
-+int write_filtered_pack(struct write_pack_opts *opts,
++int write_filtered_pack(const struct write_pack_opts *opts,
+ struct existing_packs *existing,
+ struct string_list *names)
+{
@@ repack.h: struct repack_write_midx_opts {
void midx_snapshot_refs(struct repository *repo, struct tempfile *f);
int write_midx_included_packs(struct repack_write_midx_opts *opts);

-+int write_filtered_pack(struct write_pack_opts *opts,
++int write_filtered_pack(const struct write_pack_opts *opts,
+ struct existing_packs *existing,
+ struct string_list *names);
+
48: 4c6ec504e3 ! 48: 567ccd3d3e repack: move `write_cruft_pack()` out of the builtin
@@ builtin/repack.c: static int repack_config(const char *var, const char *value,
- strbuf_release(&buf);
-}
-
--static int write_cruft_pack(struct write_pack_opts *opts,
+-static int write_cruft_pack(const struct write_pack_opts *opts,
- const char *cruft_expiration,
- unsigned long combine_cruft_below_size,
- struct string_list *names,
@@ repack-cruft.c (new)
+ strbuf_release(&buf);
+}
+
-+int write_cruft_pack(struct write_pack_opts *opts,
++int write_cruft_pack(const struct write_pack_opts *opts,
+ const char *cruft_expiration,
+ unsigned long combine_cruft_below_size,
+ struct string_list *names,
@@ repack-cruft.c (new)
+}

## repack.h ##
-@@ repack.h: int write_filtered_pack(struct write_pack_opts *opts,
+@@ repack.h: int write_filtered_pack(const struct write_pack_opts *opts,
struct existing_packs *existing,
struct string_list *names);

-+int write_cruft_pack(struct write_pack_opts *opts,
++int write_cruft_pack(const struct write_pack_opts *opts,
+ const char *cruft_expiration,
+ unsigned long combine_cruft_below_size,
+ struct string_list *names,
49: 16eca91f2c = 49: b7178565ac builtin/repack.c: clean up unused `#include`s

base-commit: 4b71b294773cc4f7fe48ec3a70079aa8783f373d
--
2.51.0.540.ga7423965ad8