Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 569 lines (506 sloc) 13.18 kb
6441363 @matthiask Make git-unpack-objects a builtin
matthiask authored
1 #include "builtin.h"
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
2 #include "cache.h"
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
3 #include "object.h"
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
4 #include "delta.h"
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
5 #include "pack.h"
8e44025 Use blob_, commit_, tag_, and tree_type throughout.
Peter Eriksen authored
6 #include "blob.h"
7 #include "commit.h"
8 #include "tag.h"
9 #include "tree.h"
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
10 #include "tree-walk.h"
96a02f8 common progress display support
Nicolas Pitre authored
11 #include "progress.h"
2add1e6 unpack-object: cache for non written objects
Martin Koegler authored
12 #include "decorate.h"
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
13 #include "fsck.h"
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
14
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
15 static int dry_run, quiet, recover, has_errors, strict;
f18d244 @heikkiorsila Start conforming code to "git subcmd" style part 3
heikkiorsila authored
16 static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict] < pack-file";
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
17
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
18 /* We always read in 4kB chunks. */
19 static unsigned char buffer[4096];
d7dd022 add overflow tests on pack offset variables
Nicolas Pitre authored
20 static unsigned int offset, len;
21 static off_t consumed_bytes;
9126f00 fix openssl headers conflicting with custom SHA1 implementations
Nicolas Pitre authored
22 static git_SHA_CTX ctx;
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
23
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
24 /*
25 * When running under --strict mode, objects whose reachability are
26 * suspect are kept in core without getting written in the object
27 * store.
28 */
2add1e6 unpack-object: cache for non written objects
Martin Koegler authored
29 struct obj_buffer {
30 char *buffer;
31 unsigned long size;
32 };
33
34 static struct decoration obj_decorate;
35
36 static struct obj_buffer *lookup_object_buffer(struct object *base)
37 {
38 return lookup_decoration(&obj_decorate, base);
39 }
40
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
41 static void add_object_buffer(struct object *object, char *buffer, unsigned long size)
42 {
43 struct obj_buffer *obj;
44 obj = xcalloc(1, sizeof(struct obj_buffer));
45 obj->buffer = buffer;
46 obj->size = size;
47 if (add_decoration(&obj_decorate, object, obj))
48 die("object %s tried to add buffer twice!", sha1_to_hex(object->sha1));
49 }
50
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
51 /*
52 * Make sure at least "min" bytes are available in the buffer, and
53 * return the pointer to the buffer.
54 */
79a6569 Use memmove instead of memcpy for overlapping areas
Edgar Toernig authored
55 static void *fill(int min)
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
56 {
57 if (min <= len)
58 return buffer + offset;
59 if (min > sizeof(buffer))
60 die("cannot fill %d bytes", min);
61 if (offset) {
9126f00 fix openssl headers conflicting with custom SHA1 implementations
Nicolas Pitre authored
62 git_SHA1_Update(&ctx, buffer, offset);
79a6569 Use memmove instead of memcpy for overlapping areas
Edgar Toernig authored
63 memmove(buffer, buffer + offset, len);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
64 offset = 0;
65 }
66 do {
8a912bc @jherland Ensure return value from xread() is always stored into an ssize_t
jherland authored
67 ssize_t ret = xread(0, buffer + len, sizeof(buffer) - len);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
68 if (ret <= 0) {
69 if (!ret)
70 die("early EOF");
d824cbb @trast Convert existing die(..., strerror(errno)) to die_errno()
trast authored
71 die_errno("read error on input");
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
72 }
73 len += ret;
74 } while (len < min);
75 return buffer;
76 }
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
77
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
78 static void use(int bytes)
79 {
80 if (bytes > len)
81 die("used more bytes than were available");
82 len -= bytes;
83 offset += bytes;
d7dd022 add overflow tests on pack offset variables
Nicolas Pitre authored
84
85 /* make sure off_t is sufficiently large not to wrap */
86 if (consumed_bytes > consumed_bytes + bytes)
87 die("pack too large for current definition of off_t");
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
88 consumed_bytes += bytes;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
89 }
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
90
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
91 static void *get_data(unsigned long size)
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
92 {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
93 z_stream stream;
94 void *buf = xmalloc(size);
95
96 memset(&stream, 0, sizeof(stream));
97
98 stream.next_out = buf;
99 stream.avail_out = size;
100 stream.next_in = fill(1);
101 stream.avail_in = len;
39c6854 @torvalds Wrap inflate and other zlib routines for better error reporting
torvalds authored
102 git_inflate_init(&stream);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
103
104 for (;;) {
39c6854 @torvalds Wrap inflate and other zlib routines for better error reporting
torvalds authored
105 int ret = git_inflate(&stream, 0);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
106 use(len - stream.avail_in);
107 if (stream.total_out == size && ret == Z_STREAM_END)
108 break;
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
109 if (ret != Z_OK) {
110 error("inflate returned %d\n", ret);
111 free(buf);
112 buf = NULL;
3b67d29 unpack-objects -r: call it "recover".
Junio C Hamano authored
113 if (!recover)
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
114 exit(1);
115 has_errors = 1;
116 break;
117 }
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
118 stream.next_in = fill(1);
119 stream.avail_in = len;
120 }
39c6854 @torvalds Wrap inflate and other zlib routines for better error reporting
torvalds authored
121 git_inflate_end(&stream);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
122 return buf;
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
123 }
124
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
125 struct delta_info {
126 unsigned char base_sha1[20];
d7dd022 add overflow tests on pack offset variables
Nicolas Pitre authored
127 unsigned nr;
128 off_t base_offset;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
129 unsigned long size;
130 void *delta;
131 struct delta_info *next;
132 };
133
134 static struct delta_info *delta_list;
135
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
136 static void add_delta_to_list(unsigned nr, unsigned const char *base_sha1,
d7dd022 add overflow tests on pack offset variables
Nicolas Pitre authored
137 off_t base_offset,
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
138 void *delta, unsigned long size)
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
139 {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
140 struct delta_info *info = xmalloc(sizeof(*info));
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
141
e702496 @spearce Convert memcpy(a,b,20) to hashcpy(a,b).
spearce authored
142 hashcpy(info->base_sha1, base_sha1);
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
143 info->base_offset = base_offset;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
144 info->size = size;
145 info->delta = delta;
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
146 info->nr = nr;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
147 info->next = delta_list;
148 delta_list = info;
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
149 }
150
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
151 struct obj_info {
d7dd022 add overflow tests on pack offset variables
Nicolas Pitre authored
152 off_t offset;
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
153 unsigned char sha1[20];
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
154 struct object *obj;
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
155 };
156
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
157 #define FLAG_OPEN (1u<<20)
158 #define FLAG_WRITTEN (1u<<21)
159
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
160 static struct obj_info *obj_list;
2af202b @torvalds Fix various sparse warnings in the git source code
torvalds authored
161 static unsigned nr_objects;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
162
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
163 /*
164 * Called only from check_object() after it verified this object
165 * is Ok.
166 */
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
167 static void write_cached_object(struct object *obj)
168 {
169 unsigned char sha1[20];
170 struct obj_buffer *obj_buf = lookup_object_buffer(obj);
171 if (write_sha1_file(obj_buf->buffer, obj_buf->size, typename(obj->type), sha1) < 0)
172 die("failed to write object %s", sha1_to_hex(obj->sha1));
173 obj->flags |= FLAG_WRITTEN;
174 }
175
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
176 /*
177 * At the very end of the processing, write_rest() scans the objects
178 * that have reachability requirements and calls this function.
179 * Verify its reachability and validity recursively and write it out.
180 */
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
181 static int check_object(struct object *obj, int type, void *data)
182 {
183 if (!obj)
9a21739 @gitster Fix "unpack-objects --strict"
gitster authored
184 return 1;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
185
186 if (obj->flags & FLAG_WRITTEN)
9a21739 @gitster Fix "unpack-objects --strict"
gitster authored
187 return 0;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
188
189 if (type != OBJ_ANY && obj->type != type)
190 die("object type mismatch");
191
192 if (!(obj->flags & FLAG_OPEN)) {
193 unsigned long size;
194 int type = sha1_object_info(obj->sha1, &size);
195 if (type != obj->type || type <= 0)
196 die("object of unexpected type");
197 obj->flags |= FLAG_WRITTEN;
9a21739 @gitster Fix "unpack-objects --strict"
gitster authored
198 return 0;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
199 }
200
201 if (fsck_object(obj, 1, fsck_error_function))
202 die("Error in object");
ab36d06 @gitster Merge branch 'jc/maint-unpack-objects-strict'
gitster authored
203 if (fsck_walk(obj, check_object, NULL))
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
204 die("Error on reachable objects of %s", sha1_to_hex(obj->sha1));
205 write_cached_object(obj);
9a21739 @gitster Fix "unpack-objects --strict"
gitster authored
206 return 0;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
207 }
208
209 static void write_rest(void)
210 {
211 unsigned i;
9a21739 @gitster Fix "unpack-objects --strict"
gitster authored
212 for (i = 0; i < nr_objects; i++) {
213 if (obj_list[i].obj)
ab36d06 @gitster Merge branch 'jc/maint-unpack-objects-strict'
gitster authored
214 check_object(obj_list[i].obj, OBJ_ANY, NULL);
9a21739 @gitster Fix "unpack-objects --strict"
gitster authored
215 }
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
216 }
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
217
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
218 static void added_object(unsigned nr, enum object_type type,
219 void *data, unsigned long size);
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
220
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
221 /*
222 * Write out nr-th object from the list, now we know the contents
223 * of it. Under --strict, this buffers structured objects in-core,
224 * to be checked at the end.
225 */
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
226 static void write_object(unsigned nr, enum object_type type,
227 void *buf, unsigned long size)
cca7081 Clean up git-unpack-objects a bit
Linus Torvalds authored
228 {
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
229 if (!strict) {
230 if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
231 die("failed to write object");
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
232 added_object(nr, type, buf, size);
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
233 free(buf);
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
234 obj_list[nr].obj = NULL;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
235 } else if (type == OBJ_BLOB) {
236 struct blob *blob;
237 if (write_sha1_file(buf, size, typename(type), obj_list[nr].sha1) < 0)
238 die("failed to write object");
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
239 added_object(nr, type, buf, size);
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
240 free(buf);
241
242 blob = lookup_blob(obj_list[nr].sha1);
243 if (blob)
244 blob->object.flags |= FLAG_WRITTEN;
245 else
246 die("invalid blob object");
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
247 obj_list[nr].obj = NULL;
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
248 } else {
249 struct object *obj;
250 int eaten;
251 hash_sha1_file(buf, size, typename(type), obj_list[nr].sha1);
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
252 added_object(nr, type, buf, size);
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
253 obj = parse_object_buffer(obj_list[nr].sha1, type, size, buf, &eaten);
254 if (!obj)
255 die("invalid %s", typename(type));
256 add_object_buffer(obj, buf, size);
257 obj->flags |= FLAG_OPEN;
258 obj_list[nr].obj = obj;
259 }
cca7081 Clean up git-unpack-objects a bit
Linus Torvalds authored
260 }
261
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
262 static void resolve_delta(unsigned nr, enum object_type type,
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
263 void *base, unsigned long base_size,
264 void *delta, unsigned long delta_size)
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
265 {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
266 void *result;
267 unsigned long result_size;
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
268
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
269 result = patch_delta(base, base_size,
270 delta, delta_size,
271 &result_size);
272 if (!result)
273 die("failed to apply delta");
274 free(delta);
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
275 write_object(nr, type, result, result_size);
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
276 }
277
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
278 /*
279 * We now know the contents of an object (which is nr-th in the pack);
280 * resolve all the deltified objects that are based on it.
281 */
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
282 static void added_object(unsigned nr, enum object_type type,
283 void *data, unsigned long size)
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
284 {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
285 struct delta_info **p = &delta_list;
286 struct delta_info *info;
287
288 while ((info = *p) != NULL) {
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
289 if (!hashcmp(info->base_sha1, obj_list[nr].sha1) ||
290 info->base_offset == obj_list[nr].offset) {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
291 *p = info->next;
292 p = &delta_list;
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
293 resolve_delta(info->nr, type, data, size,
294 info->delta, info->size);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
295 free(info);
296 continue;
297 }
298 p = &info->next;
299 }
300 }
301
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
302 static void unpack_non_delta_entry(enum object_type type, unsigned long size,
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
303 unsigned nr)
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
304 {
305 void *buf = get_data(size);
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
306
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
307 if (!dry_run && buf)
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
308 write_object(nr, type, buf, size);
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
309 else
310 free(buf);
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
311 }
312
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
313 static int resolve_against_held(unsigned nr, const unsigned char *base,
314 void *delta_data, unsigned long delta_size)
315 {
316 struct object *obj;
317 struct obj_buffer *obj_buffer;
318 obj = lookup_object(base);
319 if (!obj)
320 return 0;
321 obj_buffer = lookup_object_buffer(obj);
322 if (!obj_buffer)
323 return 0;
324 resolve_delta(nr, obj->type, obj_buffer->buffer,
325 obj_buffer->size, delta_data, delta_size);
326 return 1;
327 }
328
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
329 static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
330 unsigned nr)
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
331 {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
332 void *delta_data, *base;
333 unsigned long base_size;
334 unsigned char base_sha1[20];
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
335
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
336 if (type == OBJ_REF_DELTA) {
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
337 hashcpy(base_sha1, fill(20));
338 use(20);
339 delta_data = get_data(delta_size);
340 if (dry_run || !delta_data) {
341 free(delta_data);
342 return;
343 }
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
344 if (has_sha1_file(base_sha1))
345 ; /* Ok we have this one */
346 else if (resolve_against_held(nr, base_sha1,
347 delta_data, delta_size))
348 return; /* we are done */
349 else {
350 /* cannot resolve yet --- queue it */
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
351 hashcpy(obj_list[nr].sha1, null_sha1);
352 add_delta_to_list(nr, base_sha1, 0, delta_data, delta_size);
353 return;
354 }
355 } else {
356 unsigned base_found = 0;
357 unsigned char *pack, c;
d7dd022 add overflow tests on pack offset variables
Nicolas Pitre authored
358 off_t base_offset;
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
359 unsigned lo, mid, hi;
c4fb06c Fix object packing/unpacking.
Linus Torvalds authored
360
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
361 pack = fill(1);
362 c = *pack;
363 use(1);
364 base_offset = c & 127;
365 while (c & 128) {
366 base_offset += 1;
8723f21 make overflow test on delta base offset work regardless of variable size
Nicolas Pitre authored
367 if (!base_offset || MSB(base_offset, 7))
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
368 die("offset value overflow for delta base object");
369 pack = fill(1);
370 c = *pack;
371 use(1);
372 base_offset = (base_offset << 7) + (c & 127);
373 }
374 base_offset = obj_list[nr].offset - base_offset;
d8f3255 better validation on delta base object offsets
Nicolas Pitre authored
375 if (base_offset <= 0 || base_offset >= obj_list[nr].offset)
376 die("offset value out of bound for delta base object");
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
377
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
378 delta_data = get_data(delta_size);
379 if (dry_run || !delta_data) {
380 free(delta_data);
381 return;
382 }
383 lo = 0;
384 hi = nr;
385 while (lo < hi) {
386 mid = (lo + hi)/2;
387 if (base_offset < obj_list[mid].offset) {
388 hi = mid;
389 } else if (base_offset > obj_list[mid].offset) {
390 lo = mid + 1;
391 } else {
392 hashcpy(base_sha1, obj_list[mid].sha1);
393 base_found = !is_null_sha1(base_sha1);
394 break;
395 }
396 }
397 if (!base_found) {
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
398 /*
399 * The delta base object is itself a delta that
400 * has not been resolved yet.
401 */
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
402 hashcpy(obj_list[nr].sha1, null_sha1);
403 add_delta_to_list(nr, null_sha1, base_offset, delta_data, delta_size);
404 return;
2add1e6 unpack-object: cache for non written objects
Martin Koegler authored
405 }
406 }
407
f2898cf @gitster unpack-objects: fix --strict handling
gitster authored
408 if (resolve_against_held(nr, base_sha1, delta_data, delta_size))
409 return;
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
410
21666f1 convert object type handling from a string to a number
Nicolas Pitre authored
411 base = read_sha1_file(base_sha1, &type, &base_size);
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
412 if (!base) {
413 error("failed to read delta-pack base object %s",
414 sha1_to_hex(base_sha1));
3b67d29 unpack-objects -r: call it "recover".
Junio C Hamano authored
415 if (!recover)
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
416 exit(1);
417 has_errors = 1;
418 return;
419 }
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
420 resolve_delta(nr, type, base, base_size, delta_data, delta_size);
ee63914 @sigprof [PATCH] Plug memory leaks in git-unpack-objects
sigprof authored
421 free(base);
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
422 }
423
96a02f8 common progress display support
Nicolas Pitre authored
424 static void unpack_one(unsigned nr)
8ee378a [PATCH] Finish initial cut of git-pack-object/git-unpack-object pair.
Junio C Hamano authored
425 {
01247d8 Make git pack files use little-endian size encoding
Linus Torvalds authored
426 unsigned shift;
48fb7de @torvalds Fix big left-shifts of unsigned char
torvalds authored
427 unsigned char *pack;
428 unsigned long size, c;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
429 enum object_type type;
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
430
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
431 obj_list[nr].offset = consumed_bytes;
432
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
433 pack = fill(1);
434 c = *pack;
435 use(1);
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
436 type = (c >> 4) & 7;
437 size = (c & 15);
01247d8 Make git pack files use little-endian size encoding
Linus Torvalds authored
438 shift = 4;
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
439 while (c & 0x80) {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
440 pack = fill(1);
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
441 c = *pack;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
442 use(1);
01247d8 Make git pack files use little-endian size encoding
Linus Torvalds authored
443 size += (c & 0x7f) << shift;
444 shift += 7;
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
445 }
96a02f8 common progress display support
Nicolas Pitre authored
446
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
447 switch (type) {
448 case OBJ_COMMIT:
449 case OBJ_TREE:
450 case OBJ_BLOB:
451 case OBJ_TAG:
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
452 unpack_non_delta_entry(type, size, nr);
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
453 return;
eb32d23 introduce delta objects with offset to base
Nicolas Pitre authored
454 case OBJ_REF_DELTA:
209c554 teach git-unpack-objects about deltas with offset to base
Nicolas Pitre authored
455 case OBJ_OFS_DELTA:
456 unpack_delta_entry(type, size, nr);
a733cb6 Change pack file format. Hopefully for the last time.
Linus Torvalds authored
457 return;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
458 default:
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
459 error("bad object type %d", type);
460 has_errors = 1;
3b67d29 unpack-objects -r: call it "recover".
Junio C Hamano authored
461 if (recover)
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
462 return;
463 exit(1);
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
464 }
465 }
466
467 static void unpack_all(void)
468 {
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
469 int i;
dc6a075 make struct progress an opaque type
Nicolas Pitre authored
470 struct progress *progress = NULL;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
471 struct pack_header *hdr = fill(sizeof(struct pack_header));
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
472
473 nr_objects = ntohl(hdr->hdr_entries);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
474
475 if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
476 die("bad pack file");
d60fc1c remove delta-against-self bit
Nicolas Pitre authored
477 if (!pack_version_ok(hdr->hdr_version))
6e1c234 Fix some warnings (on cygwin) to allow -Werror
Ramsay Jones authored
478 die("unknown pack file version %"PRIu32,
479 ntohl(hdr->hdr_version));
96a02f8 common progress display support
Nicolas Pitre authored
480 use(sizeof(struct pack_header));
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
481
13aaf14 make progress "title" part of the common progress interface
Nicolas Pitre authored
482 if (!quiet)
dc6a075 make struct progress an opaque type
Nicolas Pitre authored
483 progress = start_progress("Unpacking objects", nr_objects);
19d4b41 Replace xmalloc/memset(0) pairs with xcalloc
Brandon Casey authored
484 obj_list = xcalloc(nr_objects, sizeof(*obj_list));
96a02f8 common progress display support
Nicolas Pitre authored
485 for (i = 0; i < nr_objects; i++) {
486 unpack_one(i);
4d4fcc5 relax usage of the progress API
Nicolas Pitre authored
487 display_progress(progress, i + 1);
96a02f8 common progress display support
Nicolas Pitre authored
488 }
4d4fcc5 relax usage of the progress API
Nicolas Pitre authored
489 stop_progress(&progress);
96a02f8 common progress display support
Nicolas Pitre authored
490
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
491 if (delta_list)
492 die("unresolved deltas left after unpacking");
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
493 }
494
6441363 @matthiask Make git-unpack-objects a builtin
matthiask authored
495 int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
496 {
497 int i;
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
498 unsigned char sha1[20];
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
499
dae556b @chriscool environment: add global variable to disable replacement
chriscool authored
500 read_replace_refs = 0;
501
ef90d6d @dscho Provide git_config with a callback-data parameter
dscho authored
502 git_config(git_default_config, NULL);
53228a5 Make the rest of commands work from a subdirectory.
Junio C Hamano authored
503
476e801 unpack-objects: default to quiet if stderr is not a tty.
Junio C Hamano authored
504 quiet = !isatty(2);
505
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
506 for (i = 1 ; i < argc; i++) {
507 const char *arg = argv[i];
508
509 if (*arg == '-') {
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
510 if (!strcmp(arg, "-n")) {
511 dry_run = 1;
512 continue;
513 }
d36f7b8 git-unpack-objects: show progress report by default
Linus Torvalds authored
514 if (!strcmp(arg, "-q")) {
515 quiet = 1;
516 continue;
517 }
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
518 if (!strcmp(arg, "-r")) {
3b67d29 unpack-objects -r: call it "recover".
Junio C Hamano authored
519 recover = 1;
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
520 continue;
521 }
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
522 if (!strcmp(arg, "--strict")) {
523 strict = 1;
524 continue;
525 }
cc44c76 Mechanical conversion to use prefixcmp()
Junio C Hamano authored
526 if (!prefixcmp(arg, "--pack_header=")) {
bed006f Allow pack header preprocessing before unpack-objects/index-pack.
Nicolas Pitre authored
527 struct pack_header *hdr;
528 char *c;
529
530 hdr = (struct pack_header *)buffer;
531 hdr->hdr_signature = htonl(PACK_SIGNATURE);
532 hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
533 if (*c != ',')
534 die("bad %s", arg);
535 hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
536 if (*c)
537 die("bad %s", arg);
538 len = sizeof(*hdr);
539 continue;
540 }
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
541 usage(unpack_usage);
542 }
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
543
544 /* We don't take any non-flag arguments now.. Maybe some day */
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
545 usage(unpack_usage);
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
546 }
9126f00 fix openssl headers conflicting with custom SHA1 implementations
Nicolas Pitre authored
547 git_SHA1_Init(&ctx);
7453695 git-unpack-objects: start parsing the actual packed data
Linus Torvalds authored
548 unpack_all();
9126f00 fix openssl headers conflicting with custom SHA1 implementations
Nicolas Pitre authored
549 git_SHA1_Update(&ctx, buffer, offset);
550 git_SHA1_Final(sha1, &ctx);
b41860b unpack-objects: prevent writing of inconsistent objects
Martin Koegler authored
551 if (strict)
552 write_rest();
a89fccd Do not use memcmp(sha1_1, sha1_2, 20) with hardcoded length.
David Rientjes authored
553 if (hashcmp(fill(20), sha1))
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
554 die("final sha1 did not match");
555 use(20);
556
557 /* Write the last part of the buffer to stdout */
558 while (len) {
1c15afb xread/xwrite: do not worry about EINTR at calling sites.
Junio C Hamano authored
559 int ret = xwrite(1, buffer + offset, len);
560 if (ret <= 0)
67e5a5e git-unpack-objects: re-write to read from stdin
Linus Torvalds authored
561 break;
562 len -= ret;
563 offset += ret;
564 }
565
566 /* All done */
f986f2c unpack-objects desperately salvages objects from a corrupt pack
Junio C Hamano authored
567 return has_errors;
bad50dc First cut at git-unpack-objects
Linus Torvalds authored
568 }
Something went wrong with that request. Please try again.