9
#include "csum-file.h"
10
#include "blob.h"
11
#include "commit.h"
12
+#include "tag.h"
13
#include "tree.h"
14
#include "progress.h"
15
#include "fsck.h"
21
#include "object-file.h"
22
#include "object-store-ll.h"
23
#include "oid-array.h"
24
+#include "oidset.h"
25
+#include "path.h"
26
#include "replace-object.h"
27
+#include "tree-walk.h"
28
#include "promisor-remote.h"
29
+#include "run-command.h"
30
#include "setup.h"
31
+#include "strvec.h"
32
33
static const char index_pack_usage[] =
34
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict[=<msg-id>=<severity>...]] [--fsck-objects[=<msg-id>=<severity>...]] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
154
static int input_fd, output_fd;
155
static const char *curr_pack;
156
157
+/*
158
+ * local_links is guarded by read_mutex, and record_local_links is read-only in
159
+ * a thread.
160
+ */
161
+static struct oidset local_links = OIDSET_INIT;
162
+static int record_local_links;
163
+
164
static struct thread_local *thread_data;
165
static int nr_dispatched;
166
static int threads_active;
812
return 0;
813
}
814
815
+static void record_if_local_object(const struct object_id *oid)
816
+{
817
+ struct object_info info = OBJECT_INFO_INIT;
818
+ if (oid_object_info_extended(the_repository, oid, &info, 0))
819
+ /* Missing; assume it is a promisor object */
820
+ return;
821
+ if (info.whence == OI_PACKED && info.u.packed.pack->pack_promisor)
822
+ return;
823
+ oidset_insert(&local_links, oid);
824
+}
825
+
826
+static void do_record_local_links(struct object *obj)
827
+{
828
+ if (obj->type == OBJ_TREE) {
829
+ struct tree *tree = (struct tree *)obj;
830
+ struct tree_desc desc;
831
+ struct name_entry entry;
832
+ if (init_tree_desc_gently(&desc, &tree->object.oid,
833
+ tree->buffer, tree->size, 0))
834
+ /*
835
+ * Error messages are given when packs are
836
+ * verified, so do not print any here.
837
+ */
838
+ return;
839
+ while (tree_entry_gently(&desc, &entry))
840
+ record_if_local_object(&entry.oid);
841
+ } else if (obj->type == OBJ_COMMIT) {
842
+ struct commit *commit = (struct commit *) obj;
843
+ struct commit_list *parents = commit->parents;
844
+
845
+ for (; parents; parents = parents->next)
846
+ record_if_local_object(&parents->item->object.oid);
847
+ } else if (obj->type == OBJ_TAG) {
848
+ struct tag *tag = (struct tag *) obj;
849
+ record_if_local_object(get_tagged_oid(tag));
850
+ }
851
+}
852
+
853
static void sha1_object(const void *data, struct object_entry *obj_entry,
854
unsigned long size, enum object_type type,
855
const struct object_id *oid)
896
free(has_data);
897
}
898
848
- if (strict || do_fsck_object) {
899
+ if (strict || do_fsck_object || record_local_links) {
900
read_lock();
901
if (type == OBJ_BLOB) {
902
struct blob *blob = lookup_blob(the_repository, oid);
928
die(_("fsck error in packed object"));
929
if (strict && fsck_walk(obj, NULL, &fsck_options))
930
die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid));
931
+ if (record_local_links)
932
+ do_record_local_links(obj);
933
934
if (obj->type == OBJ_TREE) {
935
struct tree *item = (struct tree *) obj;
1772
free(chain_histogram);
1773
}
1774
1775
+static void repack_local_links(void)
1776
+{
1777
+ struct child_process cmd = CHILD_PROCESS_INIT;
1778
+ FILE *out;
1779
+ struct strbuf line = STRBUF_INIT;
1780
+ struct oidset_iter iter;
1781
+ struct object_id *oid;
1782
+ char *base_name;
1783
+
1784
+ if (!oidset_size(&local_links))
1785
+ return;
1786
+
1787
+ base_name = mkpathdup("%s/pack/pack", repo_get_object_directory(the_repository));
1788
+
1789
+ strvec_push(&cmd.args, "pack-objects");
1790
+ strvec_push(&cmd.args, "--exclude-promisor-objects-best-effort");
1791
+ strvec_push(&cmd.args, base_name);
1792
+ cmd.git_cmd = 1;
1793
+ cmd.in = -1;
1794
+ cmd.out = -1;
1795
+ if (start_command(&cmd))
1796
+ die(_("could not start pack-objects to repack local links"));
1797
+
1798
+ oidset_iter_init(&local_links, &iter);
1799
+ while ((oid = oidset_iter_next(&iter))) {
1800
+ if (write_in_full(cmd.in, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
1801
+ write_in_full(cmd.in, "\n", 1) < 0)
1802
+ die(_("failed to feed local object to pack-objects"));
1803
+ }
1804
+ close(cmd.in);
1805
+
1806
+ out = xfdopen(cmd.out, "r");
1807
+ while (strbuf_getline_lf(&line, out) != EOF) {
1808
+ unsigned char binary[GIT_MAX_RAWSZ];
1809
+ if (line.len != the_hash_algo->hexsz ||
1810
+ !hex_to_bytes(binary, line.buf, line.len))
1811
+ die(_("index-pack: Expecting full hex object ID lines only from pack-objects."));
1812
+
1813
+ /*
1814
+ * pack-objects creates the .pack and .idx files, but not the
1815
+ * .promisor file. Create the .promisor file, which is empty.
1816
+ */
1817
+ write_special_file("promisor", "", NULL, binary, NULL);
1818
+ }
1819
+
1820
+ fclose(out);
1821
+ if (finish_command(&cmd))
1822
+ die(_("could not finish pack-objects to repack local links"));
1823
+ strbuf_release(&line);
1824
+ free(base_name);
1825
+}
1826
+
1827
int cmd_index_pack(int argc,
1828
const char **argv,
1829
const char *prefix,
1899
} else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) {
1900
; /* nothing to do */
1901
} else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) {
1797
- ; /* already parsed */
1902
+ record_local_links = 1;
1903
} else if (starts_with(arg, "--threads=")) {
1904
char *end;
1905
nr_threads = strtoul(arg+10, &end, 0);
2075
free((void *) curr_index);
2076
free(curr_rev_index);
2077
2078
+ repack_local_links();
2079
+
2080
/*
2081
* Let the caller know this pack is not self contained
2082
*/