Ramsay Jones | 2ad9d4c | 2011-04-07 19:23:40 +0100 | [diff] [blame] | 1 | #include "builtin.h" |
Brandon Williams | b2141fc | 2017-06-14 11:07:36 -0700 | [diff] [blame] | 2 | #include "config.h" |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 3 | #include "delta.h" |
Elijah Newren | 32a8f51 | 2023-03-21 06:26:03 +0000 | [diff] [blame] | 4 | #include "environment.h" |
Elijah Newren | f394e09 | 2023-03-21 06:25:54 +0000 | [diff] [blame] | 5 | #include "gettext.h" |
Elijah Newren | 41771fa | 2023-02-24 00:09:27 +0000 | [diff] [blame] | 6 | #include "hex.h" |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 7 | #include "pack.h" |
| 8 | #include "csum-file.h" |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 9 | #include "blob.h" |
| 10 | #include "commit.h" |
Peter Eriksen | 8e44025 | 2006-04-02 14:44:09 +0200 | [diff] [blame] | 11 | #include "tree.h" |
Nicolas Pitre | 96a02f8 | 2007-04-18 14:27:45 -0400 | [diff] [blame] | 12 | #include "progress.h" |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 13 | #include "fsck.h" |
Elijah Newren | a034e91 | 2023-05-16 06:34:06 +0000 | [diff] [blame] | 14 | #include "strbuf.h" |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 15 | #include "streaming.h" |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 16 | #include "thread-utils.h" |
Jonathan Tan | 4f39cd8 | 2017-08-18 15:20:16 -0700 | [diff] [blame] | 17 | #include "packfile.h" |
Elijah Newren | 75f273d | 2023-04-11 03:00:41 +0000 | [diff] [blame] | 18 | #include "pack-revindex.h" |
Elijah Newren | 87bed17 | 2023-04-11 00:41:53 -0700 | [diff] [blame] | 19 | #include "object-file.h" |
Elijah Newren | a034e91 | 2023-05-16 06:34:06 +0000 | [diff] [blame] | 20 | #include "object-store-ll.h" |
Elijah Newren | 6f2d743 | 2023-04-11 03:00:42 +0000 | [diff] [blame] | 21 | #include "oid-array.h" |
Elijah Newren | cbeab74 | 2023-02-24 00:09:33 +0000 | [diff] [blame] | 22 | #include "replace-object.h" |
Christian Couder | b14ed5a | 2019-06-25 15:40:31 +0200 | [diff] [blame] | 23 | #include "promisor-remote.h" |
Elijah Newren | e38da48 | 2023-03-21 06:26:05 +0000 | [diff] [blame] | 24 | #include "setup.h" |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 25 | |
| 26 | static const char index_pack_usage[] = |
John Cai | 0f8edf7 | 2024-02-01 01:38:02 +0000 | [diff] [blame] | 27 | "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>])"; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 28 | |
Jonathan Nieder | 9cba13c | 2011-03-16 02:08:34 -0500 | [diff] [blame] | 29 | struct object_entry { |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 30 | struct pack_idx_entry idx; |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 31 | unsigned long size; |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 32 | unsigned char hdr_size; |
| 33 | signed char type; |
| 34 | signed char real_type; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 35 | }; |
| 36 | |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 37 | struct object_stat { |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 38 | unsigned delta_depth; |
| 39 | int base_object_no; |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 40 | }; |
| 41 | |
Shawn O. Pearce | f41aebd | 2008-07-13 22:07:44 -0400 | [diff] [blame] | 42 | struct base_data { |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 43 | /* Initialized by make_base(). */ |
Shawn O. Pearce | 4a438ca | 2008-07-13 22:07:45 -0400 | [diff] [blame] | 44 | struct base_data *base; |
Shawn O. Pearce | 03993e1 | 2008-07-13 22:07:46 -0400 | [diff] [blame] | 45 | struct object_entry *obj; |
Nguyễn Thái Ngọc Duy | 2baad22 | 2012-01-14 19:19:54 +0700 | [diff] [blame] | 46 | int ref_first, ref_last; |
| 47 | int ofs_first, ofs_last; |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 48 | /* |
| 49 | * Threads should increment retain_data if they are about to call |
| 50 | * patch_delta() using this struct's data as a base, and decrement this |
| 51 | * when they are done. While retain_data is nonzero, this struct's data |
| 52 | * will not be freed even if the delta base cache limit is exceeded. |
| 53 | */ |
| 54 | int retain_data; |
| 55 | /* |
| 56 | * The number of direct children that have not been fully processed |
| 57 | * (entered work_head, entered done_head, left done_head). When this |
| 58 | * number reaches zero, this struct base_data can be freed. |
| 59 | */ |
| 60 | int children_remaining; |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 61 | |
| 62 | /* Not initialized by make_base(). */ |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 63 | struct list_head list; |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 64 | void *data; |
| 65 | unsigned long size; |
Shawn O. Pearce | f41aebd | 2008-07-13 22:07:44 -0400 | [diff] [blame] | 66 | }; |
| 67 | |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 68 | /* |
| 69 | * Stack of struct base_data that have unprocessed children. |
| 70 | * threaded_second_pass() uses this as a source of work (the other being the |
| 71 | * objects array). |
| 72 | * |
| 73 | * Guarded by work_mutex. |
| 74 | */ |
| 75 | static LIST_HEAD(work_head); |
| 76 | |
| 77 | /* |
| 78 | * Stack of struct base_data that have children, all of whom have been |
| 79 | * processed or are being processed, and at least one child is being processed. |
| 80 | * These struct base_data must be kept around until the last child is |
| 81 | * processed. |
| 82 | * |
| 83 | * Guarded by work_mutex. |
| 84 | */ |
| 85 | static LIST_HEAD(done_head); |
| 86 | |
| 87 | /* |
| 88 | * All threads share one delta base cache. |
| 89 | * |
| 90 | * base_cache_used is guarded by work_mutex, and base_cache_limit is read-only |
| 91 | * in a thread. |
| 92 | */ |
| 93 | static size_t base_cache_used; |
| 94 | static size_t base_cache_limit; |
| 95 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 96 | struct thread_local { |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 97 | pthread_t thread; |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 98 | int pack_fd; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 99 | }; |
| 100 | |
Nguyễn Thái Ngọc Duy | 95308d6 | 2018-03-06 17:16:14 +0700 | [diff] [blame] | 101 | /* Remember to update object flag allocation in object.h */ |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 102 | #define FLAG_LINK (1u<<20) |
| 103 | #define FLAG_CHECKED (1u<<21) |
| 104 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 105 | struct ofs_delta_entry { |
| 106 | off_t offset; |
| 107 | int obj_no; |
| 108 | }; |
| 109 | |
| 110 | struct ref_delta_entry { |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 111 | struct object_id oid; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 112 | int obj_no; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 113 | }; |
| 114 | |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 115 | static struct object_entry *objects; |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 116 | static struct object_stat *obj_stat; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 117 | static struct ofs_delta_entry *ofs_deltas; |
| 118 | static struct ref_delta_entry *ref_deltas; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 119 | static struct thread_local nothread_data; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 120 | static int nr_objects; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 121 | static int nr_ofs_deltas; |
| 122 | static int nr_ref_deltas; |
| 123 | static int ref_deltas_alloc; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 124 | static int nr_resolved_deltas; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 125 | static int nr_threads; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 126 | |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 127 | static int from_stdin; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 128 | static int strict; |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 129 | static int do_fsck_object; |
Ævar Arnfjörð Bjarmason | 3745e26 | 2021-03-28 15:15:51 +0200 | [diff] [blame] | 130 | static struct fsck_options fsck_options = FSCK_OPTIONS_MISSING_GITMODULES; |
Nicolas Pitre | 3c9af36 | 2006-10-25 23:32:59 -0400 | [diff] [blame] | 131 | static int verbose; |
Ævar Arnfjörð Bjarmason | f46c46e | 2021-09-05 09:34:44 +0200 | [diff] [blame] | 132 | static const char *progress_title; |
Jeff King | e376f17 | 2016-07-15 06:34:22 -0400 | [diff] [blame] | 133 | static int show_resolving_progress; |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 134 | static int show_stat; |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 135 | static int check_self_contained_and_connected; |
Nicolas Pitre | 3c9af36 | 2006-10-25 23:32:59 -0400 | [diff] [blame] | 136 | |
Nicolas Pitre | dc6a075 | 2007-10-30 14:57:32 -0400 | [diff] [blame] | 137 | static struct progress *progress; |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 138 | |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 139 | /* We always read in 4kB chunks. */ |
| 140 | static unsigned char input_buffer[4096]; |
Nicolas Pitre | d7dd022 | 2007-04-09 01:06:30 -0400 | [diff] [blame] | 141 | static unsigned int input_offset, input_len; |
| 142 | static off_t consumed_bytes; |
Jeff King | 411481b | 2016-08-24 20:41:55 +0200 | [diff] [blame] | 143 | static off_t max_input_size; |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 144 | static unsigned deepest_delta; |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 145 | static git_hash_ctx input_ctx; |
Nicolas Pitre | ee5743c | 2007-04-09 01:06:32 -0400 | [diff] [blame] | 146 | static uint32_t input_crc32; |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 147 | static int input_fd, output_fd; |
| 148 | static const char *curr_pack; |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 149 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 150 | static struct thread_local *thread_data; |
| 151 | static int nr_dispatched; |
| 152 | static int threads_active; |
| 153 | |
| 154 | static pthread_mutex_t read_mutex; |
| 155 | #define read_lock() lock_mutex(&read_mutex) |
| 156 | #define read_unlock() unlock_mutex(&read_mutex) |
| 157 | |
| 158 | static pthread_mutex_t counter_mutex; |
| 159 | #define counter_lock() lock_mutex(&counter_mutex) |
| 160 | #define counter_unlock() unlock_mutex(&counter_mutex) |
| 161 | |
| 162 | static pthread_mutex_t work_mutex; |
| 163 | #define work_lock() lock_mutex(&work_mutex) |
| 164 | #define work_unlock() unlock_mutex(&work_mutex) |
| 165 | |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 166 | static pthread_mutex_t deepest_delta_mutex; |
| 167 | #define deepest_delta_lock() lock_mutex(&deepest_delta_mutex) |
| 168 | #define deepest_delta_unlock() unlock_mutex(&deepest_delta_mutex) |
| 169 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 170 | static pthread_key_t key; |
| 171 | |
| 172 | static inline void lock_mutex(pthread_mutex_t *mutex) |
| 173 | { |
| 174 | if (threads_active) |
| 175 | pthread_mutex_lock(mutex); |
| 176 | } |
| 177 | |
| 178 | static inline void unlock_mutex(pthread_mutex_t *mutex) |
| 179 | { |
| 180 | if (threads_active) |
| 181 | pthread_mutex_unlock(mutex); |
| 182 | } |
| 183 | |
| 184 | /* |
| 185 | * Mutex and conditional variable can't be statically-initialized on Windows. |
| 186 | */ |
| 187 | static void init_thread(void) |
| 188 | { |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 189 | int i; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 190 | init_recursive_mutex(&read_mutex); |
| 191 | pthread_mutex_init(&counter_mutex, NULL); |
| 192 | pthread_mutex_init(&work_mutex, NULL); |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 193 | if (show_stat) |
| 194 | pthread_mutex_init(&deepest_delta_mutex, NULL); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 195 | pthread_key_create(&key, NULL); |
René Scharfe | ca56dad | 2021-03-13 17:17:22 +0100 | [diff] [blame] | 196 | CALLOC_ARRAY(thread_data, nr_threads); |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 197 | for (i = 0; i < nr_threads; i++) { |
René Scharfe | 6346f70 | 2021-09-10 22:25:50 +0200 | [diff] [blame] | 198 | thread_data[i].pack_fd = xopen(curr_pack, O_RDONLY); |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 199 | } |
| 200 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 201 | threads_active = 1; |
| 202 | } |
| 203 | |
| 204 | static void cleanup_thread(void) |
| 205 | { |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 206 | int i; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 207 | if (!threads_active) |
| 208 | return; |
| 209 | threads_active = 0; |
| 210 | pthread_mutex_destroy(&read_mutex); |
| 211 | pthread_mutex_destroy(&counter_mutex); |
| 212 | pthread_mutex_destroy(&work_mutex); |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 213 | if (show_stat) |
| 214 | pthread_mutex_destroy(&deepest_delta_mutex); |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 215 | for (i = 0; i < nr_threads; i++) |
| 216 | close(thread_data[i].pack_fd); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 217 | pthread_key_delete(key); |
| 218 | free(thread_data); |
| 219 | } |
| 220 | |
Ævar Arnfjörð Bjarmason | a1aad71 | 2021-03-28 15:15:35 +0200 | [diff] [blame] | 221 | static int mark_link(struct object *obj, enum object_type type, |
Jeff King | 0b4e901 | 2023-07-03 02:44:18 -0400 | [diff] [blame] | 222 | void *data UNUSED, |
| 223 | struct fsck_options *options UNUSED) |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 224 | { |
| 225 | if (!obj) |
| 226 | return -1; |
| 227 | |
| 228 | if (type != OBJ_ANY && obj->type != type) |
brian m. carlson | f2fd076 | 2015-11-10 02:22:28 +0000 | [diff] [blame] | 229 | die(_("object type mismatch at %s"), oid_to_hex(&obj->oid)); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 230 | |
| 231 | obj->flags |= FLAG_LINK; |
| 232 | return 0; |
| 233 | } |
| 234 | |
| 235 | /* The content of each linked object must have been checked |
| 236 | or it must be already present in the object database */ |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 237 | static unsigned check_object(struct object *obj) |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 238 | { |
| 239 | if (!obj) |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 240 | return 0; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 241 | |
| 242 | if (!(obj->flags & FLAG_LINK)) |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 243 | return 0; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 244 | |
| 245 | if (!(obj->flags & FLAG_CHECKED)) { |
| 246 | unsigned long size; |
Stefan Beller | 0df8e96 | 2018-04-25 11:20:59 -0700 | [diff] [blame] | 247 | int type = oid_object_info(the_repository, &obj->oid, &size); |
Jeff King | 77583e7 | 2014-05-12 00:38:39 -0400 | [diff] [blame] | 248 | if (type <= 0) |
| 249 | die(_("did not receive expected object %s"), |
brian m. carlson | f2fd076 | 2015-11-10 02:22:28 +0000 | [diff] [blame] | 250 | oid_to_hex(&obj->oid)); |
Jeff King | 77583e7 | 2014-05-12 00:38:39 -0400 | [diff] [blame] | 251 | if (type != obj->type) |
| 252 | die(_("object %s: expected type %s, found %s"), |
brian m. carlson | f2fd076 | 2015-11-10 02:22:28 +0000 | [diff] [blame] | 253 | oid_to_hex(&obj->oid), |
Brandon Williams | debca9d | 2018-02-14 10:59:24 -0800 | [diff] [blame] | 254 | type_name(obj->type), type_name(type)); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 255 | obj->flags |= FLAG_CHECKED; |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 256 | return 1; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 257 | } |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 258 | |
| 259 | return 0; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 260 | } |
| 261 | |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 262 | static unsigned check_objects(void) |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 263 | { |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 264 | unsigned i, max, foreign_nr = 0; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 265 | |
| 266 | max = get_max_object_index(); |
SZEDER Gábor | 79e3aa6 | 2019-04-01 01:12:35 +0200 | [diff] [blame] | 267 | |
| 268 | if (verbose) |
| 269 | progress = start_delayed_progress(_("Checking objects"), max); |
| 270 | |
| 271 | for (i = 0; i < max; i++) { |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 272 | foreign_nr += check_object(get_indexed_object(i)); |
SZEDER Gábor | 79e3aa6 | 2019-04-01 01:12:35 +0200 | [diff] [blame] | 273 | display_progress(progress, i + 1); |
| 274 | } |
| 275 | |
| 276 | stop_progress(&progress); |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 277 | return foreign_nr; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 281 | /* Discard current buffer used content. */ |
Rene Scharfe | a6e8a76 | 2006-11-18 13:07:06 +0100 | [diff] [blame] | 282 | static void flush(void) |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 283 | { |
| 284 | if (input_offset) { |
| 285 | if (output_fd >= 0) |
| 286 | write_or_die(output_fd, input_buffer, input_offset); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 287 | the_hash_algo->update_fn(&input_ctx, input_buffer, input_offset); |
Jim Meyering | 554a263 | 2006-12-11 19:06:34 +0100 | [diff] [blame] | 288 | memmove(input_buffer, input_buffer + input_offset, input_len); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 289 | input_offset = 0; |
| 290 | } |
| 291 | } |
| 292 | |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 293 | /* |
| 294 | * Make sure at least "min" bytes are available in the buffer, and |
| 295 | * return the pointer to the buffer. |
| 296 | */ |
Nicolas Pitre | b89c4e9 | 2006-10-27 16:14:23 -0400 | [diff] [blame] | 297 | static void *fill(int min) |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 298 | { |
| 299 | if (min <= input_len) |
| 300 | return input_buffer + input_offset; |
| 301 | if (min > sizeof(input_buffer)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 302 | die(Q_("cannot fill %d byte", |
| 303 | "cannot fill %d bytes", |
| 304 | min), |
| 305 | min); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 306 | flush(); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 307 | do { |
Johan Herland | 8a912bc | 2007-05-15 14:49:22 +0200 | [diff] [blame] | 308 | ssize_t ret = xread(input_fd, input_buffer + input_len, |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 309 | sizeof(input_buffer) - input_len); |
| 310 | if (ret <= 0) { |
| 311 | if (!ret) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 312 | die(_("early EOF")); |
| 313 | die_errno(_("read error on input")); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 314 | } |
| 315 | input_len += ret; |
Nicolas Pitre | 218558a | 2007-11-04 22:15:41 -0500 | [diff] [blame] | 316 | if (from_stdin) |
| 317 | display_throughput(progress, consumed_bytes + input_len); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 318 | } while (input_len < min); |
| 319 | return input_buffer; |
| 320 | } |
| 321 | |
| 322 | static void use(int bytes) |
| 323 | { |
| 324 | if (bytes > input_len) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 325 | die(_("used more bytes than were available")); |
Nicolas Pitre | ee5743c | 2007-04-09 01:06:32 -0400 | [diff] [blame] | 326 | input_crc32 = crc32(input_crc32, input_buffer + input_offset, bytes); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 327 | input_len -= bytes; |
| 328 | input_offset += bytes; |
Nicolas Pitre | d7dd022 | 2007-04-09 01:06:30 -0400 | [diff] [blame] | 329 | |
| 330 | /* make sure off_t is sufficiently large not to wrap */ |
Erik Faye-Lund | c03c831 | 2010-10-05 09:24:10 +0200 | [diff] [blame] | 331 | if (signed_add_overflows(consumed_bytes, bytes)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 332 | die(_("pack too large for current definition of off_t")); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 333 | consumed_bytes += bytes; |
Matt Cooper | 0cf5fbc | 2022-02-24 00:07:20 +0000 | [diff] [blame] | 334 | if (max_input_size && consumed_bytes > max_input_size) { |
| 335 | struct strbuf size_limit = STRBUF_INIT; |
| 336 | strbuf_humanise_bytes(&size_limit, max_input_size); |
| 337 | die(_("pack exceeds maximum allowed size (%s)"), |
| 338 | size_limit.buf); |
| 339 | } |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 340 | } |
| 341 | |
Linus Torvalds | 3bb7256 | 2010-01-22 07:55:19 -0800 | [diff] [blame] | 342 | static const char *open_pack_file(const char *pack_name) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 343 | { |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 344 | if (from_stdin) { |
| 345 | input_fd = 0; |
| 346 | if (!pack_name) { |
Jeff King | 594fa99 | 2017-03-28 15:45:43 -0400 | [diff] [blame] | 347 | struct strbuf tmp_file = STRBUF_INIT; |
| 348 | output_fd = odb_mkstemp(&tmp_file, |
Junio C Hamano | 6e180cd | 2009-02-24 23:11:29 -0800 | [diff] [blame] | 349 | "pack/tmp_pack_XXXXXX"); |
Jeff King | 594fa99 | 2017-03-28 15:45:43 -0400 | [diff] [blame] | 350 | pack_name = strbuf_detach(&tmp_file, NULL); |
Jeff King | 892e723 | 2017-03-28 15:45:25 -0400 | [diff] [blame] | 351 | } else { |
René Scharfe | 66e905b | 2021-08-25 22:16:46 +0200 | [diff] [blame] | 352 | output_fd = xopen(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600); |
Jeff King | 892e723 | 2017-03-28 15:45:25 -0400 | [diff] [blame] | 353 | } |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 354 | nothread_data.pack_fd = output_fd; |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 355 | } else { |
René Scharfe | 66e905b | 2021-08-25 22:16:46 +0200 | [diff] [blame] | 356 | input_fd = xopen(pack_name, O_RDONLY); |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 357 | output_fd = -1; |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 358 | nothread_data.pack_fd = input_fd; |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 359 | } |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 360 | the_hash_algo->init_fn(&input_ctx); |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 361 | return pack_name; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 362 | } |
| 363 | |
| 364 | static void parse_pack_header(void) |
| 365 | { |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 366 | struct pack_header *hdr = fill(sizeof(struct pack_header)); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 367 | |
| 368 | /* Header consistency check */ |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 369 | if (hdr->hdr_signature != htonl(PACK_SIGNATURE)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 370 | die(_("pack signature mismatch")); |
Nicolas Pitre | d60fc1c | 2006-02-09 17:50:04 -0500 | [diff] [blame] | 371 | if (!pack_version_ok(hdr->hdr_version)) |
Nguyễn Thái Ngọc Duy | f350df4 | 2012-08-31 19:13:04 +0700 | [diff] [blame] | 372 | die(_("pack version %"PRIu32" unsupported"), |
Ramsay Jones | 6e1c234 | 2008-07-03 16:52:09 +0100 | [diff] [blame] | 373 | ntohl(hdr->hdr_version)); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 374 | |
| 375 | nr_objects = ntohl(hdr->hdr_entries); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 376 | use(sizeof(struct pack_header)); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 377 | } |
| 378 | |
Ævar Arnfjörð Bjarmason | 103e02c | 2021-07-10 10:47:27 +0200 | [diff] [blame] | 379 | __attribute__((format (printf, 2, 3))) |
Nguyễn Thái Ngọc Duy | fd3e674 | 2016-07-13 17:44:01 +0200 | [diff] [blame] | 380 | static NORETURN void bad_object(off_t offset, const char *format, ...) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 381 | { |
| 382 | va_list params; |
| 383 | char buf[1024]; |
| 384 | |
| 385 | va_start(params, format); |
| 386 | vsnprintf(buf, sizeof(buf), format, params); |
| 387 | va_end(params); |
Nguyễn Thái Ngọc Duy | fd3e674 | 2016-07-13 17:44:01 +0200 | [diff] [blame] | 388 | die(_("pack has bad object at offset %"PRIuMAX": %s"), |
| 389 | (uintmax_t)offset, buf); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 390 | } |
| 391 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 392 | static inline struct thread_local *get_thread_data(void) |
| 393 | { |
Nguyễn Thái Ngọc Duy | 2094c5e | 2018-11-03 09:48:40 +0100 | [diff] [blame] | 394 | if (HAVE_THREADS) { |
| 395 | if (threads_active) |
| 396 | return pthread_getspecific(key); |
| 397 | assert(!threads_active && |
| 398 | "This should only be reached when all threads are gone"); |
| 399 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 400 | return ¬hread_data; |
| 401 | } |
| 402 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 403 | static void set_thread_data(struct thread_local *data) |
| 404 | { |
| 405 | if (threads_active) |
| 406 | pthread_setspecific(key, data); |
| 407 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 408 | |
Nicolas Pitre | 6a87ed9 | 2008-10-17 15:57:58 -0400 | [diff] [blame] | 409 | static void free_base_data(struct base_data *c) |
| 410 | { |
| 411 | if (c->data) { |
Ævar Arnfjörð Bjarmason | 6a83d90 | 2017-06-15 23:15:46 +0000 | [diff] [blame] | 412 | FREE_AND_NULL(c->data); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 413 | base_cache_used -= c->size; |
Nicolas Pitre | 6a87ed9 | 2008-10-17 15:57:58 -0400 | [diff] [blame] | 414 | } |
| 415 | } |
| 416 | |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 417 | static void prune_base_data(struct base_data *retain) |
| 418 | { |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 419 | struct list_head *pos; |
Jonathan Tan | a7f7e84 | 2020-08-24 12:16:35 -0700 | [diff] [blame] | 420 | |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 421 | if (base_cache_used <= base_cache_limit) |
Jonathan Tan | a7f7e84 | 2020-08-24 12:16:35 -0700 | [diff] [blame] | 422 | return; |
| 423 | |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 424 | list_for_each_prev(pos, &done_head) { |
| 425 | struct base_data *b = list_entry(pos, struct base_data, list); |
| 426 | if (b->retain_data || b == retain) |
| 427 | continue; |
| 428 | if (b->data) { |
Nicolas Pitre | 6a87ed9 | 2008-10-17 15:57:58 -0400 | [diff] [blame] | 429 | free_base_data(b); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 430 | if (base_cache_used <= base_cache_limit) |
| 431 | return; |
| 432 | } |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 433 | } |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 434 | |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 435 | list_for_each_prev(pos, &work_head) { |
| 436 | struct base_data *b = list_entry(pos, struct base_data, list); |
| 437 | if (b->retain_data || b == retain) |
| 438 | continue; |
| 439 | if (b->data) { |
| 440 | free_base_data(b); |
| 441 | if (base_cache_used <= base_cache_limit) |
| 442 | return; |
| 443 | } |
Jonathan Tan | a7f7e84 | 2020-08-24 12:16:35 -0700 | [diff] [blame] | 444 | } |
Shawn O. Pearce | 4a438ca | 2008-07-13 22:07:45 -0400 | [diff] [blame] | 445 | } |
| 446 | |
Nguyễn Thái Ngọc Duy | 681b07d | 2012-05-23 21:09:46 +0700 | [diff] [blame] | 447 | static int is_delta_type(enum object_type type) |
| 448 | { |
| 449 | return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA); |
| 450 | } |
| 451 | |
Nguyễn Thái Ngọc Duy | da49a7d | 2016-07-13 17:44:02 +0200 | [diff] [blame] | 452 | static void *unpack_entry_data(off_t offset, unsigned long size, |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 453 | enum object_type type, struct object_id *oid) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 454 | { |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 455 | static char fixed_buf[8192]; |
Nicolas Pitre | 7ce4721 | 2010-04-12 12:12:06 -0400 | [diff] [blame] | 456 | int status; |
Junio C Hamano | ef49a7a | 2011-06-10 11:52:15 -0700 | [diff] [blame] | 457 | git_zstream stream; |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 458 | void *buf; |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 459 | git_hash_ctx c; |
Nguyễn Thái Ngọc Duy | 681b07d | 2012-05-23 21:09:46 +0700 | [diff] [blame] | 460 | char hdr[32]; |
| 461 | int hdrlen; |
| 462 | |
| 463 | if (!is_delta_type(type)) { |
Ævar Arnfjörð Bjarmason | b04cdea | 2022-02-05 00:48:25 +0100 | [diff] [blame] | 464 | hdrlen = format_object_header(hdr, sizeof(hdr), type, size); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 465 | the_hash_algo->init_fn(&c); |
| 466 | the_hash_algo->update_fn(&c, hdr, hdrlen); |
Nguyễn Thái Ngọc Duy | 681b07d | 2012-05-23 21:09:46 +0700 | [diff] [blame] | 467 | } else |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 468 | oid = NULL; |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 469 | if (type == OBJ_BLOB && size > big_file_threshold) |
| 470 | buf = fixed_buf; |
| 471 | else |
Duy Nguyen | a1e920a | 2014-12-08 15:17:55 +0100 | [diff] [blame] | 472 | buf = xmallocz(size); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 473 | |
| 474 | memset(&stream, 0, sizeof(stream)); |
Nicolas Pitre | 7ce4721 | 2010-04-12 12:12:06 -0400 | [diff] [blame] | 475 | git_inflate_init(&stream); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 476 | stream.next_out = buf; |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 477 | stream.avail_out = buf == fixed_buf ? sizeof(fixed_buf) : size; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 478 | |
Nicolas Pitre | 7ce4721 | 2010-04-12 12:12:06 -0400 | [diff] [blame] | 479 | do { |
Nguyễn Thái Ngọc Duy | 681b07d | 2012-05-23 21:09:46 +0700 | [diff] [blame] | 480 | unsigned char *last_out = stream.next_out; |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 481 | stream.next_in = fill(1); |
| 482 | stream.avail_in = input_len; |
Nicolas Pitre | 7ce4721 | 2010-04-12 12:12:06 -0400 | [diff] [blame] | 483 | status = git_inflate(&stream, 0); |
| 484 | use(input_len - stream.avail_in); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 485 | if (oid) |
| 486 | the_hash_algo->update_fn(&c, last_out, stream.next_out - last_out); |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 487 | if (buf == fixed_buf) { |
| 488 | stream.next_out = buf; |
| 489 | stream.avail_out = sizeof(fixed_buf); |
| 490 | } |
Nicolas Pitre | 7ce4721 | 2010-04-12 12:12:06 -0400 | [diff] [blame] | 491 | } while (status == Z_OK); |
| 492 | if (stream.total_out != size || status != Z_STREAM_END) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 493 | bad_object(offset, _("inflate returned %d"), status); |
Linus Torvalds | 39c6854 | 2009-01-07 19:54:47 -0800 | [diff] [blame] | 494 | git_inflate_end(&stream); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 495 | if (oid) |
brian m. carlson | 5951bf4 | 2021-04-26 01:02:53 +0000 | [diff] [blame] | 496 | the_hash_algo->final_oid_fn(oid, &c); |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 497 | return buf == fixed_buf ? NULL : buf; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 498 | } |
| 499 | |
Nguyễn Thái Ngọc Duy | 681b07d | 2012-05-23 21:09:46 +0700 | [diff] [blame] | 500 | static void *unpack_raw_entry(struct object_entry *obj, |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 501 | off_t *ofs_offset, |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 502 | struct object_id *ref_oid, |
| 503 | struct object_id *oid) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 504 | { |
Linus Torvalds | 48fb7de | 2009-06-17 17:22:27 -0700 | [diff] [blame] | 505 | unsigned char *p; |
| 506 | unsigned long size, c; |
Nicolas Pitre | d7dd022 | 2007-04-09 01:06:30 -0400 | [diff] [blame] | 507 | off_t base_offset; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 508 | unsigned shift; |
Nicolas Pitre | ee5743c | 2007-04-09 01:06:32 -0400 | [diff] [blame] | 509 | void *data; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 510 | |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 511 | obj->idx.offset = consumed_bytes; |
Stephen Boyd | 1e4cd68 | 2011-04-03 00:06:54 -0700 | [diff] [blame] | 512 | input_crc32 = crc32(0, NULL, 0); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 513 | |
| 514 | p = fill(1); |
| 515 | c = *p; |
| 516 | use(1); |
| 517 | obj->type = (c >> 4) & 7; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 518 | size = (c & 15); |
| 519 | shift = 4; |
| 520 | while (c & 0x80) { |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 521 | p = fill(1); |
| 522 | c = *p; |
| 523 | use(1); |
Linus Torvalds | 48fb7de | 2009-06-17 17:22:27 -0700 | [diff] [blame] | 524 | size += (c & 0x7f) << shift; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 525 | shift += 7; |
| 526 | } |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 527 | obj->size = size; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 528 | |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 529 | switch (obj->type) { |
Nicolas Pitre | eb32d23 | 2006-09-21 00:06:49 -0400 | [diff] [blame] | 530 | case OBJ_REF_DELTA: |
brian m. carlson | 92e2cab | 2021-04-26 01:02:50 +0000 | [diff] [blame] | 531 | oidread(ref_oid, fill(the_hash_algo->rawsz)); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 532 | use(the_hash_algo->rawsz); |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 533 | break; |
| 534 | case OBJ_OFS_DELTA: |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 535 | p = fill(1); |
| 536 | c = *p; |
| 537 | use(1); |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 538 | base_offset = c & 127; |
| 539 | while (c & 128) { |
| 540 | base_offset += 1; |
Nicolas Pitre | 8723f21 | 2007-04-09 01:06:29 -0400 | [diff] [blame] | 541 | if (!base_offset || MSB(base_offset, 7)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 542 | bad_object(obj->idx.offset, _("offset value overflow for delta base object")); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 543 | p = fill(1); |
| 544 | c = *p; |
| 545 | use(1); |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 546 | base_offset = (base_offset << 7) + (c & 127); |
| 547 | } |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 548 | *ofs_offset = obj->idx.offset - base_offset; |
| 549 | if (*ofs_offset <= 0 || *ofs_offset >= obj->idx.offset) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 550 | bad_object(obj->idx.offset, _("delta base offset is out of bound")); |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 551 | break; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 552 | case OBJ_COMMIT: |
| 553 | case OBJ_TREE: |
| 554 | case OBJ_BLOB: |
| 555 | case OBJ_TAG: |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 556 | break; |
| 557 | default: |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 558 | bad_object(obj->idx.offset, _("unknown object type %d"), obj->type); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 559 | } |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 560 | obj->hdr_size = consumed_bytes - obj->idx.offset; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 561 | |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 562 | data = unpack_entry_data(obj->idx.offset, obj->size, obj->type, oid); |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 563 | obj->idx.crc32 = input_crc32; |
Nicolas Pitre | ee5743c | 2007-04-09 01:06:32 -0400 | [diff] [blame] | 564 | return data; |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 565 | } |
| 566 | |
Nguyễn Thái Ngọc Duy | 8a2e163 | 2012-05-23 21:09:48 +0700 | [diff] [blame] | 567 | static void *unpack_data(struct object_entry *obj, |
| 568 | int (*consume)(const unsigned char *, unsigned long, void *), |
| 569 | void *cb_data) |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 570 | { |
Nicolas Pitre | a91ef6e | 2007-11-10 23:29:10 -0500 | [diff] [blame] | 571 | off_t from = obj[0].idx.offset + obj[0].hdr_size; |
Nguyễn Thái Ngọc Duy | 7171a0b | 2016-07-13 17:44:00 +0200 | [diff] [blame] | 572 | off_t len = obj[1].idx.offset - from; |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 573 | unsigned char *data, *inbuf; |
Junio C Hamano | ef49a7a | 2011-06-10 11:52:15 -0700 | [diff] [blame] | 574 | git_zstream stream; |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 575 | int status; |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 576 | |
Duy Nguyen | a1e920a | 2014-12-08 15:17:55 +0100 | [diff] [blame] | 577 | data = xmallocz(consume ? 64*1024 : obj->size); |
Nguyễn Thái Ngọc Duy | 7171a0b | 2016-07-13 17:44:00 +0200 | [diff] [blame] | 578 | inbuf = xmalloc((len < 64*1024) ? (int)len : 64*1024); |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 579 | |
| 580 | memset(&stream, 0, sizeof(stream)); |
| 581 | git_inflate_init(&stream); |
| 582 | stream.next_out = data; |
Nguyễn Thái Ngọc Duy | 8a2e163 | 2012-05-23 21:09:48 +0700 | [diff] [blame] | 583 | stream.avail_out = consume ? 64*1024 : obj->size; |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 584 | |
Shawn O. Pearce | a91d49c | 2007-02-27 23:47:19 -0500 | [diff] [blame] | 585 | do { |
Nguyễn Thái Ngọc Duy | 7171a0b | 2016-07-13 17:44:00 +0200 | [diff] [blame] | 586 | ssize_t n = (len < 64*1024) ? (ssize_t)len : 64*1024; |
Junio C Hamano | 53f52cd | 2014-06-03 12:06:42 -0700 | [diff] [blame] | 587 | n = xpread(get_thread_data()->pack_fd, inbuf, n, from); |
Samuel Tardieu | fb74243 | 2008-10-06 19:28:41 +0200 | [diff] [blame] | 588 | if (n < 0) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 589 | die_errno(_("cannot pread pack file")); |
Samuel Tardieu | fb74243 | 2008-10-06 19:28:41 +0200 | [diff] [blame] | 590 | if (!n) |
Nguyễn Thái Ngọc Duy | 7171a0b | 2016-07-13 17:44:00 +0200 | [diff] [blame] | 591 | die(Q_("premature end of pack file, %"PRIuMAX" byte missing", |
| 592 | "premature end of pack file, %"PRIuMAX" bytes missing", |
Ævar Arnfjörð Bjarmason | 6f69325 | 2022-03-07 16:27:07 +0100 | [diff] [blame] | 593 | len), |
Nguyễn Thái Ngọc Duy | 7171a0b | 2016-07-13 17:44:00 +0200 | [diff] [blame] | 594 | (uintmax_t)len); |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 595 | from += n; |
| 596 | len -= n; |
| 597 | stream.next_in = inbuf; |
| 598 | stream.avail_in = n; |
Jeff King | f8b0903 | 2012-07-04 03:12:14 -0400 | [diff] [blame] | 599 | if (!consume) |
| 600 | status = git_inflate(&stream, 0); |
| 601 | else { |
| 602 | do { |
| 603 | status = git_inflate(&stream, 0); |
| 604 | if (consume(data, stream.next_out - data, cb_data)) { |
| 605 | free(inbuf); |
| 606 | free(data); |
| 607 | return NULL; |
| 608 | } |
| 609 | stream.next_out = data; |
| 610 | stream.avail_out = 64*1024; |
| 611 | } while (status == Z_OK && stream.avail_in); |
Nguyễn Thái Ngọc Duy | 8a2e163 | 2012-05-23 21:09:48 +0700 | [diff] [blame] | 612 | } |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 613 | } while (len && status == Z_OK && !stream.avail_in); |
| 614 | |
| 615 | /* This has been inflated OK when first encountered, so... */ |
| 616 | if (status != Z_STREAM_END || stream.total_out != obj->size) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 617 | die(_("serious inflate inconsistency")); |
Nicolas Pitre | 776ea37 | 2010-04-12 12:11:07 -0400 | [diff] [blame] | 618 | |
| 619 | git_inflate_end(&stream); |
| 620 | free(inbuf); |
Nguyễn Thái Ngọc Duy | 8a2e163 | 2012-05-23 21:09:48 +0700 | [diff] [blame] | 621 | if (consume) { |
Ævar Arnfjörð Bjarmason | 6a83d90 | 2017-06-15 23:15:46 +0000 | [diff] [blame] | 622 | FREE_AND_NULL(data); |
Nguyễn Thái Ngọc Duy | 8a2e163 | 2012-05-23 21:09:48 +0700 | [diff] [blame] | 623 | } |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 624 | return data; |
| 625 | } |
| 626 | |
Nguyễn Thái Ngọc Duy | 8a2e163 | 2012-05-23 21:09:48 +0700 | [diff] [blame] | 627 | static void *get_data_from_pack(struct object_entry *obj) |
| 628 | { |
| 629 | return unpack_data(obj, NULL, NULL); |
| 630 | } |
| 631 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 632 | static int compare_ofs_delta_bases(off_t offset1, off_t offset2, |
| 633 | enum object_type type1, |
| 634 | enum object_type type2) |
Junio C Hamano | 7218a21 | 2011-02-02 10:06:51 -0800 | [diff] [blame] | 635 | { |
| 636 | int cmp = type1 - type2; |
| 637 | if (cmp) |
| 638 | return cmp; |
Jeff King | f0e7f11 | 2015-06-04 08:35:42 -0400 | [diff] [blame] | 639 | return offset1 < offset2 ? -1 : |
| 640 | offset1 > offset2 ? 1 : |
| 641 | 0; |
Junio C Hamano | 7218a21 | 2011-02-02 10:06:51 -0800 | [diff] [blame] | 642 | } |
| 643 | |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 644 | static int find_ofs_delta(const off_t offset) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 645 | { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 646 | int first = 0, last = nr_ofs_deltas; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 647 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 648 | while (first < last) { |
Derrick Stolee | 19716b2 | 2017-10-08 14:29:37 -0400 | [diff] [blame] | 649 | int next = first + (last - first) / 2; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 650 | struct ofs_delta_entry *delta = &ofs_deltas[next]; |
| 651 | int cmp; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 652 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 653 | cmp = compare_ofs_delta_bases(offset, delta->offset, |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 654 | OBJ_OFS_DELTA, |
| 655 | objects[delta->obj_no].type); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 656 | if (!cmp) |
| 657 | return next; |
| 658 | if (cmp < 0) { |
| 659 | last = next; |
| 660 | continue; |
| 661 | } |
| 662 | first = next+1; |
| 663 | } |
| 664 | return -first-1; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 665 | } |
| 666 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 667 | static void find_ofs_delta_children(off_t offset, |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 668 | int *first_index, int *last_index) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 669 | { |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 670 | int first = find_ofs_delta(offset); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 671 | int last = first; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 672 | int end = nr_ofs_deltas - 1; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 673 | |
Nicolas Pitre | 6a87ed9 | 2008-10-17 15:57:58 -0400 | [diff] [blame] | 674 | if (first < 0) { |
| 675 | *first_index = 0; |
| 676 | *last_index = -1; |
| 677 | return; |
| 678 | } |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 679 | while (first > 0 && ofs_deltas[first - 1].offset == offset) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 680 | --first; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 681 | while (last < end && ofs_deltas[last + 1].offset == offset) |
| 682 | ++last; |
| 683 | *first_index = first; |
| 684 | *last_index = last; |
| 685 | } |
| 686 | |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 687 | static int compare_ref_delta_bases(const struct object_id *oid1, |
| 688 | const struct object_id *oid2, |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 689 | enum object_type type1, |
| 690 | enum object_type type2) |
| 691 | { |
| 692 | int cmp = type1 - type2; |
| 693 | if (cmp) |
| 694 | return cmp; |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 695 | return oidcmp(oid1, oid2); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 696 | } |
| 697 | |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 698 | static int find_ref_delta(const struct object_id *oid) |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 699 | { |
| 700 | int first = 0, last = nr_ref_deltas; |
| 701 | |
| 702 | while (first < last) { |
Derrick Stolee | 19716b2 | 2017-10-08 14:29:37 -0400 | [diff] [blame] | 703 | int next = first + (last - first) / 2; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 704 | struct ref_delta_entry *delta = &ref_deltas[next]; |
| 705 | int cmp; |
| 706 | |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 707 | cmp = compare_ref_delta_bases(oid, &delta->oid, |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 708 | OBJ_REF_DELTA, |
| 709 | objects[delta->obj_no].type); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 710 | if (!cmp) |
| 711 | return next; |
| 712 | if (cmp < 0) { |
| 713 | last = next; |
| 714 | continue; |
| 715 | } |
| 716 | first = next+1; |
| 717 | } |
| 718 | return -first-1; |
| 719 | } |
| 720 | |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 721 | static void find_ref_delta_children(const struct object_id *oid, |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 722 | int *first_index, int *last_index) |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 723 | { |
Jonathan Tan | fc968e2 | 2020-08-24 12:16:33 -0700 | [diff] [blame] | 724 | int first = find_ref_delta(oid); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 725 | int last = first; |
| 726 | int end = nr_ref_deltas - 1; |
| 727 | |
| 728 | if (first < 0) { |
| 729 | *first_index = 0; |
| 730 | *last_index = -1; |
| 731 | return; |
| 732 | } |
Jeff King | 4a7e27e | 2018-08-28 17:22:40 -0400 | [diff] [blame] | 733 | while (first > 0 && oideq(&ref_deltas[first - 1].oid, oid)) |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 734 | --first; |
Jeff King | 4a7e27e | 2018-08-28 17:22:40 -0400 | [diff] [blame] | 735 | while (last < end && oideq(&ref_deltas[last + 1].oid, oid)) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 736 | ++last; |
| 737 | *first_index = first; |
| 738 | *last_index = last; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 739 | } |
| 740 | |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 741 | struct compare_data { |
| 742 | struct object_entry *entry; |
| 743 | struct git_istream *st; |
| 744 | unsigned char *buf; |
| 745 | unsigned long buf_size; |
| 746 | }; |
| 747 | |
| 748 | static int compare_objects(const unsigned char *buf, unsigned long size, |
| 749 | void *cb_data) |
| 750 | { |
| 751 | struct compare_data *data = cb_data; |
| 752 | |
| 753 | if (data->buf_size < size) { |
| 754 | free(data->buf); |
| 755 | data->buf = xmalloc(size); |
| 756 | data->buf_size = size; |
| 757 | } |
| 758 | |
| 759 | while (size) { |
| 760 | ssize_t len = read_istream(data->st, data->buf, size); |
| 761 | if (len == 0) |
| 762 | die(_("SHA1 COLLISION FOUND WITH %s !"), |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 763 | oid_to_hex(&data->entry->idx.oid)); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 764 | if (len < 0) |
| 765 | die(_("unable to read %s"), |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 766 | oid_to_hex(&data->entry->idx.oid)); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 767 | if (memcmp(buf, data->buf, len)) |
| 768 | die(_("SHA1 COLLISION FOUND WITH %s !"), |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 769 | oid_to_hex(&data->entry->idx.oid)); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 770 | size -= len; |
| 771 | buf += len; |
| 772 | } |
| 773 | return 0; |
| 774 | } |
| 775 | |
| 776 | static int check_collison(struct object_entry *entry) |
| 777 | { |
| 778 | struct compare_data data; |
| 779 | enum object_type type; |
| 780 | unsigned long size; |
| 781 | |
| 782 | if (entry->size <= big_file_threshold || entry->type != OBJ_BLOB) |
| 783 | return -1; |
| 784 | |
| 785 | memset(&data, 0, sizeof(data)); |
| 786 | data.entry = entry; |
Matheus Tavares | c8123e7 | 2020-01-30 17:32:20 -0300 | [diff] [blame] | 787 | data.st = open_istream(the_repository, &entry->idx.oid, &type, &size, |
| 788 | NULL); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 789 | if (!data.st) |
| 790 | return -1; |
| 791 | if (size != entry->size || type != entry->type) |
| 792 | die(_("SHA1 COLLISION FOUND WITH %s !"), |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 793 | oid_to_hex(&entry->idx.oid)); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 794 | unpack_data(entry, compare_objects, &data); |
| 795 | close_istream(data.st); |
| 796 | free(data.buf); |
| 797 | return 0; |
| 798 | } |
| 799 | |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 800 | static void sha1_object(const void *data, struct object_entry *obj_entry, |
| 801 | unsigned long size, enum object_type type, |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 802 | const struct object_id *oid) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 803 | { |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 804 | void *new_data = NULL; |
Jeff King | 29401e1 | 2016-12-16 16:43:22 -0500 | [diff] [blame] | 805 | int collision_test_needed = 0; |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 806 | |
| 807 | assert(data || obj_entry); |
| 808 | |
Jeff King | 29401e1 | 2016-12-16 16:43:22 -0500 | [diff] [blame] | 809 | if (startup_info->have_repository) { |
| 810 | read_lock(); |
Jonathan Tan | e83e71c | 2017-06-21 17:40:24 -0700 | [diff] [blame] | 811 | collision_test_needed = |
Ævar Arnfjörð Bjarmason | bc726bd | 2023-03-28 15:58:50 +0200 | [diff] [blame] | 812 | repo_has_object_file_with_flags(the_repository, oid, |
| 813 | OBJECT_INFO_QUICK); |
Jeff King | 29401e1 | 2016-12-16 16:43:22 -0500 | [diff] [blame] | 814 | read_unlock(); |
| 815 | } |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 816 | |
| 817 | if (collision_test_needed && !data) { |
| 818 | read_lock(); |
| 819 | if (!check_collison(obj_entry)) |
| 820 | collision_test_needed = 0; |
| 821 | read_unlock(); |
| 822 | } |
| 823 | if (collision_test_needed) { |
Nicolas Pitre | 8685da4 | 2007-03-20 15:32:35 -0400 | [diff] [blame] | 824 | void *has_data; |
| 825 | enum object_type has_type; |
| 826 | unsigned long has_size; |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 827 | read_lock(); |
Stefan Beller | 0df8e96 | 2018-04-25 11:20:59 -0700 | [diff] [blame] | 828 | has_type = oid_object_info(the_repository, oid, &has_size); |
Jeff King | 5105417 | 2017-04-01 04:09:32 -0400 | [diff] [blame] | 829 | if (has_type < 0) |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 830 | die(_("cannot read existing object info %s"), oid_to_hex(oid)); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 831 | if (has_type != type || has_size != size) |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 832 | die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid)); |
Ævar Arnfjörð Bjarmason | bc726bd | 2023-03-28 15:58:50 +0200 | [diff] [blame] | 833 | has_data = repo_read_object_file(the_repository, oid, |
| 834 | &has_type, &has_size); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 835 | read_unlock(); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 836 | if (!data) |
| 837 | data = new_data = get_data_from_pack(obj_entry); |
Nicolas Pitre | 8685da4 | 2007-03-20 15:32:35 -0400 | [diff] [blame] | 838 | if (!has_data) |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 839 | die(_("cannot read existing object %s"), oid_to_hex(oid)); |
Nicolas Pitre | 8685da4 | 2007-03-20 15:32:35 -0400 | [diff] [blame] | 840 | if (size != has_size || type != has_type || |
| 841 | memcmp(data, has_data, size) != 0) |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 842 | die(_("SHA1 COLLISION FOUND WITH %s !"), oid_to_hex(oid)); |
Nicolas Pitre | bbf4b41 | 2007-04-03 12:33:46 -0400 | [diff] [blame] | 843 | free(has_data); |
Nguyễn Thái Ngọc Duy | 4614043 | 2012-05-24 20:55:44 +0700 | [diff] [blame] | 844 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 845 | |
Jonathan Tan | ffb2c0f | 2018-03-14 11:42:40 -0700 | [diff] [blame] | 846 | if (strict || do_fsck_object) { |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 847 | read_lock(); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 848 | if (type == OBJ_BLOB) { |
Stefan Beller | da14a7f | 2018-06-28 18:21:55 -0700 | [diff] [blame] | 849 | struct blob *blob = lookup_blob(the_repository, oid); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 850 | if (blob) |
| 851 | blob->object.flags |= FLAG_CHECKED; |
| 852 | else |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 853 | die(_("invalid blob object %s"), oid_to_hex(oid)); |
Jeff King | 73c3f0f | 2018-05-04 19:45:01 -0400 | [diff] [blame] | 854 | if (do_fsck_object && |
| 855 | fsck_object(&blob->object, (void *)data, size, &fsck_options)) |
| 856 | die(_("fsck error in packed object")); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 857 | } else { |
| 858 | struct object *obj; |
| 859 | int eaten; |
| 860 | void *buf = (void *) data; |
| 861 | |
Nguyễn Thái Ngọc Duy | 920734b | 2013-05-26 08:16:16 +0700 | [diff] [blame] | 862 | assert(data && "data can only be NULL for large _blobs_"); |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 863 | |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 864 | /* |
| 865 | * we do not need to free the memory here, as the |
| 866 | * buf is deleted by the caller. |
| 867 | */ |
Stefan Beller | 1ec5bfd | 2018-06-28 18:21:53 -0700 | [diff] [blame] | 868 | obj = parse_object_buffer(the_repository, oid, type, |
| 869 | size, buf, |
brian m. carlson | c251c83 | 2017-05-06 22:10:38 +0000 | [diff] [blame] | 870 | &eaten); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 871 | if (!obj) |
Brandon Williams | debca9d | 2018-02-14 10:59:24 -0800 | [diff] [blame] | 872 | die(_("invalid %s"), type_name(type)); |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 873 | if (do_fsck_object && |
Johannes Schindelin | 2241054 | 2015-06-22 17:25:00 +0200 | [diff] [blame] | 874 | fsck_object(obj, buf, size, &fsck_options)) |
Jeff King | db5a58c | 2018-05-02 16:37:09 -0400 | [diff] [blame] | 875 | die(_("fsck error in packed object")); |
Jonathan Tan | ffb2c0f | 2018-03-14 11:42:40 -0700 | [diff] [blame] | 876 | if (strict && fsck_walk(obj, NULL, &fsck_options)) |
brian m. carlson | f2fd076 | 2015-11-10 02:22:28 +0000 | [diff] [blame] | 877 | die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid)); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 878 | |
| 879 | if (obj->type == OBJ_TREE) { |
| 880 | struct tree *item = (struct tree *) obj; |
| 881 | item->buffer = NULL; |
Jeff King | 6e454b9 | 2013-06-05 18:37:39 -0400 | [diff] [blame] | 882 | obj->parsed = 0; |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 883 | } |
| 884 | if (obj->type == OBJ_COMMIT) { |
| 885 | struct commit *commit = (struct commit *) obj; |
Jeff King | 8597ea3 | 2014-06-10 17:44:13 -0400 | [diff] [blame] | 886 | if (detach_commit_buffer(commit, NULL) != data) |
Johannes Schindelin | 033abf9 | 2018-05-02 11:38:39 +0200 | [diff] [blame] | 887 | BUG("parse_object_buffer transmogrified our buffer"); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 888 | } |
| 889 | obj->flags |= FLAG_CHECKED; |
| 890 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 891 | read_unlock(); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 892 | } |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 893 | |
| 894 | free(new_data); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 895 | } |
| 896 | |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 897 | /* |
Jonathan Tan | ec6a8f9 | 2020-10-07 13:16:58 -0700 | [diff] [blame] | 898 | * Ensure that this node has been reconstructed and return its contents. |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 899 | * |
Jonathan Tan | ec6a8f9 | 2020-10-07 13:16:58 -0700 | [diff] [blame] | 900 | * In the typical and best case, this node would already be reconstructed |
| 901 | * (through the invocation to resolve_delta() in threaded_second_pass()) and it |
| 902 | * would not be pruned. However, if pruning of this node was necessary due to |
| 903 | * reaching delta_base_cache_limit, this function will find the closest |
| 904 | * ancestor with reconstructed data that has not been pruned (or if there is |
| 905 | * none, the ultimate base object), and reconstruct each node in the delta |
| 906 | * chain in order to generate the reconstructed data for this node. |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 907 | */ |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 908 | static void *get_base_data(struct base_data *c) |
| 909 | { |
| 910 | if (!c->data) { |
| 911 | struct object_entry *obj = c->obj; |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 912 | struct base_data **delta = NULL; |
| 913 | int delta_nr = 0, delta_alloc = 0; |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 914 | |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 915 | while (is_delta_type(c->obj->type) && !c->data) { |
| 916 | ALLOC_GROW(delta, delta_nr + 1, delta_alloc); |
| 917 | delta[delta_nr++] = c; |
| 918 | c = c->base; |
| 919 | } |
| 920 | if (!delta_nr) { |
| 921 | c->data = get_data_from_pack(obj); |
| 922 | c->size = obj->size; |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 923 | base_cache_used += c->size; |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 924 | prune_base_data(c); |
| 925 | } |
| 926 | for (; delta_nr > 0; delta_nr--) { |
| 927 | void *base, *raw; |
| 928 | c = delta[delta_nr - 1]; |
| 929 | obj = c->obj; |
| 930 | base = get_base_data(c->base); |
| 931 | raw = get_data_from_pack(obj); |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 932 | c->data = patch_delta( |
| 933 | base, c->base->size, |
| 934 | raw, obj->size, |
| 935 | &c->size); |
| 936 | free(raw); |
| 937 | if (!c->data) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 938 | bad_object(obj->idx.offset, _("failed to apply delta")); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 939 | base_cache_used += c->size; |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 940 | prune_base_data(c); |
Nicolas Pitre | 9441b61 | 2008-10-17 15:57:57 -0400 | [diff] [blame] | 941 | } |
Nguyễn Thái Ngọc Duy | 20e95d0 | 2012-01-14 19:19:55 +0700 | [diff] [blame] | 942 | free(delta); |
Shawn O. Pearce | 92392b4 | 2008-07-15 04:45:34 +0000 | [diff] [blame] | 943 | } |
| 944 | return c->data; |
| 945 | } |
| 946 | |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 947 | static struct base_data *make_base(struct object_entry *obj, |
| 948 | struct base_data *parent) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 949 | { |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 950 | struct base_data *base = xcalloc(1, sizeof(struct base_data)); |
| 951 | base->base = parent; |
| 952 | base->obj = obj; |
| 953 | find_ref_delta_children(&obj->idx.oid, |
| 954 | &base->ref_first, &base->ref_last); |
| 955 | find_ofs_delta_children(obj->idx.offset, |
| 956 | &base->ofs_first, &base->ofs_last); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 957 | base->children_remaining = base->ref_last - base->ref_first + |
| 958 | base->ofs_last - base->ofs_first + 2; |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 959 | return base; |
| 960 | } |
| 961 | |
| 962 | static struct base_data *resolve_delta(struct object_entry *delta_obj, |
| 963 | struct base_data *base) |
| 964 | { |
Jonathan Tan | ee6f058 | 2020-08-24 12:16:37 -0700 | [diff] [blame] | 965 | void *delta_data, *result_data; |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 966 | struct base_data *result; |
| 967 | unsigned long result_size; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 968 | |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 969 | if (show_stat) { |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 970 | int i = delta_obj - objects; |
| 971 | int j = base->obj - objects; |
| 972 | obj_stat[i].delta_depth = obj_stat[j].delta_depth + 1; |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 973 | deepest_delta_lock(); |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 974 | if (deepest_delta < obj_stat[i].delta_depth) |
| 975 | deepest_delta = obj_stat[i].delta_depth; |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 976 | deepest_delta_unlock(); |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 977 | obj_stat[i].base_object_no = j; |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 978 | } |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 979 | delta_data = get_data_from_pack(delta_obj); |
Jonathan Tan | ee6f058 | 2020-08-24 12:16:37 -0700 | [diff] [blame] | 980 | assert(base->data); |
| 981 | result_data = patch_delta(base->data, base->size, |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 982 | delta_data, delta_obj->size, &result_size); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 983 | free(delta_data); |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 984 | if (!result_data) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 985 | bad_object(delta_obj->idx.offset, _("failed to apply delta")); |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 986 | hash_object_file(the_hash_algo, result_data, result_size, |
Ævar Arnfjörð Bjarmason | 44439c1 | 2022-02-05 00:48:32 +0100 | [diff] [blame] | 987 | delta_obj->real_type, &delta_obj->idx.oid); |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 988 | sha1_object(result_data, NULL, result_size, delta_obj->real_type, |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 989 | &delta_obj->idx.oid); |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 990 | |
| 991 | result = make_base(delta_obj, base); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 992 | result->data = result_data; |
| 993 | result->size = result_size; |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 994 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 995 | counter_lock(); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 996 | nr_resolved_deltas++; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 997 | counter_unlock(); |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 998 | |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 999 | return result; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1000 | } |
| 1001 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1002 | static int compare_ofs_delta_entry(const void *a, const void *b) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1003 | { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1004 | const struct ofs_delta_entry *delta_a = a; |
| 1005 | const struct ofs_delta_entry *delta_b = b; |
Junio C Hamano | 7218a21 | 2011-02-02 10:06:51 -0800 | [diff] [blame] | 1006 | |
Jeff King | f0e7f11 | 2015-06-04 08:35:42 -0400 | [diff] [blame] | 1007 | return delta_a->offset < delta_b->offset ? -1 : |
| 1008 | delta_a->offset > delta_b->offset ? 1 : |
| 1009 | 0; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1010 | } |
| 1011 | |
| 1012 | static int compare_ref_delta_entry(const void *a, const void *b) |
| 1013 | { |
| 1014 | const struct ref_delta_entry *delta_a = a; |
| 1015 | const struct ref_delta_entry *delta_b = b; |
| 1016 | |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 1017 | return oidcmp(&delta_a->oid, &delta_b->oid); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1018 | } |
| 1019 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1020 | static void *threaded_second_pass(void *data) |
| 1021 | { |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1022 | if (data) |
| 1023 | set_thread_data(data); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1024 | for (;;) { |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1025 | struct base_data *parent = NULL; |
| 1026 | struct object_entry *child_obj; |
| 1027 | struct base_data *child; |
| 1028 | |
Jeff King | cea6915 | 2020-10-07 14:19:23 -0400 | [diff] [blame] | 1029 | counter_lock(); |
| 1030 | display_progress(progress, nr_resolved_deltas); |
| 1031 | counter_unlock(); |
| 1032 | |
Thomas Rast | 8f82aad | 2013-03-19 15:16:41 +0100 | [diff] [blame] | 1033 | work_lock(); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1034 | if (list_empty(&work_head)) { |
| 1035 | /* |
| 1036 | * Take an object from the object array. |
| 1037 | */ |
| 1038 | while (nr_dispatched < nr_objects && |
| 1039 | is_delta_type(objects[nr_dispatched].type)) |
| 1040 | nr_dispatched++; |
| 1041 | if (nr_dispatched >= nr_objects) { |
| 1042 | work_unlock(); |
| 1043 | break; |
| 1044 | } |
| 1045 | child_obj = &objects[nr_dispatched++]; |
| 1046 | } else { |
| 1047 | /* |
| 1048 | * Peek at the top of the stack, and take a child from |
| 1049 | * it. |
| 1050 | */ |
| 1051 | parent = list_first_entry(&work_head, struct base_data, |
| 1052 | list); |
| 1053 | |
| 1054 | if (parent->ref_first <= parent->ref_last) { |
| 1055 | int offset = ref_deltas[parent->ref_first++].obj_no; |
| 1056 | child_obj = objects + offset; |
| 1057 | if (child_obj->real_type != OBJ_REF_DELTA) |
| 1058 | die("REF_DELTA at offset %"PRIuMAX" already resolved (duplicate base %s?)", |
| 1059 | (uintmax_t) child_obj->idx.offset, |
| 1060 | oid_to_hex(&parent->obj->idx.oid)); |
| 1061 | child_obj->real_type = parent->obj->real_type; |
| 1062 | } else { |
| 1063 | child_obj = objects + |
| 1064 | ofs_deltas[parent->ofs_first++].obj_no; |
| 1065 | assert(child_obj->real_type == OBJ_OFS_DELTA); |
| 1066 | child_obj->real_type = parent->obj->real_type; |
| 1067 | } |
| 1068 | |
| 1069 | if (parent->ref_first > parent->ref_last && |
| 1070 | parent->ofs_first > parent->ofs_last) { |
| 1071 | /* |
| 1072 | * This parent has run out of children, so move |
| 1073 | * it to done_head. |
| 1074 | */ |
| 1075 | list_del(&parent->list); |
| 1076 | list_add(&parent->list, &done_head); |
| 1077 | } |
| 1078 | |
| 1079 | /* |
| 1080 | * Ensure that the parent has data, since we will need |
| 1081 | * it later. |
| 1082 | * |
| 1083 | * NEEDSWORK: If parent data needs to be reloaded, this |
| 1084 | * prolongs the time that the current thread spends in |
| 1085 | * the mutex. A mitigating factor is that parent data |
| 1086 | * needs to be reloaded only if the delta base cache |
| 1087 | * limit is exceeded, so in the typical case, this does |
| 1088 | * not happen. |
| 1089 | */ |
| 1090 | get_base_data(parent); |
| 1091 | parent->retain_data++; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1092 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1093 | work_unlock(); |
| 1094 | |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1095 | if (parent) { |
| 1096 | child = resolve_delta(child_obj, parent); |
| 1097 | if (!child->children_remaining) |
| 1098 | FREE_AND_NULL(child->data); |
| 1099 | } else { |
| 1100 | child = make_base(child_obj, NULL); |
| 1101 | if (child->children_remaining) { |
| 1102 | /* |
| 1103 | * Since this child has its own delta children, |
| 1104 | * we will need this data in the future. |
| 1105 | * Inflate now so that future iterations will |
| 1106 | * have access to this object's data while |
| 1107 | * outside the work mutex. |
| 1108 | */ |
| 1109 | child->data = get_data_from_pack(child_obj); |
| 1110 | child->size = child_obj->size; |
| 1111 | } |
| 1112 | } |
| 1113 | |
| 1114 | work_lock(); |
| 1115 | if (parent) |
| 1116 | parent->retain_data--; |
| 1117 | if (child->data) { |
| 1118 | /* |
| 1119 | * This child has its own children, so add it to |
| 1120 | * work_head. |
| 1121 | */ |
| 1122 | list_add(&child->list, &work_head); |
| 1123 | base_cache_used += child->size; |
| 1124 | prune_base_data(NULL); |
Ævar Arnfjörð Bjarmason | f2bcc69 | 2022-03-04 19:32:04 +0100 | [diff] [blame] | 1125 | free_base_data(child); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1126 | } else { |
| 1127 | /* |
| 1128 | * This child does not have its own children. It may be |
| 1129 | * the last descendant of its ancestors; free those |
| 1130 | * that we can. |
| 1131 | */ |
| 1132 | struct base_data *p = parent; |
| 1133 | |
| 1134 | while (p) { |
| 1135 | struct base_data *next_p; |
| 1136 | |
| 1137 | p->children_remaining--; |
| 1138 | if (p->children_remaining) |
| 1139 | break; |
| 1140 | |
| 1141 | next_p = p->base; |
| 1142 | free_base_data(p); |
| 1143 | list_del(&p->list); |
| 1144 | free(p); |
| 1145 | |
| 1146 | p = next_p; |
| 1147 | } |
Ævar Arnfjörð Bjarmason | f2bcc69 | 2022-03-04 19:32:04 +0100 | [diff] [blame] | 1148 | FREE_AND_NULL(child); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1149 | } |
| 1150 | work_unlock(); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1151 | } |
| 1152 | return NULL; |
| 1153 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1154 | |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1155 | /* |
| 1156 | * First pass: |
| 1157 | * - find locations of all objects; |
| 1158 | * - calculate SHA1 of all non-delta objects; |
| 1159 | * - remember base (SHA1 or offset) for all deltas. |
| 1160 | */ |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1161 | static void parse_pack_objects(unsigned char *hash) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1162 | { |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 1163 | int i, nr_delays = 0; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1164 | struct ofs_delta_entry *ofs_delta = ofs_deltas; |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1165 | struct object_id ref_delta_oid; |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 1166 | struct stat st; |
Eric Wong | e0b8c84 | 2023-09-01 02:09:28 +0000 | [diff] [blame] | 1167 | git_hash_ctx tmp_ctx; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1168 | |
Nicolas Pitre | 13aaf14 | 2007-04-20 14:10:07 -0400 | [diff] [blame] | 1169 | if (verbose) |
Nicolas Pitre | 29e63ed | 2007-10-30 14:57:35 -0400 | [diff] [blame] | 1170 | progress = start_progress( |
Ævar Arnfjörð Bjarmason | f46c46e | 2021-09-05 09:34:44 +0200 | [diff] [blame] | 1171 | progress_title ? progress_title : |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1172 | from_stdin ? _("Receiving objects") : _("Indexing objects"), |
Nicolas Pitre | 29e63ed | 2007-10-30 14:57:35 -0400 | [diff] [blame] | 1173 | nr_objects); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1174 | for (i = 0; i < nr_objects; i++) { |
| 1175 | struct object_entry *obj = &objects[i]; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1176 | void *data = unpack_raw_entry(obj, &ofs_delta->offset, |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1177 | &ref_delta_oid, |
| 1178 | &obj->idx.oid); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1179 | obj->real_type = obj->type; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1180 | if (obj->type == OBJ_OFS_DELTA) { |
| 1181 | nr_ofs_deltas++; |
| 1182 | ofs_delta->obj_no = i; |
| 1183 | ofs_delta++; |
| 1184 | } else if (obj->type == OBJ_REF_DELTA) { |
| 1185 | ALLOC_GROW(ref_deltas, nr_ref_deltas + 1, ref_deltas_alloc); |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 1186 | oidcpy(&ref_deltas[nr_ref_deltas].oid, &ref_delta_oid); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1187 | ref_deltas[nr_ref_deltas].obj_no = i; |
| 1188 | nr_ref_deltas++; |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 1189 | } else if (!data) { |
| 1190 | /* large blobs, check later */ |
| 1191 | obj->real_type = OBJ_BAD; |
| 1192 | nr_delays++; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1193 | } else |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 1194 | sha1_object(data, NULL, obj->size, obj->type, |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 1195 | &obj->idx.oid); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1196 | free(data); |
Nicolas Pitre | 4d4fcc5 | 2007-10-30 14:57:33 -0400 | [diff] [blame] | 1197 | display_progress(progress, i+1); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1198 | } |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 1199 | objects[i].idx.offset = consumed_bytes; |
Nicolas Pitre | 4d4fcc5 | 2007-10-30 14:57:33 -0400 | [diff] [blame] | 1200 | stop_progress(&progress); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 1201 | |
| 1202 | /* Check pack integrity */ |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1203 | flush(); |
Eric Wong | e0b8c84 | 2023-09-01 02:09:28 +0000 | [diff] [blame] | 1204 | the_hash_algo->init_fn(&tmp_ctx); |
| 1205 | the_hash_algo->clone_fn(&tmp_ctx, &input_ctx); |
| 1206 | the_hash_algo->final_fn(hash, &tmp_ctx); |
Jeff King | 67947c3 | 2018-08-28 17:22:52 -0400 | [diff] [blame] | 1207 | if (!hasheq(fill(the_hash_algo->rawsz), hash)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1208 | die(_("pack is corrupted (SHA1 mismatch)")); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1209 | use(the_hash_algo->rawsz); |
Nicolas Pitre | 2d47705 | 2006-10-20 14:45:21 -0400 | [diff] [blame] | 1210 | |
| 1211 | /* If input_fd is a file, we should have reached its end now. */ |
| 1212 | if (fstat(input_fd, &st)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1213 | die_errno(_("cannot fstat packfile")); |
Johannes Schindelin | fa257b0 | 2007-02-22 19:14:14 +0100 | [diff] [blame] | 1214 | if (S_ISREG(st.st_mode) && |
| 1215 | lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1216 | die(_("pack has junk at the end")); |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 1217 | |
| 1218 | for (i = 0; i < nr_objects; i++) { |
| 1219 | struct object_entry *obj = &objects[i]; |
| 1220 | if (obj->real_type != OBJ_BAD) |
| 1221 | continue; |
| 1222 | obj->real_type = obj->type; |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 1223 | sha1_object(NULL, obj, obj->size, obj->type, |
brian m. carlson | 3e93098 | 2017-05-06 22:10:13 +0000 | [diff] [blame] | 1224 | &obj->idx.oid); |
Nguyễn Thái Ngọc Duy | 9ec2dde | 2012-05-23 21:09:47 +0700 | [diff] [blame] | 1225 | nr_delays--; |
| 1226 | } |
| 1227 | if (nr_delays) |
| 1228 | die(_("confusion beyond insanity in parse_pack_objects()")); |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1229 | } |
| 1230 | |
| 1231 | /* |
| 1232 | * Second pass: |
| 1233 | * - for all non-delta objects, look if it is used as a base for |
| 1234 | * deltas; |
| 1235 | * - if used as a base, uncompress the object and apply all deltas, |
| 1236 | * recursively checking if the resulting object is used as a base |
| 1237 | * for some more deltas. |
| 1238 | */ |
| 1239 | static void resolve_deltas(void) |
| 1240 | { |
| 1241 | int i; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1242 | |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1243 | if (!nr_ofs_deltas && !nr_ref_deltas) |
Nicolas Pitre | 3c9af36 | 2006-10-25 23:32:59 -0400 | [diff] [blame] | 1244 | return; |
| 1245 | |
Nicolas Pitre | 53dda6f | 2006-09-21 00:08:33 -0400 | [diff] [blame] | 1246 | /* Sort deltas by base SHA1/offset for fast searching */ |
René Scharfe | 9ed0d8d | 2016-09-29 17:27:31 +0200 | [diff] [blame] | 1247 | QSORT(ofs_deltas, nr_ofs_deltas, compare_ofs_delta_entry); |
| 1248 | QSORT(ref_deltas, nr_ref_deltas, compare_ref_delta_entry); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1249 | |
Jeff King | e376f17 | 2016-07-15 06:34:22 -0400 | [diff] [blame] | 1250 | if (verbose || show_resolving_progress) |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1251 | progress = start_progress(_("Resolving deltas"), |
| 1252 | nr_ref_deltas + nr_ofs_deltas); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1253 | |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1254 | nr_dispatched = 0; |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1255 | base_cache_limit = delta_base_cache_limit * nr_threads; |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1256 | if (nr_threads > 1 || getenv("GIT_FORCE_THREADS")) { |
| 1257 | init_thread(); |
Jeff King | 993d38a | 2024-01-05 03:50:34 -0500 | [diff] [blame] | 1258 | work_lock(); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1259 | for (i = 0; i < nr_threads; i++) { |
| 1260 | int ret = pthread_create(&thread_data[i].thread, NULL, |
| 1261 | threaded_second_pass, thread_data + i); |
| 1262 | if (ret) |
Nguyễn Thái Ngọc Duy | f350df4 | 2012-08-31 19:13:04 +0700 | [diff] [blame] | 1263 | die(_("unable to create thread: %s"), |
| 1264 | strerror(ret)); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1265 | } |
Jeff King | 993d38a | 2024-01-05 03:50:34 -0500 | [diff] [blame] | 1266 | work_unlock(); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1267 | for (i = 0; i < nr_threads; i++) |
| 1268 | pthread_join(thread_data[i].thread, NULL); |
| 1269 | cleanup_thread(); |
| 1270 | return; |
| 1271 | } |
Jonathan Tan | 46e6fb1 | 2020-08-24 12:16:34 -0700 | [diff] [blame] | 1272 | threaded_second_pass(¬hread_data); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1273 | } |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1274 | |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1275 | /* |
| 1276 | * Third pass: |
| 1277 | * - append objects to convert thin pack to full pack if required |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1278 | * - write the final pack hash |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1279 | */ |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1280 | static void fix_unresolved_deltas(struct hashfile *f); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1281 | static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned char *pack_hash) |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1282 | { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1283 | if (nr_ref_deltas + nr_ofs_deltas == nr_resolved_deltas) { |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1284 | stop_progress(&progress); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1285 | /* Flush remaining pack final hash. */ |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1286 | flush(); |
| 1287 | return; |
| 1288 | } |
| 1289 | |
| 1290 | if (fix_thin_pack) { |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1291 | struct hashfile *f; |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1292 | unsigned char read_hash[GIT_MAX_RAWSZ], tail_hash[GIT_MAX_RAWSZ]; |
Nguyễn Thái Ngọc Duy | 5c3459f | 2013-03-16 08:25:18 +0700 | [diff] [blame] | 1293 | struct strbuf msg = STRBUF_INIT; |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1294 | int nr_unresolved = nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas; |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1295 | int nr_objects_initial = nr_objects; |
| 1296 | if (nr_unresolved <= 0) |
Junio C Hamano | cc13431 | 2012-05-14 11:50:40 -0700 | [diff] [blame] | 1297 | die(_("confusion beyond insanity")); |
René Scharfe | 2756ca4 | 2014-09-16 20:56:57 +0200 | [diff] [blame] | 1298 | REALLOC_ARRAY(objects, nr_objects + nr_unresolved + 1); |
Jeff King | 57165db | 2013-03-19 12:17:22 -0400 | [diff] [blame] | 1299 | memset(objects + nr_objects + 1, 0, |
| 1300 | nr_unresolved * sizeof(*objects)); |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1301 | f = hashfd(output_fd, curr_pack); |
Junio C Hamano | 781d930 | 2015-07-03 09:51:57 -0700 | [diff] [blame] | 1302 | fix_unresolved_deltas(f); |
Vasco Almeida | 71d99b8 | 2016-04-08 20:02:39 +0000 | [diff] [blame] | 1303 | strbuf_addf(&msg, Q_("completed with %d local object", |
| 1304 | "completed with %d local objects", |
| 1305 | nr_objects - nr_objects_initial), |
Nguyễn Thái Ngọc Duy | 5c3459f | 2013-03-16 08:25:18 +0700 | [diff] [blame] | 1306 | nr_objects - nr_objects_initial); |
| 1307 | stop_progress_msg(&progress, msg.buf); |
| 1308 | strbuf_release(&msg); |
Neeraj Singh | 020406e | 2022-03-10 22:43:21 +0000 | [diff] [blame] | 1309 | finalize_hashfile(f, tail_hash, FSYNC_COMPONENT_PACK, 0); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1310 | hashcpy(read_hash, pack_hash); |
| 1311 | fixup_pack_header_footer(output_fd, pack_hash, |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1312 | curr_pack, nr_objects, |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1313 | read_hash, consumed_bytes-the_hash_algo->rawsz); |
Jeff King | 67947c3 | 2018-08-28 17:22:52 -0400 | [diff] [blame] | 1314 | if (!hasheq(read_hash, tail_hash)) |
Nguyễn Thái Ngọc Duy | f350df4 | 2012-08-31 19:13:04 +0700 | [diff] [blame] | 1315 | die(_("Unexpected tail checksum for %s " |
| 1316 | "(disk corruption?)"), curr_pack); |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1317 | } |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1318 | if (nr_ofs_deltas + nr_ref_deltas != nr_resolved_deltas) |
Junio C Hamano | cc13431 | 2012-05-14 11:50:40 -0700 | [diff] [blame] | 1319 | die(Q_("pack has %d unresolved delta", |
| 1320 | "pack has %d unresolved deltas", |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1321 | nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas), |
| 1322 | nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas); |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1323 | } |
| 1324 | |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1325 | static int write_compressed(struct hashfile *f, void *in, unsigned int size) |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1326 | { |
Junio C Hamano | ef49a7a | 2011-06-10 11:52:15 -0700 | [diff] [blame] | 1327 | git_zstream stream; |
Nicolas Pitre | 7734d7f | 2010-04-12 16:50:35 -0400 | [diff] [blame] | 1328 | int status; |
| 1329 | unsigned char outbuf[4096]; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1330 | |
Junio C Hamano | 55bb5c9 | 2011-06-10 10:55:10 -0700 | [diff] [blame] | 1331 | git_deflate_init(&stream, zlib_compression_level); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1332 | stream.next_in = in; |
| 1333 | stream.avail_in = size; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1334 | |
Nicolas Pitre | 7734d7f | 2010-04-12 16:50:35 -0400 | [diff] [blame] | 1335 | do { |
| 1336 | stream.next_out = outbuf; |
| 1337 | stream.avail_out = sizeof(outbuf); |
Junio C Hamano | 55bb5c9 | 2011-06-10 10:55:10 -0700 | [diff] [blame] | 1338 | status = git_deflate(&stream, Z_FINISH); |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1339 | hashwrite(f, outbuf, sizeof(outbuf) - stream.avail_out); |
Nicolas Pitre | 7734d7f | 2010-04-12 16:50:35 -0400 | [diff] [blame] | 1340 | } while (status == Z_OK); |
| 1341 | |
| 1342 | if (status != Z_STREAM_END) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1343 | die(_("unable to deflate appended object (%d)"), status); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1344 | size = stream.total_out; |
Junio C Hamano | 55bb5c9 | 2011-06-10 10:55:10 -0700 | [diff] [blame] | 1345 | git_deflate_end(&stream); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1346 | return size; |
| 1347 | } |
| 1348 | |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1349 | static struct object_entry *append_obj_to_pack(struct hashfile *f, |
Shawn O. Pearce | 03993e1 | 2008-07-13 22:07:46 -0400 | [diff] [blame] | 1350 | const unsigned char *sha1, void *buf, |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1351 | unsigned long size, enum object_type type) |
| 1352 | { |
| 1353 | struct object_entry *obj = &objects[nr_objects++]; |
| 1354 | unsigned char header[10]; |
| 1355 | unsigned long s = size; |
| 1356 | int n = 0; |
| 1357 | unsigned char c = (type << 4) | (s & 15); |
| 1358 | s >>= 4; |
| 1359 | while (s) { |
| 1360 | header[n++] = c | 0x80; |
| 1361 | c = s & 0x7f; |
| 1362 | s >>= 7; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1363 | } |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1364 | header[n++] = c; |
Nicolas Pitre | 8522148 | 2008-08-29 16:08:01 -0400 | [diff] [blame] | 1365 | crc32_begin(f); |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1366 | hashwrite(f, header, n); |
Björn Steinbrink | 72de288 | 2008-07-24 18:32:00 +0100 | [diff] [blame] | 1367 | obj[0].size = size; |
| 1368 | obj[0].hdr_size = n; |
| 1369 | obj[0].type = type; |
| 1370 | obj[0].real_type = type; |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 1371 | obj[1].idx.offset = obj[0].idx.offset + n; |
Nicolas Pitre | 8522148 | 2008-08-29 16:08:01 -0400 | [diff] [blame] | 1372 | obj[1].idx.offset += write_compressed(f, buf, size); |
| 1373 | obj[0].idx.crc32 = crc32_end(f); |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1374 | hashflush(f); |
brian m. carlson | 92e2cab | 2021-04-26 01:02:50 +0000 | [diff] [blame] | 1375 | oidread(&obj->idx.oid, sha1); |
Shawn O. Pearce | 03993e1 | 2008-07-13 22:07:46 -0400 | [diff] [blame] | 1376 | return obj; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1377 | } |
| 1378 | |
| 1379 | static int delta_pos_compare(const void *_a, const void *_b) |
| 1380 | { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1381 | struct ref_delta_entry *a = *(struct ref_delta_entry **)_a; |
| 1382 | struct ref_delta_entry *b = *(struct ref_delta_entry **)_b; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1383 | return a->obj_no - b->obj_no; |
| 1384 | } |
| 1385 | |
brian m. carlson | 98a3bea | 2018-02-01 02:18:46 +0000 | [diff] [blame] | 1386 | static void fix_unresolved_deltas(struct hashfile *f) |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1387 | { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1388 | struct ref_delta_entry **sorted_by_pos; |
Junio C Hamano | 781d930 | 2015-07-03 09:51:57 -0700 | [diff] [blame] | 1389 | int i; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1390 | |
| 1391 | /* |
| 1392 | * Since many unresolved deltas may well be themselves base objects |
| 1393 | * for more unresolved deltas, we really want to include the |
| 1394 | * smallest number of base objects that would cover as much delta |
| 1395 | * as possible by picking the |
| 1396 | * trunc deltas first, allowing for other deltas to resolve without |
| 1397 | * additional base objects. Since most base objects are to be found |
| 1398 | * before deltas depending on them, a good heuristic is to start |
| 1399 | * resolving deltas in the same order as their position in the pack. |
| 1400 | */ |
Jeff King | b32fa95 | 2016-02-22 17:44:25 -0500 | [diff] [blame] | 1401 | ALLOC_ARRAY(sorted_by_pos, nr_ref_deltas); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1402 | for (i = 0; i < nr_ref_deltas; i++) |
Junio C Hamano | 781d930 | 2015-07-03 09:51:57 -0700 | [diff] [blame] | 1403 | sorted_by_pos[i] = &ref_deltas[i]; |
René Scharfe | 9ed0d8d | 2016-09-29 17:27:31 +0200 | [diff] [blame] | 1404 | QSORT(sorted_by_pos, nr_ref_deltas, delta_pos_compare); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1405 | |
Ævar Arnfjörð Bjarmason | a5183d7 | 2023-03-28 15:58:53 +0200 | [diff] [blame] | 1406 | if (repo_has_promisor_remote(the_repository)) { |
Jonathan Tan | 8a30a1e | 2019-05-14 14:10:55 -0700 | [diff] [blame] | 1407 | /* |
| 1408 | * Prefetch the delta bases. |
| 1409 | */ |
| 1410 | struct oid_array to_fetch = OID_ARRAY_INIT; |
| 1411 | for (i = 0; i < nr_ref_deltas; i++) { |
| 1412 | struct ref_delta_entry *d = sorted_by_pos[i]; |
| 1413 | if (!oid_object_info_extended(the_repository, &d->oid, |
| 1414 | NULL, |
| 1415 | OBJECT_INFO_FOR_PREFETCH)) |
| 1416 | continue; |
| 1417 | oid_array_append(&to_fetch, &d->oid); |
| 1418 | } |
Jonathan Tan | db7ed74 | 2020-04-02 12:19:16 -0700 | [diff] [blame] | 1419 | promisor_remote_get_direct(the_repository, |
| 1420 | to_fetch.oid, to_fetch.nr); |
Jonathan Tan | 8a30a1e | 2019-05-14 14:10:55 -0700 | [diff] [blame] | 1421 | oid_array_clear(&to_fetch); |
| 1422 | } |
| 1423 | |
Junio C Hamano | 781d930 | 2015-07-03 09:51:57 -0700 | [diff] [blame] | 1424 | for (i = 0; i < nr_ref_deltas; i++) { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1425 | struct ref_delta_entry *d = sorted_by_pos[i]; |
Nicolas Pitre | 21666f1 | 2007-02-26 14:55:59 -0500 | [diff] [blame] | 1426 | enum object_type type; |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 1427 | void *data; |
| 1428 | unsigned long size; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1429 | |
| 1430 | if (objects[d->obj_no].real_type != OBJ_REF_DELTA) |
| 1431 | continue; |
Ævar Arnfjörð Bjarmason | bc726bd | 2023-03-28 15:58:50 +0200 | [diff] [blame] | 1432 | data = repo_read_object_file(the_repository, &d->oid, &type, |
| 1433 | &size); |
Jonathan Tan | b4718ca | 2020-08-24 12:16:36 -0700 | [diff] [blame] | 1434 | if (!data) |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1435 | continue; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1436 | |
Ævar Arnfjörð Bjarmason | ee213de | 2022-02-05 00:48:29 +0100 | [diff] [blame] | 1437 | if (check_object_signature(the_repository, &d->oid, data, size, |
Ævar Arnfjörð Bjarmason | 44439c1 | 2022-02-05 00:48:32 +0100 | [diff] [blame] | 1438 | type) < 0) |
brian m. carlson | af8caf3 | 2018-03-12 02:27:37 +0000 | [diff] [blame] | 1439 | die(_("local object %s is corrupt"), oid_to_hex(&d->oid)); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1440 | |
| 1441 | /* |
| 1442 | * Add this as an object to the objects array and call |
| 1443 | * threaded_second_pass() (which will pick up the added |
| 1444 | * object). |
| 1445 | */ |
| 1446 | append_obj_to_pack(f, d->oid.hash, data, size, type); |
Ævar Arnfjörð Bjarmason | f2bcc69 | 2022-03-04 19:32:04 +0100 | [diff] [blame] | 1447 | free(data); |
Jonathan Tan | f08cbf6 | 2020-09-08 12:48:35 -0700 | [diff] [blame] | 1448 | threaded_second_pass(NULL); |
| 1449 | |
Nicolas Pitre | 4d4fcc5 | 2007-10-30 14:57:33 -0400 | [diff] [blame] | 1450 | display_progress(progress, nr_resolved_deltas); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1451 | } |
| 1452 | free(sorted_by_pos); |
| 1453 | } |
| 1454 | |
Taylor Blau | 84d5449 | 2021-01-25 18:37:22 -0500 | [diff] [blame] | 1455 | static const char *derive_filename(const char *pack_name, const char *strip, |
| 1456 | const char *suffix, struct strbuf *buf) |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1457 | { |
| 1458 | size_t len; |
Taylor Blau | 84d5449 | 2021-01-25 18:37:22 -0500 | [diff] [blame] | 1459 | if (!strip_suffix(pack_name, strip, &len) || !len || |
| 1460 | pack_name[len - 1] != '.') |
| 1461 | die(_("packfile name '%s' does not end with '.%s'"), |
| 1462 | pack_name, strip); |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1463 | strbuf_add(buf, pack_name, len); |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1464 | strbuf_addstr(buf, suffix); |
| 1465 | return buf->buf; |
| 1466 | } |
| 1467 | |
| 1468 | static void write_special_file(const char *suffix, const char *msg, |
Junio C Hamano | 0fd90da | 2018-02-15 14:55:47 -0800 | [diff] [blame] | 1469 | const char *pack_name, const unsigned char *hash, |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1470 | const char **report) |
| 1471 | { |
| 1472 | struct strbuf name_buf = STRBUF_INIT; |
| 1473 | const char *filename; |
| 1474 | int fd; |
| 1475 | int msg_len = strlen(msg); |
| 1476 | |
| 1477 | if (pack_name) |
Taylor Blau | 84d5449 | 2021-01-25 18:37:22 -0500 | [diff] [blame] | 1478 | filename = derive_filename(pack_name, "pack", suffix, &name_buf); |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1479 | else |
Junio C Hamano | 0fd90da | 2018-02-15 14:55:47 -0800 | [diff] [blame] | 1480 | filename = odb_pack_name(&name_buf, hash, suffix); |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1481 | |
| 1482 | fd = odb_pack_keep(filename); |
| 1483 | if (fd < 0) { |
| 1484 | if (errno != EEXIST) |
| 1485 | die_errno(_("cannot write %s file '%s'"), |
| 1486 | suffix, filename); |
| 1487 | } else { |
| 1488 | if (msg_len > 0) { |
| 1489 | write_or_die(fd, msg, msg_len); |
| 1490 | write_or_die(fd, "\n", 1); |
| 1491 | } |
| 1492 | if (close(fd) != 0) |
| 1493 | die_errno(_("cannot close written %s file '%s'"), |
| 1494 | suffix, filename); |
Jonathan Tan | 88e2f9e | 2017-12-05 16:58:49 +0000 | [diff] [blame] | 1495 | if (report) |
| 1496 | *report = suffix; |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1497 | } |
| 1498 | strbuf_release(&name_buf); |
| 1499 | } |
| 1500 | |
Ævar Arnfjörð Bjarmason | 8737dab | 2021-09-09 19:24:49 -0400 | [diff] [blame] | 1501 | static void rename_tmp_packfile(const char **final_name, |
| 1502 | const char *curr_name, |
| 1503 | struct strbuf *name, unsigned char *hash, |
| 1504 | const char *ext, int make_read_only_if_same) |
| 1505 | { |
| 1506 | if (*final_name != curr_name) { |
| 1507 | if (!*final_name) |
| 1508 | *final_name = odb_pack_name(name, hash, ext); |
| 1509 | if (finalize_object_file(curr_name, *final_name)) |
Jiang Xin | f733719 | 2021-11-01 10:14:17 +0800 | [diff] [blame] | 1510 | die(_("unable to rename temporary '*.%s' file to '%s'"), |
Ævar Arnfjörð Bjarmason | 8737dab | 2021-09-09 19:24:49 -0400 | [diff] [blame] | 1511 | ext, *final_name); |
| 1512 | } else if (make_read_only_if_same) { |
| 1513 | chmod(*final_name, 0444); |
| 1514 | } |
| 1515 | } |
| 1516 | |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1517 | static void final(const char *final_pack_name, const char *curr_pack_name, |
| 1518 | const char *final_index_name, const char *curr_index_name, |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1519 | const char *final_rev_index_name, const char *curr_rev_index_name, |
Jonathan Tan | 88e2f9e | 2017-12-05 16:58:49 +0000 | [diff] [blame] | 1520 | const char *keep_msg, const char *promisor_msg, |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1521 | unsigned char *hash) |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1522 | { |
Shawn O. Pearce | 3a55602 | 2007-03-06 20:44:17 -0500 | [diff] [blame] | 1523 | const char *report = "pack"; |
Jeff King | f207548 | 2017-03-16 10:27:20 -0400 | [diff] [blame] | 1524 | struct strbuf pack_name = STRBUF_INIT; |
| 1525 | struct strbuf index_name = STRBUF_INIT; |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1526 | struct strbuf rev_index_name = STRBUF_INIT; |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1527 | int err; |
| 1528 | |
| 1529 | if (!from_stdin) { |
| 1530 | close(input_fd); |
| 1531 | } else { |
Neeraj Singh | 020406e | 2022-03-10 22:43:21 +0000 | [diff] [blame] | 1532 | fsync_component_or_die(FSYNC_COMPONENT_PACK, output_fd, curr_pack_name); |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1533 | err = close(output_fd); |
| 1534 | if (err) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1535 | die_errno(_("error while closing pack file")); |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1536 | } |
| 1537 | |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1538 | if (keep_msg) |
Junio C Hamano | 0fd90da | 2018-02-15 14:55:47 -0800 | [diff] [blame] | 1539 | write_special_file("keep", keep_msg, final_pack_name, hash, |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1540 | &report); |
Jonathan Tan | 88e2f9e | 2017-12-05 16:58:49 +0000 | [diff] [blame] | 1541 | if (promisor_msg) |
| 1542 | write_special_file("promisor", promisor_msg, final_pack_name, |
Junio C Hamano | 0fd90da | 2018-02-15 14:55:47 -0800 | [diff] [blame] | 1543 | hash, NULL); |
Shawn Pearce | b807770 | 2006-10-29 04:41:59 -0500 | [diff] [blame] | 1544 | |
Ævar Arnfjörð Bjarmason | 8737dab | 2021-09-09 19:24:49 -0400 | [diff] [blame] | 1545 | rename_tmp_packfile(&final_pack_name, curr_pack_name, &pack_name, |
| 1546 | hash, "pack", from_stdin); |
Ævar Arnfjörð Bjarmason | 8737dab | 2021-09-09 19:24:49 -0400 | [diff] [blame] | 1547 | if (curr_rev_index_name) |
| 1548 | rename_tmp_packfile(&final_rev_index_name, curr_rev_index_name, |
| 1549 | &rev_index_name, hash, "rev", 1); |
Taylor Blau | 522a5c2 | 2021-09-09 19:24:53 -0400 | [diff] [blame] | 1550 | rename_tmp_packfile(&final_index_name, curr_index_name, &index_name, |
| 1551 | hash, "idx", 1); |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1552 | |
Jeff King | 368b4e5 | 2018-05-31 18:45:31 -0400 | [diff] [blame] | 1553 | if (do_fsck_object) { |
| 1554 | struct packed_git *p; |
| 1555 | p = add_packed_git(final_index_name, strlen(final_index_name), 0); |
| 1556 | if (p) |
Junio C Hamano | 549ca8a | 2018-06-13 12:50:46 -0700 | [diff] [blame] | 1557 | install_packed_git(the_repository, p); |
Jeff King | 368b4e5 | 2018-05-31 18:45:31 -0400 | [diff] [blame] | 1558 | } |
Jeff King | 73c3f0f | 2018-05-04 19:45:01 -0400 | [diff] [blame] | 1559 | |
Nicolas Pitre | 576162a | 2006-11-01 17:06:25 -0500 | [diff] [blame] | 1560 | if (!from_stdin) { |
brian m. carlson | 69fa337 | 2019-08-18 20:04:23 +0000 | [diff] [blame] | 1561 | printf("%s\n", hash_to_hex(hash)); |
Nicolas Pitre | 576162a | 2006-11-01 17:06:25 -0500 | [diff] [blame] | 1562 | } else { |
Jeff King | 5b1ef2c | 2017-03-28 15:46:50 -0400 | [diff] [blame] | 1563 | struct strbuf buf = STRBUF_INIT; |
| 1564 | |
brian m. carlson | 69fa337 | 2019-08-18 20:04:23 +0000 | [diff] [blame] | 1565 | strbuf_addf(&buf, "%s\t%s\n", report, hash_to_hex(hash)); |
Jeff King | 5b1ef2c | 2017-03-28 15:46:50 -0400 | [diff] [blame] | 1566 | write_or_die(1, buf.buf, buf.len); |
| 1567 | strbuf_release(&buf); |
Nicolas Pitre | 576162a | 2006-11-01 17:06:25 -0500 | [diff] [blame] | 1568 | |
| 1569 | /* |
| 1570 | * Let's just mimic git-unpack-objects here and write |
| 1571 | * the last part of the input buffer to stdout. |
| 1572 | */ |
| 1573 | while (input_len) { |
| 1574 | err = xwrite(1, input_buffer + input_offset, input_len); |
| 1575 | if (err <= 0) |
| 1576 | break; |
| 1577 | input_len -= err; |
| 1578 | input_offset += err; |
| 1579 | } |
| 1580 | } |
Jeff King | ba47a30 | 2017-03-16 10:27:15 -0400 | [diff] [blame] | 1581 | |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1582 | strbuf_release(&rev_index_name); |
Jeff King | f207548 | 2017-03-16 10:27:20 -0400 | [diff] [blame] | 1583 | strbuf_release(&index_name); |
| 1584 | strbuf_release(&pack_name); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1585 | } |
| 1586 | |
Glen Choo | a4e7e31 | 2023-06-28 19:26:22 +0000 | [diff] [blame] | 1587 | static int git_index_pack_config(const char *k, const char *v, |
| 1588 | const struct config_context *ctx, void *cb) |
Nicolas Pitre | 4d00bda | 2007-11-01 23:26:04 -0400 | [diff] [blame] | 1589 | { |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1590 | struct pack_idx_option *opts = cb; |
| 1591 | |
Nicolas Pitre | 4d00bda | 2007-11-01 23:26:04 -0400 | [diff] [blame] | 1592 | if (!strcmp(k, "pack.indexversion")) { |
Glen Choo | 8868b1e | 2023-06-28 19:26:27 +0000 | [diff] [blame] | 1593 | opts->version = git_config_int(k, v, ctx->kvi); |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1594 | if (opts->version > 2) |
Jiang Xin | b4eda05 | 2022-06-17 18:03:09 +0800 | [diff] [blame] | 1595 | die(_("bad pack.indexVersion=%"PRIu32), opts->version); |
Nicolas Pitre | 4d00bda | 2007-11-01 23:26:04 -0400 | [diff] [blame] | 1596 | return 0; |
| 1597 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1598 | if (!strcmp(k, "pack.threads")) { |
Glen Choo | 8868b1e | 2023-06-28 19:26:27 +0000 | [diff] [blame] | 1599 | nr_threads = git_config_int(k, v, ctx->kvi); |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1600 | if (nr_threads < 0) |
Nguyễn Thái Ngọc Duy | f350df4 | 2012-08-31 19:13:04 +0700 | [diff] [blame] | 1601 | die(_("invalid number of threads specified (%d)"), |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1602 | nr_threads); |
Nguyễn Thái Ngọc Duy | 2094c5e | 2018-11-03 09:48:40 +0100 | [diff] [blame] | 1603 | if (!HAVE_THREADS && nr_threads != 1) { |
Nguyễn Thái Ngọc Duy | f350df4 | 2012-08-31 19:13:04 +0700 | [diff] [blame] | 1604 | warning(_("no threads support, ignoring %s"), k); |
Nguyễn Thái Ngọc Duy | 2094c5e | 2018-11-03 09:48:40 +0100 | [diff] [blame] | 1605 | nr_threads = 1; |
| 1606 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1607 | return 0; |
| 1608 | } |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1609 | if (!strcmp(k, "pack.writereverseindex")) { |
| 1610 | if (git_config_bool(k, v)) |
| 1611 | opts->flags |= WRITE_REV; |
| 1612 | else |
| 1613 | opts->flags &= ~WRITE_REV; |
| 1614 | } |
Glen Choo | a4e7e31 | 2023-06-28 19:26:22 +0000 | [diff] [blame] | 1615 | return git_default_config(k, v, ctx, cb); |
Nicolas Pitre | 4d00bda | 2007-11-01 23:26:04 -0400 | [diff] [blame] | 1616 | } |
| 1617 | |
Junio C Hamano | 3c9fc07 | 2011-02-25 16:55:26 -0800 | [diff] [blame] | 1618 | static int cmp_uint32(const void *a_, const void *b_) |
| 1619 | { |
| 1620 | uint32_t a = *((uint32_t *)a_); |
| 1621 | uint32_t b = *((uint32_t *)b_); |
| 1622 | |
| 1623 | return (a < b) ? -1 : (a != b); |
| 1624 | } |
| 1625 | |
| 1626 | static void read_v2_anomalous_offsets(struct packed_git *p, |
| 1627 | struct pack_idx_option *opts) |
| 1628 | { |
| 1629 | const uint32_t *idx1, *idx2; |
| 1630 | uint32_t i; |
| 1631 | |
| 1632 | /* The address of the 4-byte offset table */ |
brian m. carlson | 629dffc | 2020-05-25 19:59:10 +0000 | [diff] [blame] | 1633 | idx1 = (((const uint32_t *)((const uint8_t *)p->index_data + p->crc_offset)) |
Jeff King | f86f769 | 2020-11-13 00:06:48 -0500 | [diff] [blame] | 1634 | + (size_t)p->num_objects /* CRC32 table */ |
Junio C Hamano | 3c9fc07 | 2011-02-25 16:55:26 -0800 | [diff] [blame] | 1635 | ); |
| 1636 | |
| 1637 | /* The address of the 8-byte offset table */ |
| 1638 | idx2 = idx1 + p->num_objects; |
| 1639 | |
| 1640 | for (i = 0; i < p->num_objects; i++) { |
| 1641 | uint32_t off = ntohl(idx1[i]); |
| 1642 | if (!(off & 0x80000000)) |
| 1643 | continue; |
| 1644 | off = off & 0x7fffffff; |
Jeff King | 47fe3f6 | 2016-02-25 09:22:52 -0500 | [diff] [blame] | 1645 | check_pack_index_ptr(p, &idx2[off * 2]); |
Junio C Hamano | 3c9fc07 | 2011-02-25 16:55:26 -0800 | [diff] [blame] | 1646 | if (idx2[off * 2]) |
| 1647 | continue; |
| 1648 | /* |
| 1649 | * The real offset is ntohl(idx2[off * 2]) in high 4 |
| 1650 | * octets, and ntohl(idx2[off * 2 + 1]) in low 4 |
| 1651 | * octets. But idx2[off * 2] is Zero!!! |
| 1652 | */ |
| 1653 | ALLOC_GROW(opts->anomaly, opts->anomaly_nr + 1, opts->anomaly_alloc); |
| 1654 | opts->anomaly[opts->anomaly_nr++] = ntohl(idx2[off * 2 + 1]); |
| 1655 | } |
| 1656 | |
René Scharfe | 1b5294d | 2016-09-30 01:40:14 +0200 | [diff] [blame] | 1657 | QSORT(opts->anomaly, opts->anomaly_nr, cmp_uint32); |
Junio C Hamano | 3c9fc07 | 2011-02-25 16:55:26 -0800 | [diff] [blame] | 1658 | } |
| 1659 | |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1660 | static void read_idx_option(struct pack_idx_option *opts, const char *pack_name) |
| 1661 | { |
| 1662 | struct packed_git *p = add_packed_git(pack_name, strlen(pack_name), 1); |
| 1663 | |
| 1664 | if (!p) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1665 | die(_("Cannot open existing pack file '%s'"), pack_name); |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1666 | if (open_pack_index(p)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1667 | die(_("Cannot open existing pack idx file for '%s'"), pack_name); |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1668 | |
| 1669 | /* Read the attributes from the existing idx file */ |
| 1670 | opts->version = p->index_version; |
| 1671 | |
Junio C Hamano | 3c9fc07 | 2011-02-25 16:55:26 -0800 | [diff] [blame] | 1672 | if (opts->version == 2) |
| 1673 | read_v2_anomalous_offsets(p, opts); |
| 1674 | |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1675 | /* |
| 1676 | * Get rid of the idx file as we do not need it anymore. |
| 1677 | * NEEDSWORK: extract this bit from free_pack_by_name() in |
Martin Ågren | e5afd44 | 2020-12-31 12:56:21 +0100 | [diff] [blame] | 1678 | * object-file.c, perhaps? It shouldn't matter very much as we |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1679 | * know we haven't installed this pack (hence we never have |
| 1680 | * read anything from it). |
| 1681 | */ |
| 1682 | close_pack_index(p); |
| 1683 | free(p); |
| 1684 | } |
| 1685 | |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1686 | static void show_pack_info(int stat_only) |
| 1687 | { |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1688 | int i, baseobjects = nr_objects - nr_ref_deltas - nr_ofs_deltas; |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 1689 | unsigned long *chain_histogram = NULL; |
| 1690 | |
| 1691 | if (deepest_delta) |
René Scharfe | ca56dad | 2021-03-13 17:17:22 +0100 | [diff] [blame] | 1692 | CALLOC_ARRAY(chain_histogram, deepest_delta); |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 1693 | |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1694 | for (i = 0; i < nr_objects; i++) { |
| 1695 | struct object_entry *obj = &objects[i]; |
| 1696 | |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 1697 | if (is_delta_type(obj->type)) |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 1698 | chain_histogram[obj_stat[i].delta_depth - 1]++; |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1699 | if (stat_only) |
| 1700 | continue; |
Torsten Bögershausen | ca473ce | 2018-11-11 08:05:04 +0100 | [diff] [blame] | 1701 | printf("%s %-6s %"PRIuMAX" %"PRIuMAX" %"PRIuMAX, |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 1702 | oid_to_hex(&obj->idx.oid), |
Torsten Bögershausen | ca473ce | 2018-11-11 08:05:04 +0100 | [diff] [blame] | 1703 | type_name(obj->real_type), (uintmax_t)obj->size, |
| 1704 | (uintmax_t)(obj[1].idx.offset - obj->idx.offset), |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1705 | (uintmax_t)obj->idx.offset); |
| 1706 | if (is_delta_type(obj->type)) { |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 1707 | struct object_entry *bobj = &objects[obj_stat[i].base_object_no]; |
brian m. carlson | e6a492b | 2017-05-06 22:10:11 +0000 | [diff] [blame] | 1708 | printf(" %u %s", obj_stat[i].delta_depth, |
| 1709 | oid_to_hex(&bobj->idx.oid)); |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1710 | } |
| 1711 | putchar('\n'); |
| 1712 | } |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 1713 | |
| 1714 | if (baseobjects) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1715 | printf_ln(Q_("non delta: %d object", |
| 1716 | "non delta: %d objects", |
| 1717 | baseobjects), |
| 1718 | baseobjects); |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 1719 | for (i = 0; i < deepest_delta; i++) { |
| 1720 | if (!chain_histogram[i]) |
| 1721 | continue; |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1722 | printf_ln(Q_("chain length = %d: %lu object", |
| 1723 | "chain length = %d: %lu objects", |
| 1724 | chain_histogram[i]), |
| 1725 | i + 1, |
| 1726 | chain_histogram[i]); |
Junio C Hamano | d1a0ed1 | 2011-06-03 15:32:16 -0700 | [diff] [blame] | 1727 | } |
Ævar Arnfjörð Bjarmason | f2bcc69 | 2022-03-04 19:32:04 +0100 | [diff] [blame] | 1728 | free(chain_histogram); |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1729 | } |
| 1730 | |
Linus Torvalds | 3bb7256 | 2010-01-22 07:55:19 -0800 | [diff] [blame] | 1731 | int cmd_index_pack(int argc, const char **argv, const char *prefix) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1732 | { |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1733 | int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; |
Nguyễn Thái Ngọc Duy | 3953949 | 2014-03-25 20:41:41 +0700 | [diff] [blame] | 1734 | const char *curr_index; |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1735 | const char *curr_rev_index = NULL; |
| 1736 | const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL; |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1737 | const char *keep_msg = NULL; |
Jonathan Tan | 88e2f9e | 2017-12-05 16:58:49 +0000 | [diff] [blame] | 1738 | const char *promisor_msg = NULL; |
Jonathan Tan | 8e29c7c | 2017-12-05 16:58:48 +0000 | [diff] [blame] | 1739 | struct strbuf index_name_buf = STRBUF_INIT; |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1740 | struct strbuf rev_index_name_buf = STRBUF_INIT; |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 1741 | struct pack_idx_entry **idx_objects; |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1742 | struct pack_idx_option opts; |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1743 | unsigned char pack_hash[GIT_MAX_RAWSZ]; |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 1744 | unsigned foreign_nr = 1; /* zero is a "good" value, assume bad */ |
Jeff King | 8355868 | 2016-07-15 06:43:47 -0400 | [diff] [blame] | 1745 | int report_end_of_input = 0; |
brian m. carlson | 586740a | 2020-06-19 17:55:52 +0000 | [diff] [blame] | 1746 | int hash_algo = 0; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1747 | |
Jonathan Tan | 8b4c010 | 2017-12-08 15:27:14 +0000 | [diff] [blame] | 1748 | /* |
Jonathan Tan | 8a30a1e | 2019-05-14 14:10:55 -0700 | [diff] [blame] | 1749 | * index-pack never needs to fetch missing objects except when |
| 1750 | * REF_DELTA bases are missing (which are explicitly handled). It only |
| 1751 | * accesses the repo to do hash collision checks and to check which |
| 1752 | * REF_DELTA bases need to be fetched. |
Jonathan Tan | 8b4c010 | 2017-12-08 15:27:14 +0000 | [diff] [blame] | 1753 | */ |
| 1754 | fetch_if_missing = 0; |
| 1755 | |
Jonathan Nieder | 99caeed | 2009-11-09 09:05:01 -0600 | [diff] [blame] | 1756 | if (argc == 2 && !strcmp(argv[1], "-h")) |
| 1757 | usage(index_pack_usage); |
| 1758 | |
Derrick Stolee | d24eda4 | 2023-06-06 13:24:35 +0000 | [diff] [blame] | 1759 | disable_replace_refs(); |
Johannes Schindelin | 2241054 | 2015-06-22 17:25:00 +0200 | [diff] [blame] | 1760 | fsck_options.walk = mark_link; |
Nelson Elhage | 6e2a09d | 2010-08-12 10:18:12 -0400 | [diff] [blame] | 1761 | |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1762 | reset_pack_idx_option(&opts); |
Taylor Blau | a8dd7e0 | 2023-04-12 18:20:33 -0400 | [diff] [blame] | 1763 | opts.flags |= WRITE_REV; |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1764 | git_config(git_index_pack_config, &opts); |
Nguyễn Thái Ngọc Duy | 3f8099f | 2010-07-24 06:30:49 -0500 | [diff] [blame] | 1765 | if (prefix && chdir(prefix)) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1766 | die(_("Cannot come back to cwd")); |
Nicolas Pitre | 4d00bda | 2007-11-01 23:26:04 -0400 | [diff] [blame] | 1767 | |
Taylor Blau | 9f7f10a | 2023-04-12 18:20:36 -0400 | [diff] [blame] | 1768 | if (git_env_bool(GIT_TEST_NO_WRITE_REV_INDEX, 0)) |
| 1769 | rev_index = 0; |
Taylor Blau | e8c58f8 | 2021-01-25 18:37:42 -0500 | [diff] [blame] | 1770 | else |
| 1771 | rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV)); |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1772 | |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1773 | for (i = 1; i < argc; i++) { |
Linus Torvalds | 3bb7256 | 2010-01-22 07:55:19 -0800 | [diff] [blame] | 1774 | const char *arg = argv[i]; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1775 | |
| 1776 | if (*arg == '-') { |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1777 | if (!strcmp(arg, "--stdin")) { |
| 1778 | from_stdin = 1; |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1779 | } else if (!strcmp(arg, "--fix-thin")) { |
| 1780 | fix_thin_pack = 1; |
Christian Couder | 72885a6 | 2017-12-09 21:40:08 +0100 | [diff] [blame] | 1781 | } else if (skip_to_optional_arg(arg, "--strict", &arg)) { |
Johannes Schindelin | 5d477a3 | 2015-06-22 17:25:31 +0200 | [diff] [blame] | 1782 | strict = 1; |
| 1783 | do_fsck_object = 1; |
| 1784 | fsck_set_msg_types(&fsck_options, arg); |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 1785 | } else if (!strcmp(arg, "--check-self-contained-and-connected")) { |
| 1786 | strict = 1; |
| 1787 | check_self_contained_and_connected = 1; |
John Cai | 0f8edf7 | 2024-02-01 01:38:02 +0000 | [diff] [blame] | 1788 | } else if (skip_to_optional_arg(arg, "--fsck-objects", &arg)) { |
Jonathan Tan | ffb2c0f | 2018-03-14 11:42:40 -0700 | [diff] [blame] | 1789 | do_fsck_object = 1; |
John Cai | 0f8edf7 | 2024-02-01 01:38:02 +0000 | [diff] [blame] | 1790 | fsck_set_msg_types(&fsck_options, arg); |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1791 | } else if (!strcmp(arg, "--verify")) { |
| 1792 | verify = 1; |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1793 | } else if (!strcmp(arg, "--verify-stat")) { |
| 1794 | verify = 1; |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 1795 | show_stat = 1; |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1796 | } else if (!strcmp(arg, "--verify-stat-only")) { |
| 1797 | verify = 1; |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 1798 | show_stat = 1; |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1799 | stat_only = 1; |
Christian Couder | 72885a6 | 2017-12-09 21:40:08 +0100 | [diff] [blame] | 1800 | } else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) { |
| 1801 | ; /* nothing to do */ |
Junio C Hamano | f3d618d | 2018-02-13 13:39:03 -0800 | [diff] [blame] | 1802 | } else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) { |
| 1803 | ; /* already parsed */ |
Christian Couder | 5955654 | 2013-11-30 21:55:40 +0100 | [diff] [blame] | 1804 | } else if (starts_with(arg, "--threads=")) { |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1805 | char *end; |
| 1806 | nr_threads = strtoul(arg+10, &end, 0); |
| 1807 | if (!arg[10] || *end || nr_threads < 0) |
| 1808 | usage(index_pack_usage); |
Nguyễn Thái Ngọc Duy | 2094c5e | 2018-11-03 09:48:40 +0100 | [diff] [blame] | 1809 | if (!HAVE_THREADS && nr_threads != 1) { |
| 1810 | warning(_("no threads support, ignoring %s"), arg); |
| 1811 | nr_threads = 1; |
| 1812 | } |
Christian Couder | 5955654 | 2013-11-30 21:55:40 +0100 | [diff] [blame] | 1813 | } else if (starts_with(arg, "--pack_header=")) { |
Nicolas Pitre | bed006f | 2006-11-01 17:06:20 -0500 | [diff] [blame] | 1814 | struct pack_header *hdr; |
| 1815 | char *c; |
| 1816 | |
| 1817 | hdr = (struct pack_header *)input_buffer; |
| 1818 | hdr->hdr_signature = htonl(PACK_SIGNATURE); |
| 1819 | hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10)); |
| 1820 | if (*c != ',') |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1821 | die(_("bad %s"), arg); |
Nicolas Pitre | bed006f | 2006-11-01 17:06:20 -0500 | [diff] [blame] | 1822 | hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10)); |
| 1823 | if (*c) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1824 | die(_("bad %s"), arg); |
Nicolas Pitre | bed006f | 2006-11-01 17:06:20 -0500 | [diff] [blame] | 1825 | input_len = sizeof(*hdr); |
Nicolas Pitre | 3c9af36 | 2006-10-25 23:32:59 -0400 | [diff] [blame] | 1826 | } else if (!strcmp(arg, "-v")) { |
| 1827 | verbose = 1; |
Ævar Arnfjörð Bjarmason | f46c46e | 2021-09-05 09:34:44 +0200 | [diff] [blame] | 1828 | } else if (!strcmp(arg, "--progress-title")) { |
| 1829 | if (progress_title || (i+1) >= argc) |
| 1830 | usage(index_pack_usage); |
| 1831 | progress_title = argv[++i]; |
Jeff King | e376f17 | 2016-07-15 06:34:22 -0400 | [diff] [blame] | 1832 | } else if (!strcmp(arg, "--show-resolving-progress")) { |
| 1833 | show_resolving_progress = 1; |
Jeff King | 8355868 | 2016-07-15 06:43:47 -0400 | [diff] [blame] | 1834 | } else if (!strcmp(arg, "--report-end-of-input")) { |
| 1835 | report_end_of_input = 1; |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1836 | } else if (!strcmp(arg, "-o")) { |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1837 | if (index_name || (i+1) >= argc) |
| 1838 | usage(index_pack_usage); |
| 1839 | index_name = argv[++i]; |
Christian Couder | 5955654 | 2013-11-30 21:55:40 +0100 | [diff] [blame] | 1840 | } else if (starts_with(arg, "--index-version=")) { |
Nicolas Pitre | 4ba7d71 | 2007-04-09 17:32:03 -0400 | [diff] [blame] | 1841 | char *c; |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1842 | opts.version = strtoul(arg + 16, &c, 10); |
| 1843 | if (opts.version > 2) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1844 | die(_("bad %s"), arg); |
Nicolas Pitre | 4ba7d71 | 2007-04-09 17:32:03 -0400 | [diff] [blame] | 1845 | if (*c == ',') |
Junio C Hamano | ebcfb37 | 2011-02-25 15:43:25 -0800 | [diff] [blame] | 1846 | opts.off32_limit = strtoul(c+1, &c, 0); |
| 1847 | if (*c || opts.off32_limit & 0x80000000) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1848 | die(_("bad %s"), arg); |
Jeff King | 411481b | 2016-08-24 20:41:55 +0200 | [diff] [blame] | 1849 | } else if (skip_prefix(arg, "--max-input-size=", &arg)) { |
| 1850 | max_input_size = strtoumax(arg, NULL, 10); |
brian m. carlson | 586740a | 2020-06-19 17:55:52 +0000 | [diff] [blame] | 1851 | } else if (skip_prefix(arg, "--object-format=", &arg)) { |
| 1852 | hash_algo = hash_algo_by_name(arg); |
| 1853 | if (hash_algo == GIT_HASH_UNKNOWN) |
| 1854 | die(_("unknown hash algorithm '%s'"), arg); |
| 1855 | repo_set_hash_algo(the_repository, hash_algo); |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1856 | } else if (!strcmp(arg, "--rev-index")) { |
| 1857 | rev_index = 1; |
| 1858 | } else if (!strcmp(arg, "--no-rev-index")) { |
| 1859 | rev_index = 0; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1860 | } else |
| 1861 | usage(index_pack_usage); |
| 1862 | continue; |
| 1863 | } |
| 1864 | |
| 1865 | if (pack_name) |
| 1866 | usage(index_pack_usage); |
| 1867 | pack_name = arg; |
| 1868 | } |
| 1869 | |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1870 | if (!pack_name && !from_stdin) |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1871 | usage(index_pack_usage); |
Nicolas Pitre | 636171c | 2006-10-25 23:28:17 -0400 | [diff] [blame] | 1872 | if (fix_thin_pack && !from_stdin) |
Jean-Noël Avila | 6fa00ee | 2022-01-05 20:02:19 +0000 | [diff] [blame] | 1873 | die(_("the option '%s' requires '%s'"), "--fix-thin", "--stdin"); |
Jeff King | 7176a31 | 2016-12-15 21:30:59 -0500 | [diff] [blame] | 1874 | if (from_stdin && !startup_info->have_repository) |
| 1875 | die(_("--stdin requires a git repository")); |
brian m. carlson | 586740a | 2020-06-19 17:55:52 +0000 | [diff] [blame] | 1876 | if (from_stdin && hash_algo) |
Jean-Noël Avila | 12909b6 | 2022-01-05 20:02:16 +0000 | [diff] [blame] | 1877 | die(_("options '%s' and '%s' cannot be used together"), "--object-format", "--stdin"); |
Junio C Hamano | bfee614 | 2016-03-03 11:29:09 -0800 | [diff] [blame] | 1878 | if (!index_name && pack_name) |
Taylor Blau | 84d5449 | 2021-01-25 18:37:22 -0500 | [diff] [blame] | 1879 | index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf); |
Junio C Hamano | bfee614 | 2016-03-03 11:29:09 -0800 | [diff] [blame] | 1880 | |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1881 | opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY); |
| 1882 | if (rev_index) { |
| 1883 | opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV; |
| 1884 | if (index_name) |
| 1885 | rev_index_name = derive_filename(index_name, |
| 1886 | "idx", "rev", |
| 1887 | &rev_index_name_buf); |
| 1888 | } |
| 1889 | |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1890 | if (verify) { |
| 1891 | if (!index_name) |
Nguyễn Thái Ngọc Duy | c2b97ec | 2012-04-23 19:30:29 +0700 | [diff] [blame] | 1892 | die(_("--verify with no packfile name given")); |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1893 | read_idx_option(&opts, index_name); |
Junio C Hamano | 68be2fe | 2011-11-16 22:04:13 -0800 | [diff] [blame] | 1894 | opts.flags |= WRITE_IDX_VERIFY | WRITE_IDX_STRICT; |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1895 | } |
Junio C Hamano | 68be2fe | 2011-11-16 22:04:13 -0800 | [diff] [blame] | 1896 | if (strict) |
| 1897 | opts.flags |= WRITE_IDX_STRICT; |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1898 | |
Nguyễn Thái Ngọc Duy | 2094c5e | 2018-11-03 09:48:40 +0100 | [diff] [blame] | 1899 | if (HAVE_THREADS && !nr_threads) { |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1900 | nr_threads = online_cpus(); |
Jeff King | fbff95b | 2020-08-21 13:58:00 -0400 | [diff] [blame] | 1901 | /* |
| 1902 | * Experiments show that going above 20 threads doesn't help, |
| 1903 | * no matter how many cores you have. Below that, we tend to |
| 1904 | * max at half the number of online_cpus(), presumably because |
| 1905 | * half of those are hyperthreads rather than full cores. We'll |
| 1906 | * never reduce the level below "3", though, to match a |
| 1907 | * historical value that nobody complained about. |
| 1908 | */ |
| 1909 | if (nr_threads < 4) |
| 1910 | ; /* too few cores to consider capping */ |
| 1911 | else if (nr_threads < 6) |
| 1912 | nr_threads = 3; /* historic cap */ |
| 1913 | else if (nr_threads < 40) |
| 1914 | nr_threads /= 2; |
| 1915 | else |
| 1916 | nr_threads = 20; /* hard cap */ |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1917 | } |
Nguyễn Thái Ngọc Duy | b8a2486 | 2012-05-06 19:31:55 +0700 | [diff] [blame] | 1918 | |
Nicolas Pitre | e42797f | 2006-10-23 14:50:18 -0400 | [diff] [blame] | 1919 | curr_pack = open_pack_file(pack_name); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1920 | parse_pack_header(); |
René Scharfe | ca56dad | 2021-03-13 17:17:22 +0100 | [diff] [blame] | 1921 | CALLOC_ARRAY(objects, st_add(nr_objects, 1)); |
Nguyễn Thái Ngọc Duy | 4173057 | 2015-02-26 17:52:07 +0700 | [diff] [blame] | 1922 | if (show_stat) |
René Scharfe | ca56dad | 2021-03-13 17:17:22 +0100 | [diff] [blame] | 1923 | CALLOC_ARRAY(obj_stat, st_add(nr_objects, 1)); |
| 1924 | CALLOC_ARRAY(ofs_deltas, nr_objects); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1925 | parse_pack_objects(pack_hash); |
Jeff King | 8355868 | 2016-07-15 06:43:47 -0400 | [diff] [blame] | 1926 | if (report_end_of_input) |
| 1927 | write_in_full(2, "\0", 1); |
Nguyễn Thái Ngọc Duy | 5272f75 | 2012-05-06 19:31:54 +0700 | [diff] [blame] | 1928 | resolve_deltas(); |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1929 | conclude_pack(fix_thin_pack, curr_pack, pack_hash); |
Nguyễn Thái Ngọc Duy | c6458e6 | 2015-04-18 17:47:05 +0700 | [diff] [blame] | 1930 | free(ofs_deltas); |
| 1931 | free(ref_deltas); |
Martin Koegler | 0153be0 | 2008-02-25 22:46:12 +0100 | [diff] [blame] | 1932 | if (strict) |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 1933 | foreign_nr = check_objects(); |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 1934 | |
Nguyễn Thái Ngọc Duy | 3aba2fd | 2013-03-19 20:01:15 +0700 | [diff] [blame] | 1935 | if (show_stat) |
Junio C Hamano | 38a4556 | 2011-06-03 15:32:15 -0700 | [diff] [blame] | 1936 | show_pack_info(stat_only); |
| 1937 | |
Jeff King | b32fa95 | 2016-02-22 17:44:25 -0500 | [diff] [blame] | 1938 | ALLOC_ARRAY(idx_objects, nr_objects); |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 1939 | for (i = 0; i < nr_objects; i++) |
| 1940 | idx_objects[i] = &objects[i].idx; |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1941 | curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash); |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1942 | if (rev_index) |
| 1943 | curr_rev_index = write_rev_file(rev_index_name, idx_objects, |
| 1944 | nr_objects, pack_hash, |
| 1945 | opts.flags); |
Geert Bosch | aa7e44b | 2007-06-01 15:18:05 -0400 | [diff] [blame] | 1946 | free(idx_objects); |
| 1947 | |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1948 | if (!verify) |
| 1949 | final(pack_name, curr_pack, |
| 1950 | index_name, curr_index, |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1951 | rev_index_name, curr_rev_index, |
Jonathan Tan | 88e2f9e | 2017-12-05 16:58:49 +0000 | [diff] [blame] | 1952 | keep_msg, promisor_msg, |
brian m. carlson | 454253f | 2018-02-01 02:18:39 +0000 | [diff] [blame] | 1953 | pack_hash); |
Junio C Hamano | e337a04 | 2011-02-02 17:29:01 -0800 | [diff] [blame] | 1954 | else |
| 1955 | close(input_fd); |
Jeff King | 73c3f0f | 2018-05-04 19:45:01 -0400 | [diff] [blame] | 1956 | |
Ævar Arnfjörð Bjarmason | 462f5ca | 2021-03-28 15:15:49 +0200 | [diff] [blame] | 1957 | if (do_fsck_object && fsck_finish(&fsck_options)) |
| 1958 | die(_("fsck error in pack objects")); |
Jeff King | 73c3f0f | 2018-05-04 19:45:01 -0400 | [diff] [blame] | 1959 | |
Ævar Arnfjörð Bjarmason | f2bcc69 | 2022-03-04 19:32:04 +0100 | [diff] [blame] | 1960 | free(opts.anomaly); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1961 | free(objects); |
Jeff King | 592ce20 | 2014-06-30 12:59:10 -0400 | [diff] [blame] | 1962 | strbuf_release(&index_name_buf); |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1963 | strbuf_release(&rev_index_name_buf); |
Junio C Hamano | afe8a90 | 2022-05-02 09:50:37 -0700 | [diff] [blame] | 1964 | if (!pack_name) |
Linus Torvalds | 3bb7256 | 2010-01-22 07:55:19 -0800 | [diff] [blame] | 1965 | free((void *) curr_pack); |
Junio C Hamano | afe8a90 | 2022-05-02 09:50:37 -0700 | [diff] [blame] | 1966 | if (!index_name) |
Linus Torvalds | 3bb7256 | 2010-01-22 07:55:19 -0800 | [diff] [blame] | 1967 | free((void *) curr_index); |
Junio C Hamano | afe8a90 | 2022-05-02 09:50:37 -0700 | [diff] [blame] | 1968 | if (!rev_index_name) |
Taylor Blau | e37d0b8 | 2021-01-25 18:37:26 -0500 | [diff] [blame] | 1969 | free((void *) curr_rev_index); |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1970 | |
Nguyễn Thái Ngọc Duy | c6807a4 | 2013-05-26 08:16:17 +0700 | [diff] [blame] | 1971 | /* |
| 1972 | * Let the caller know this pack is not self contained |
| 1973 | */ |
| 1974 | if (check_self_contained_and_connected && foreign_nr) |
| 1975 | return 1; |
| 1976 | |
Sergey Vlasov | 9cf6d33 | 2005-10-12 12:01:31 -0700 | [diff] [blame] | 1977 | return 0; |
| 1978 | } |