summaryrefslogtreecommitdiff
path: root/repack-cruft.c
diff options
context:
space:
mode:
Diffstat (limited to 'repack-cruft.c')
-rw-r--r--repack-cruft.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/repack-cruft.c b/repack-cruft.c
new file mode 100644
index 0000000000..0653e88792
--- /dev/null
+++ b/repack-cruft.c
@@ -0,0 +1,98 @@
+#include "git-compat-util.h"
+#include "repack.h"
+#include "packfile.h"
+#include "repository.h"
+#include "run-command.h"
+
+static void combine_small_cruft_packs(FILE *in, off_t combine_cruft_below_size,
+ struct existing_packs *existing)
+{
+ struct packed_git *p;
+ struct strbuf buf = STRBUF_INIT;
+ size_t i;
+
+ repo_for_each_pack(existing->repo, p) {
+ if (!(p->is_cruft && p->pack_local))
+ continue;
+
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, pack_basename(p));
+ strbuf_strip_suffix(&buf, ".pack");
+
+ if (!string_list_has_string(&existing->cruft_packs, buf.buf))
+ continue;
+
+ if (p->pack_size < combine_cruft_below_size) {
+ fprintf(in, "-%s\n", pack_basename(p));
+ } else {
+ existing_packs_retain_cruft(existing, p);
+ fprintf(in, "%s\n", pack_basename(p));
+ }
+ }
+
+ for (i = 0; i < existing->non_kept_packs.nr; i++)
+ fprintf(in, "-%s.pack\n",
+ existing->non_kept_packs.items[i].string);
+
+ strbuf_release(&buf);
+}
+
+int write_cruft_pack(const struct write_pack_opts *opts,
+ const char *cruft_expiration,
+ unsigned long combine_cruft_below_size,
+ struct string_list *names,
+ struct existing_packs *existing)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ struct string_list_item *item;
+ FILE *in;
+ int ret;
+ const char *pack_prefix = write_pack_opts_pack_prefix(opts);
+
+ prepare_pack_objects(&cmd, opts->po_args, opts->destination);
+
+ strvec_push(&cmd.args, "--cruft");
+ if (cruft_expiration)
+ strvec_pushf(&cmd.args, "--cruft-expiration=%s",
+ cruft_expiration);
+
+ strvec_push(&cmd.args, "--non-empty");
+
+ cmd.in = -1;
+
+ ret = start_command(&cmd);
+ if (ret)
+ return ret;
+
+ /*
+ * names has a confusing double use: it both provides the list
+ * of just-written new packs, and accepts the name of the cruft
+ * pack we are writing.
+ *
+ * By the time it is read here, it contains only the pack(s)
+ * that were just written, which is exactly the set of packs we
+ * want to consider kept.
+ *
+ * If `--expire-to` is given, the double-use served by `names`
+ * ensures that the pack written to `--expire-to` excludes any
+ * objects contained in the cruft pack.
+ */
+ in = xfdopen(cmd.in, "w");
+ for_each_string_list_item(item, names)
+ fprintf(in, "%s-%s.pack\n", pack_prefix, item->string);
+ if (combine_cruft_below_size && !cruft_expiration) {
+ combine_small_cruft_packs(in, combine_cruft_below_size,
+ existing);
+ } else {
+ 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)
+ fprintf(in, "-%s.pack\n", item->string);
+ }
+ for_each_string_list_item(item, &existing->kept_packs)
+ fprintf(in, "%s.pack\n", item->string);
+ fclose(in);
+
+ return finish_pack_objects_cmd(existing->repo->hash_algo, opts, &cmd,
+ names);
+}