#include "git-compat-util.h" #include "repack.h" #include "hex.h" #include "pack.h" #include "packfile.h" #include "path.h" #include "repository.h" #include "run-command.h" struct write_oid_context { struct child_process *cmd; const struct git_hash_algo *algop; }; /* * Write oid to the given struct child_process's stdin, starting it first if * necessary. */ static int write_oid(const struct object_id *oid, struct packed_git *pack UNUSED, uint32_t pos UNUSED, void *data) { struct write_oid_context *ctx = data; struct child_process *cmd = ctx->cmd; if (cmd->in == -1) { if (start_command(cmd)) die(_("could not start pack-objects to repack promisor objects")); } if (write_in_full(cmd->in, oid_to_hex(oid), ctx->algop->hexsz) < 0 || write_in_full(cmd->in, "\n", 1) < 0) die(_("failed to feed promisor objects to pack-objects")); return 0; } void repack_promisor_objects(struct repository *repo, const struct pack_objects_args *args, struct string_list *names, const char *packtmp) { struct write_oid_context ctx; struct child_process cmd = CHILD_PROCESS_INIT; FILE *out; struct strbuf line = STRBUF_INIT; prepare_pack_objects(&cmd, args, packtmp); cmd.in = -1; /* * NEEDSWORK: Giving pack-objects only the OIDs without any ordering * hints may result in suboptimal deltas in the resulting pack. See if * the OIDs can be sent with fake paths such that pack-objects can use a * {type -> existing pack order} ordering when computing deltas instead * of a {type -> size} ordering, which may produce better deltas. */ ctx.cmd = &cmd; ctx.algop = repo->hash_algo; for_each_packed_object(repo, write_oid, &ctx, FOR_EACH_OBJECT_PROMISOR_ONLY); if (cmd.in == -1) { /* No packed objects; cmd was never started */ child_process_clear(&cmd); return; } close(cmd.in); out = xfdopen(cmd.out, "r"); while (strbuf_getline_lf(&line, out) != EOF) { struct string_list_item *item; char *promisor_name; if (line.len != repo->hash_algo->hexsz) die(_("repack: Expecting full hex object ID lines only from pack-objects.")); item = string_list_append(names, line.buf); /* * pack-objects creates the .pack and .idx files, but not the * .promisor file. Create the .promisor file, which is empty. * * NEEDSWORK: fetch-pack sometimes generates non-empty * .promisor files containing the ref names and associated * hashes at the point of generation of the corresponding * packfile, but this would not preserve their contents. Maybe * concatenate the contents of all .promisor files instead of * just creating a new empty file. */ promisor_name = mkpathdup("%s-%s.promisor", packtmp, line.buf); write_promisor_file(promisor_name, NULL, 0); item->util = generated_pack_populate(item->string, packtmp); free(promisor_name); } fclose(out); if (finish_command(&cmd)) die(_("could not finish pack-objects to repack promisor objects")); strbuf_release(&line); }