|
9 | 9 | #include "csum-file.h"
|
10 | 10 | #include "blob.h"
|
11 | 11 | #include "commit.h"
|
| 12 | +#include "tag.h" |
12 | 13 | #include "tree.h"
|
13 | 14 | #include "progress.h"
|
14 | 15 | #include "fsck.h"
|
|
20 | 21 | #include "object-file.h"
|
21 | 22 | #include "object-store-ll.h"
|
22 | 23 | #include "oid-array.h"
|
| 24 | +#include "oidset.h" |
| 25 | +#include "path.h" |
23 | 26 | #include "replace-object.h"
|
| 27 | +#include "tree-walk.h" |
24 | 28 | #include "promisor-remote.h"
|
| 29 | +#include "run-command.h" |
25 | 30 | #include "setup.h"
|
| 31 | +#include "strvec.h" |
26 | 32 |
|
27 | 33 | static const char index_pack_usage[] =
|
28 | 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>])";
|
@@ -148,6 +154,13 @@ static uint32_t input_crc32;
|
148 | 154 | static int input_fd, output_fd;
|
149 | 155 | static const char *curr_pack;
|
150 | 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 | + |
151 | 164 | static struct thread_local *thread_data;
|
152 | 165 | static int nr_dispatched;
|
153 | 166 | static int threads_active;
|
@@ -799,6 +812,44 @@ static int check_collison(struct object_entry *entry)
|
799 | 812 | return 0;
|
800 | 813 | }
|
801 | 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 | + |
802 | 853 | static void sha1_object(const void *data, struct object_entry *obj_entry,
|
803 | 854 | unsigned long size, enum object_type type,
|
804 | 855 | const struct object_id *oid)
|
@@ -845,7 +896,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
845 | 896 | free(has_data);
|
846 | 897 | }
|
847 | 898 |
|
848 |
| - if (strict || do_fsck_object) { |
| 899 | + if (strict || do_fsck_object || record_local_links) { |
849 | 900 | read_lock();
|
850 | 901 | if (type == OBJ_BLOB) {
|
851 | 902 | struct blob *blob = lookup_blob(the_repository, oid);
|
@@ -877,6 +928,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
877 | 928 | die(_("fsck error in packed object"));
|
878 | 929 | if (strict && fsck_walk(obj, NULL, &fsck_options))
|
879 | 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); |
880 | 933 |
|
881 | 934 | if (obj->type == OBJ_TREE) {
|
882 | 935 | struct tree *item = (struct tree *) obj;
|
@@ -1719,6 +1772,58 @@ static void show_pack_info(int stat_only)
|
1719 | 1772 | free(chain_histogram);
|
1720 | 1773 | }
|
1721 | 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 | + |
1722 | 1827 | int cmd_index_pack(int argc,
|
1723 | 1828 | const char **argv,
|
1724 | 1829 | const char *prefix,
|
@@ -1794,7 +1899,7 @@ int cmd_index_pack(int argc,
|
1794 | 1899 | } else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) {
|
1795 | 1900 | ; /* nothing to do */
|
1796 | 1901 | } else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) {
|
1797 |
| - ; /* already parsed */ |
| 1902 | + record_local_links = 1; |
1798 | 1903 | } else if (starts_with(arg, "--threads=")) {
|
1799 | 1904 | char *end;
|
1800 | 1905 | nr_threads = strtoul(arg+10, &end, 0);
|
@@ -1970,6 +2075,8 @@ int cmd_index_pack(int argc,
|
1970 | 2075 | free((void *) curr_index);
|
1971 | 2076 | free(curr_rev_index);
|
1972 | 2077 |
|
| 2078 | + repack_local_links(); |
| 2079 | + |
1973 | 2080 | /*
|
1974 | 2081 | * Let the caller know this pack is not self contained
|
1975 | 2082 | */
|
|
0 commit comments