Raw
1 #include "git-compat-util.h"
2 #include "repack.h"
3 #include "packfile.h"
4 #include "repository.h"
5 #include "run-command.h"
6
7 static void combine_small_cruft_packs(FILE *in, off_t combine_cruft_below_size,
8 struct existing_packs *existing)
9 {
10 struct packed_git *p;
11 struct strbuf buf = STRBUF_INIT;
12
13 repo_for_each_pack(existing->repo, p) {
14 if (!(p->is_cruft && p->pack_local))
15 continue;
16
17 strbuf_reset(&buf);
18 strbuf_addstr(&buf, pack_basename(p));
19 strbuf_strip_suffix(&buf, ".pack");
20
21 if (!string_list_has_string(&existing->cruft_packs, buf.buf))
22 continue;
23
24 if (p->pack_size < combine_cruft_below_size) {
25 fprintf(in, "-%s\n", pack_basename(p));
26 } else {
27 existing_packs_retain_cruft(existing, p);
28 fprintf(in, "%s\n", pack_basename(p));
29 }
30 }
31
32 strbuf_release(&buf);
33 }
34
35 int write_cruft_pack(const struct write_pack_opts *opts,
36 const char *cruft_expiration,
37 unsigned long combine_cruft_below_size,
38 struct string_list *names,
39 struct existing_packs *existing,
40 struct pack_geometry *geometry)
41 {
42 struct child_process cmd = CHILD_PROCESS_INIT;
43 struct string_list_item *item;
44 FILE *in;
45 int ret;
46 const char *pack_prefix = write_pack_opts_pack_prefix(opts);
47
48 prepare_pack_objects(&cmd, opts->po_args, opts->destination);
49
50 strvec_push(&cmd.args, "--cruft");
51 if (cruft_expiration)
52 strvec_pushf(&cmd.args, "--cruft-expiration=%s",
53 cruft_expiration);
54
55 strvec_push(&cmd.args, "--non-empty");
56
57 cmd.in = -1;
58
59 ret = start_command(&cmd);
60 if (ret)
61 return ret;
62
63 /*
64 * names has a confusing double use: it both provides the list
65 * of just-written new packs, and accepts the name of the cruft
66 * pack we are writing.
67 *
68 * By the time it is read here, it contains only the pack(s)
69 * that were just written, which is exactly the set of packs we
70 * want to consider kept.
71 *
72 * If `--expire-to` is given, the double-use served by `names`
73 * ensures that the pack written to `--expire-to` excludes any
74 * objects contained in the cruft pack.
75 */
76 in = xfdopen(cmd.in, "w");
77 for_each_string_list_item(item, names)
78 fprintf(in, "%s-%s.pack\n", pack_prefix, item->string);
79 if (combine_cruft_below_size && !cruft_expiration)
80 combine_small_cruft_packs(in, combine_cruft_below_size,
81 existing);
82 else
83 for_each_string_list_item(item, &existing->cruft_packs)
84 fprintf(in, "-%s.pack\n", item->string);
85 if (geometry) {
86 uint32_t j;
87 for (j = 0; j < geometry->split; j++)
88 fprintf(in, "-%s\n",
89 pack_basename(geometry->pack[j]));
90 for (; j < geometry->pack_nr; j++)
91 fprintf(in, "%s\n",
92 pack_basename(geometry->pack[j]));
93 for (j = 0; j < geometry->promisor_split; j++)
94 fprintf(in, "-%s\n",
95 pack_basename(geometry->promisor_pack[j]));
96 for (; j < geometry->promisor_pack_nr; j++)
97 fprintf(in, "%s\n",
98 pack_basename(geometry->promisor_pack[j]));
99 } else {
100 for_each_string_list_item(item, &existing->non_kept_packs)
101 fprintf(in, "-%s.pack\n", item->string);
102 }
103 for_each_string_list_item(item, &existing->kept_packs)
104 fprintf(in, "%s.pack\n", item->string);
105 fclose(in);
106
107 return finish_pack_objects_cmd(existing->repo->hash_algo, opts, &cmd,
108 names);
109 }