builtin/repack.c: remove "repack_promisor_objects()" from the builtin
Now that we have properly factored the portion of the builtin which is responsible for repacking promisor objects, we can move that function (and associated dependencies) out of the builtin entirely. Similar to previous extractions, this function is declared in repack.h, but implemented in a separate repack-promisor.c file. This is done to separate promisor-specific repacking functionality from generic repack utilities (like "existing_packs", and "generated_pack" APIs). Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Taylor Blau committed
Oct 15, 2025 at 18:28 UTC
29e935515d1b49fa08b2781371625e5c55d2bf13
5 files changed
+108
-95
Makefile
+1
@@ -1137,6 +1137,7 @@ LIB_OBJS += refs/ref-cache.o
1137
LIB_OBJS += refspec.o
1138
LIB_OBJS += remote.o
1139
LIB_OBJS += repack.o
1140
+LIB_OBJS += repack-promisor.o
1141
LIB_OBJS += replace-object.o
1142
LIB_OBJS += repo-settings.o
1143
LIB_OBJS += repository.o
builtin/repack.c
-95
@@ -107,101 +107,6 @@ static int repack_config(const char *var, const char *value,
107
return git_default_config(var, value, ctx, cb);
108
}
109
110
-struct write_oid_context {
111
- struct child_process *cmd;
112
- const struct git_hash_algo *algop;
113
-};
114
-
115
-/*
116
- * Write oid to the given struct child_process's stdin, starting it first if
117
- * necessary.
118
- */
119
-static int write_oid(const struct object_id *oid,
120
- struct packed_git *pack UNUSED,
121
- uint32_t pos UNUSED, void *data)
122
-{
123
- struct write_oid_context *ctx = data;
124
- struct child_process *cmd = ctx->cmd;
125
-
126
- if (cmd->in == -1) {
127
- if (start_command(cmd))
128
- die(_("could not start pack-objects to repack promisor objects"));
129
- }
130
-
131
- if (write_in_full(cmd->in, oid_to_hex(oid), ctx->algop->hexsz) < 0 ||
132
- write_in_full(cmd->in, "\n", 1) < 0)
133
- die(_("failed to feed promisor objects to pack-objects"));
134
- return 0;
135
-}
136
-
137
-static void repack_promisor_objects(struct repository *repo,
138
- const struct pack_objects_args *args,
139
- struct string_list *names,
140
- const char *packtmp)
141
-{
142
- struct write_oid_context ctx;
143
- struct child_process cmd = CHILD_PROCESS_INIT;
144
- FILE *out;
145
- struct strbuf line = STRBUF_INIT;
146
-
147
- prepare_pack_objects(&cmd, args, packtmp);
148
- cmd.in = -1;
149
-
150
- /*
151
- * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
152
- * hints may result in suboptimal deltas in the resulting pack. See if
153
- * the OIDs can be sent with fake paths such that pack-objects can use a
154
- * {type -> existing pack order} ordering when computing deltas instead
155
- * of a {type -> size} ordering, which may produce better deltas.
156
- */
157
- ctx.cmd = &cmd;
158
- ctx.algop = repo->hash_algo;
159
- for_each_packed_object(repo, write_oid, &ctx,
160
- FOR_EACH_OBJECT_PROMISOR_ONLY);
161
-
162
- if (cmd.in == -1) {
163
- /* No packed objects; cmd was never started */
164
- child_process_clear(&cmd);
165
- return;
166
- }
167
-
168
- close(cmd.in);
169
-
170
- out = xfdopen(cmd.out, "r");
171
- while (strbuf_getline_lf(&line, out) != EOF) {
172
- struct string_list_item *item;
173
- char *promisor_name;
174
-
175
- if (line.len != repo->hash_algo->hexsz)
176
- die(_("repack: Expecting full hex object ID lines only from pack-objects."));
177
- item = string_list_append(names, line.buf);
178
-
179
- /*
180
- * pack-objects creates the .pack and .idx files, but not the
181
- * .promisor file. Create the .promisor file, which is empty.
182
- *
183
- * NEEDSWORK: fetch-pack sometimes generates non-empty
184
- * .promisor files containing the ref names and associated
185
- * hashes at the point of generation of the corresponding
186
- * packfile, but this would not preserve their contents. Maybe
187
- * concatenate the contents of all .promisor files instead of
188
- * just creating a new empty file.
189
- */
190
- promisor_name = mkpathdup("%s-%s.promisor", packtmp,
191
- line.buf);
192
- write_promisor_file(promisor_name, NULL, 0);
193
-
194
- item->util = generated_pack_populate(item->string, packtmp);
195
-
196
- free(promisor_name);
197
- }
198
-
199
- fclose(out);
200
- if (finish_command(&cmd))
201
- die(_("could not finish pack-objects to repack promisor objects"));
202
- strbuf_release(&line);
203
-}
204
-
110
struct pack_geometry {
111
struct packed_git **pack;
112
uint32_t pack_nr, pack_alloc;
meson.build
+1
@@ -463,6 +463,7 @@ libgit_sources = [
463
'reftable/writer.c',
464
'remote.c',
465
'repack.c',
466
+ 'repack-promisor.c',
467
'replace-object.c',
468
'repo-settings.c',
469
'repository.c',
repack-promisor.c
new
+102
@@ -0,0 +1,102 @@
1
+#include "git-compat-util.h"
2
+#include "repack.h"
3
+#include "hex.h"
4
+#include "pack.h"
5
+#include "packfile.h"
6
+#include "path.h"
7
+#include "repository.h"
8
+#include "run-command.h"
9
+
10
+struct write_oid_context {
11
+ struct child_process *cmd;
12
+ const struct git_hash_algo *algop;
13
+};
14
+
15
+/*
16
+ * Write oid to the given struct child_process's stdin, starting it first if
17
+ * necessary.
18
+ */
19
+static int write_oid(const struct object_id *oid,
20
+ struct packed_git *pack UNUSED,
21
+ uint32_t pos UNUSED, void *data)
22
+{
23
+ struct write_oid_context *ctx = data;
24
+ struct child_process *cmd = ctx->cmd;
25
+
26
+ if (cmd->in == -1) {
27
+ if (start_command(cmd))
28
+ die(_("could not start pack-objects to repack promisor objects"));
29
+ }
30
+
31
+ if (write_in_full(cmd->in, oid_to_hex(oid), ctx->algop->hexsz) < 0 ||
32
+ write_in_full(cmd->in, "\n", 1) < 0)
33
+ die(_("failed to feed promisor objects to pack-objects"));
34
+ return 0;
35
+}
36
+
37
+void repack_promisor_objects(struct repository *repo,
38
+ const struct pack_objects_args *args,
39
+ struct string_list *names, const char *packtmp)
40
+{
41
+ struct write_oid_context ctx;
42
+ struct child_process cmd = CHILD_PROCESS_INIT;
43
+ FILE *out;
44
+ struct strbuf line = STRBUF_INIT;
45
+
46
+ prepare_pack_objects(&cmd, args, packtmp);
47
+ cmd.in = -1;
48
+
49
+ /*
50
+ * NEEDSWORK: Giving pack-objects only the OIDs without any ordering
51
+ * hints may result in suboptimal deltas in the resulting pack. See if
52
+ * the OIDs can be sent with fake paths such that pack-objects can use a
53
+ * {type -> existing pack order} ordering when computing deltas instead
54
+ * of a {type -> size} ordering, which may produce better deltas.
55
+ */
56
+ ctx.cmd = &cmd;
57
+ ctx.algop = repo->hash_algo;
58
+ for_each_packed_object(repo, write_oid, &ctx,
59
+ FOR_EACH_OBJECT_PROMISOR_ONLY);
60
+
61
+ if (cmd.in == -1) {
62
+ /* No packed objects; cmd was never started */
63
+ child_process_clear(&cmd);
64
+ return;
65
+ }
66
+
67
+ close(cmd.in);
68
+
69
+ out = xfdopen(cmd.out, "r");
70
+ while (strbuf_getline_lf(&line, out) != EOF) {
71
+ struct string_list_item *item;
72
+ char *promisor_name;
73
+
74
+ if (line.len != repo->hash_algo->hexsz)
75
+ die(_("repack: Expecting full hex object ID lines only from pack-objects."));
76
+ item = string_list_append(names, line.buf);
77
+
78
+ /*
79
+ * pack-objects creates the .pack and .idx files, but not the
80
+ * .promisor file. Create the .promisor file, which is empty.
81
+ *
82
+ * NEEDSWORK: fetch-pack sometimes generates non-empty
83
+ * .promisor files containing the ref names and associated
84
+ * hashes at the point of generation of the corresponding
85
+ * packfile, but this would not preserve their contents. Maybe
86
+ * concatenate the contents of all .promisor files instead of
87
+ * just creating a new empty file.
88
+ */
89
+ promisor_name = mkpathdup("%s-%s.promisor", packtmp,
90
+ line.buf);
91
+ write_promisor_file(promisor_name, NULL, 0);
92
+
93
+ item->util = generated_pack_populate(item->string, packtmp);
94
+
95
+ free(promisor_name);
96
+ }
97
+
98
+ fclose(out);
99
+ if (finish_command(&cmd))
100
+ die(_("could not finish pack-objects to repack promisor objects"));
101
+ strbuf_release(&line);
102
+}
repack.h
+4
@@ -74,4 +74,8 @@ int generated_pack_has_ext(const struct generated_pack *pack, const char *ext);
74
void generated_pack_install(struct generated_pack *pack, const char *name,
75
const char *packdir, const char *packtmp);
76
77
+void repack_promisor_objects(struct repository *repo,
78
+ const struct pack_objects_args *args,
79
+ struct string_list *names, const char *packtmp);
80
+
81
#endif /* REPACK_H */