#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); }