Skip to content

Commit 62d3fa0

Browse files
ttaylorrgitster
authored andcommitted
repack: remove pack_geometry API from the builtin
Now that the pack_geometry API is fully factored and isolated from the rest of the builtin, declare it within repack.h and move its implementation to "repack-geometry.c" as a separate component. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent b2ebeed commit 62d3fa0

5 files changed

Lines changed: 256 additions & 235 deletions

File tree

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,7 @@ LIB_OBJS += refs/ref-cache.o
11371137
LIB_OBJS += refspec.o
11381138
LIB_OBJS += remote.o
11391139
LIB_OBJS += repack.o
1140+
LIB_OBJS += repack-geometry.o
11401141
LIB_OBJS += repack-promisor.o
11411142
LIB_OBJS += replace-object.o
11421143
LIB_OBJS += repo-settings.o

builtin/repack.c

Lines changed: 0 additions & 235 deletions
Original file line numberDiff line numberDiff line change
@@ -107,241 +107,6 @@ static int repack_config(const char *var, const char *value,
107107
return git_default_config(var, value, ctx, cb);
108108
}
109109

110-
struct pack_geometry {
111-
struct packed_git **pack;
112-
uint32_t pack_nr, pack_alloc;
113-
uint32_t split;
114-
115-
int split_factor;
116-
};
117-
118-
static uint32_t pack_geometry_weight(struct packed_git *p)
119-
{
120-
if (open_pack_index(p))
121-
die(_("cannot open index for %s"), p->pack_name);
122-
return p->num_objects;
123-
}
124-
125-
static int pack_geometry_cmp(const void *va, const void *vb)
126-
{
127-
uint32_t aw = pack_geometry_weight(*(struct packed_git **)va),
128-
bw = pack_geometry_weight(*(struct packed_git **)vb);
129-
130-
if (aw < bw)
131-
return -1;
132-
if (aw > bw)
133-
return 1;
134-
return 0;
135-
}
136-
137-
static void pack_geometry_init(struct pack_geometry *geometry,
138-
struct existing_packs *existing,
139-
const struct pack_objects_args *args,
140-
int pack_kept_objects)
141-
{
142-
struct packfile_store *packs = existing->repo->objects->packfiles;
143-
struct packed_git *p;
144-
struct strbuf buf = STRBUF_INIT;
145-
146-
for (p = packfile_store_get_all_packs(packs); p; p = p->next) {
147-
if (args->local && !p->pack_local)
148-
/*
149-
* When asked to only repack local packfiles we skip
150-
* over any packfiles that are borrowed from alternate
151-
* object directories.
152-
*/
153-
continue;
154-
155-
if (!pack_kept_objects) {
156-
/*
157-
* Any pack that has its pack_keep bit set will
158-
* appear in existing->kept_packs below, but
159-
* this saves us from doing a more expensive
160-
* check.
161-
*/
162-
if (p->pack_keep)
163-
continue;
164-
165-
/*
166-
* The pack may be kept via the --keep-pack
167-
* option; check 'existing->kept_packs' to
168-
* determine whether to ignore it.
169-
*/
170-
strbuf_reset(&buf);
171-
strbuf_addstr(&buf, pack_basename(p));
172-
strbuf_strip_suffix(&buf, ".pack");
173-
174-
if (string_list_has_string(&existing->kept_packs, buf.buf))
175-
continue;
176-
}
177-
if (p->is_cruft)
178-
continue;
179-
180-
ALLOC_GROW(geometry->pack,
181-
geometry->pack_nr + 1,
182-
geometry->pack_alloc);
183-
184-
geometry->pack[geometry->pack_nr] = p;
185-
geometry->pack_nr++;
186-
}
187-
188-
QSORT(geometry->pack, geometry->pack_nr, pack_geometry_cmp);
189-
strbuf_release(&buf);
190-
}
191-
192-
static void pack_geometry_split(struct pack_geometry *geometry)
193-
{
194-
uint32_t i;
195-
uint32_t split;
196-
off_t total_size = 0;
197-
198-
if (!geometry->pack_nr) {
199-
geometry->split = geometry->pack_nr;
200-
return;
201-
}
202-
203-
/*
204-
* First, count the number of packs (in descending order of size) which
205-
* already form a geometric progression.
206-
*/
207-
for (i = geometry->pack_nr - 1; i > 0; i--) {
208-
struct packed_git *ours = geometry->pack[i];
209-
struct packed_git *prev = geometry->pack[i - 1];
210-
211-
if (unsigned_mult_overflows(geometry->split_factor,
212-
pack_geometry_weight(prev)))
213-
die(_("pack %s too large to consider in geometric "
214-
"progression"),
215-
prev->pack_name);
216-
217-
if (pack_geometry_weight(ours) <
218-
geometry->split_factor * pack_geometry_weight(prev))
219-
break;
220-
}
221-
222-
split = i;
223-
224-
if (split) {
225-
/*
226-
* Move the split one to the right, since the top element in the
227-
* last-compared pair can't be in the progression. Only do this
228-
* when we split in the middle of the array (otherwise if we got
229-
* to the end, then the split is in the right place).
230-
*/
231-
split++;
232-
}
233-
234-
/*
235-
* Then, anything to the left of 'split' must be in a new pack. But,
236-
* creating that new pack may cause packs in the heavy half to no longer
237-
* form a geometric progression.
238-
*
239-
* Compute an expected size of the new pack, and then determine how many
240-
* packs in the heavy half need to be joined into it (if any) to restore
241-
* the geometric progression.
242-
*/
243-
for (i = 0; i < split; i++) {
244-
struct packed_git *p = geometry->pack[i];
245-
246-
if (unsigned_add_overflows(total_size, pack_geometry_weight(p)))
247-
die(_("pack %s too large to roll up"), p->pack_name);
248-
total_size += pack_geometry_weight(p);
249-
}
250-
for (i = split; i < geometry->pack_nr; i++) {
251-
struct packed_git *ours = geometry->pack[i];
252-
253-
if (unsigned_mult_overflows(geometry->split_factor,
254-
total_size))
255-
die(_("pack %s too large to roll up"), ours->pack_name);
256-
257-
if (pack_geometry_weight(ours) <
258-
geometry->split_factor * total_size) {
259-
if (unsigned_add_overflows(total_size,
260-
pack_geometry_weight(ours)))
261-
die(_("pack %s too large to roll up"),
262-
ours->pack_name);
263-
264-
split++;
265-
total_size += pack_geometry_weight(ours);
266-
} else
267-
break;
268-
}
269-
270-
geometry->split = split;
271-
}
272-
273-
static struct packed_git *pack_geometry_preferred_pack(struct pack_geometry *geometry)
274-
{
275-
uint32_t i;
276-
277-
if (!geometry) {
278-
/*
279-
* No geometry means either an all-into-one repack (in which
280-
* case there is only one pack left and it is the largest) or an
281-
* incremental one.
282-
*
283-
* If repacking incrementally, then we could check the size of
284-
* all packs to determine which should be preferred, but leave
285-
* this for later.
286-
*/
287-
return NULL;
288-
}
289-
if (geometry->split == geometry->pack_nr)
290-
return NULL;
291-
292-
/*
293-
* The preferred pack is the largest pack above the split line. In
294-
* other words, it is the largest pack that does not get rolled up in
295-
* the geometric repack.
296-
*/
297-
for (i = geometry->pack_nr; i > geometry->split; i--)
298-
/*
299-
* A pack that is not local would never be included in a
300-
* multi-pack index. We thus skip over any non-local packs.
301-
*/
302-
if (geometry->pack[i - 1]->pack_local)
303-
return geometry->pack[i - 1];
304-
305-
return NULL;
306-
}
307-
308-
static void pack_geometry_remove_redundant(struct pack_geometry *geometry,
309-
struct string_list *names,
310-
struct existing_packs *existing,
311-
const char *packdir)
312-
{
313-
const struct git_hash_algo *algop = existing->repo->hash_algo;
314-
struct strbuf buf = STRBUF_INIT;
315-
uint32_t i;
316-
317-
for (i = 0; i < geometry->split; i++) {
318-
struct packed_git *p = geometry->pack[i];
319-
if (string_list_has_string(names, hash_to_hex_algop(p->hash,
320-
algop)))
321-
continue;
322-
323-
strbuf_reset(&buf);
324-
strbuf_addstr(&buf, pack_basename(p));
325-
strbuf_strip_suffix(&buf, ".pack");
326-
327-
if ((p->pack_keep) ||
328-
(string_list_has_string(&existing->kept_packs, buf.buf)))
329-
continue;
330-
331-
repack_remove_redundant_pack(existing->repo, packdir, buf.buf);
332-
}
333-
334-
strbuf_release(&buf);
335-
}
336-
337-
static void pack_geometry_release(struct pack_geometry *geometry)
338-
{
339-
if (!geometry)
340-
return;
341-
342-
free(geometry->pack);
343-
}
344-
345110
static int midx_has_unknown_packs(char **midx_pack_names,
346111
size_t midx_pack_names_nr,
347112
struct string_list *include,

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ libgit_sources = [
463463
'reftable/writer.c',
464464
'remote.c',
465465
'repack.c',
466+
'repack-geometry.c',
466467
'repack-promisor.c',
467468
'replace-object.c',
468469
'repo-settings.c',

0 commit comments

Comments
 (0)