index-pack.c 24.2 KB
Newer Older
S
Sergey Vlasov 已提交
1 2 3 4
#include "cache.h"
#include "delta.h"
#include "pack.h"
#include "csum-file.h"
5 6 7 8
#include "blob.h"
#include "commit.h"
#include "tag.h"
#include "tree.h"
N
Nicolas Pitre 已提交
9
#include "progress.h"
10
#include "fsck.h"
S
Sergey Vlasov 已提交
11 12

static const char index_pack_usage[] =
13
"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
S
Sergey Vlasov 已提交
14 15 16

struct object_entry
{
G
Geert Bosch 已提交
17
	struct pack_idx_entry idx;
18 19
	unsigned long size;
	unsigned int hdr_size;
S
Sergey Vlasov 已提交
20 21 22 23
	enum object_type type;
	enum object_type real_type;
};

24 25
union delta_base {
	unsigned char sha1[20];
26
	off_t offset;
27 28
};

29 30 31 32 33 34
/*
 * Even if sizeof(union delta_base) == 24 on 64-bit archs, we really want
 * to memcmp() only the first 20 bytes.
 */
#define UNION_BASE_SZ	20

35 36 37
#define FLAG_LINK (1u<<20)
#define FLAG_CHECKED (1u<<21)

S
Sergey Vlasov 已提交
38 39
struct delta_entry
{
40
	union delta_base base;
41
	int obj_no;
S
Sergey Vlasov 已提交
42 43 44 45 46 47
};

static struct object_entry *objects;
static struct delta_entry *deltas;
static int nr_objects;
static int nr_deltas;
48
static int nr_resolved_deltas;
S
Sergey Vlasov 已提交
49

50
static int from_stdin;
51
static int strict;
N
Nicolas Pitre 已提交
52 53
static int verbose;

54
static struct progress *progress;
55

56 57
/* We always read in 4kB chunks. */
static unsigned char input_buffer[4096];
58 59
static unsigned int input_offset, input_len;
static off_t consumed_bytes;
60
static SHA_CTX input_ctx;
61
static uint32_t input_crc32;
62
static int input_fd, output_fd, pack_fd;
63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
static int mark_link(struct object *obj, int type, void *data)
{
	if (!obj)
		return -1;

	if (type != OBJ_ANY && obj->type != type)
		die("object type mismatch at %s", sha1_to_hex(obj->sha1));

	obj->flags |= FLAG_LINK;
	return 0;
}

/* The content of each linked object must have been checked
   or it must be already present in the object database */
static void check_object(struct object *obj)
{
	if (!obj)
		return;

	if (!(obj->flags & FLAG_LINK))
		return;

	if (!(obj->flags & FLAG_CHECKED)) {
		unsigned long size;
		int type = sha1_object_info(obj->sha1, &size);
		if (type != obj->type || type <= 0)
			die("object of unexpected type");
		obj->flags |= FLAG_CHECKED;
		return;
	}
}

static void check_objects(void)
{
	unsigned i, max;

	max = get_max_object_index();
	for (i = 0; i < max; i++)
		check_object(get_indexed_object(i));
}


106
/* Discard current buffer used content. */
107
static void flush(void)
108 109 110 111 112
{
	if (input_offset) {
		if (output_fd >= 0)
			write_or_die(output_fd, input_buffer, input_offset);
		SHA1_Update(&input_ctx, input_buffer, input_offset);
113
		memmove(input_buffer, input_buffer + input_offset, input_len);
114 115 116 117
		input_offset = 0;
	}
}

118 119 120 121
/*
 * Make sure at least "min" bytes are available in the buffer, and
 * return the pointer to the buffer.
 */
122
static void *fill(int min)
S
Sergey Vlasov 已提交
123
{
124 125 126 127
	if (min <= input_len)
		return input_buffer + input_offset;
	if (min > sizeof(input_buffer))
		die("cannot fill %d bytes", min);
128
	flush();
129
	do {
130
		ssize_t ret = xread(input_fd, input_buffer + input_len,
131 132 133 134 135 136 137
				sizeof(input_buffer) - input_len);
		if (ret <= 0) {
			if (!ret)
				die("early EOF");
			die("read error on input: %s", strerror(errno));
		}
		input_len += ret;
138 139
		if (from_stdin)
			display_throughput(progress, consumed_bytes + input_len);
140 141 142 143 144 145 146 147
	} while (input_len < min);
	return input_buffer;
}

static void use(int bytes)
{
	if (bytes > input_len)
		die("used more bytes than were available");
148
	input_crc32 = crc32(input_crc32, input_buffer + input_offset, bytes);
149 150
	input_len -= bytes;
	input_offset += bytes;
151 152 153 154

	/* make sure off_t is sufficiently large not to wrap */
	if (consumed_bytes > consumed_bytes + bytes)
		die("pack too large for current definition of off_t");
155 156
	consumed_bytes += bytes;
}
S
Sergey Vlasov 已提交
157

158
static char *open_pack_file(char *pack_name)
159
{
160 161 162 163 164
	if (from_stdin) {
		input_fd = 0;
		if (!pack_name) {
			static char tmpfile[PATH_MAX];
			snprintf(tmpfile, sizeof(tmpfile),
165
				 "%s/tmp_pack_XXXXXX", get_object_directory());
166
			output_fd = xmkstemp(tmpfile);
167 168 169 170 171
			pack_name = xstrdup(tmpfile);
		} else
			output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
		if (output_fd < 0)
			die("unable to create %s: %s\n", pack_name, strerror(errno));
172
		pack_fd = output_fd;
173 174 175 176 177 178
	} else {
		input_fd = open(pack_name, O_RDONLY);
		if (input_fd < 0)
			die("cannot open packfile '%s': %s",
			    pack_name, strerror(errno));
		output_fd = -1;
179
		pack_fd = input_fd;
180
	}
181
	SHA1_Init(&input_ctx);
182
	return pack_name;
S
Sergey Vlasov 已提交
183 184 185 186
}

static void parse_pack_header(void)
{
187
	struct pack_header *hdr = fill(sizeof(struct pack_header));
S
Sergey Vlasov 已提交
188 189 190

	/* Header consistency check */
	if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
191
		die("pack signature mismatch");
N
Nicolas Pitre 已提交
192
	if (!pack_version_ok(hdr->hdr_version))
193
		die("pack version %d unsupported", ntohl(hdr->hdr_version));
S
Sergey Vlasov 已提交
194 195

	nr_objects = ntohl(hdr->hdr_entries);
196
	use(sizeof(struct pack_header));
S
Sergey Vlasov 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209
}

static void bad_object(unsigned long offset, const char *format,
		       ...) NORETURN __attribute__((format (printf, 2, 3)));

static void bad_object(unsigned long offset, const char *format, ...)
{
	va_list params;
	char buf[1024];

	va_start(params, format);
	vsnprintf(buf, sizeof(buf), format, params);
	va_end(params);
210
	die("pack has bad object at offset %lu: %s", offset, buf);
S
Sergey Vlasov 已提交
211 212
}

213
static void *unpack_entry_data(unsigned long offset, unsigned long size)
S
Sergey Vlasov 已提交
214 215 216 217 218 219 220
{
	z_stream stream;
	void *buf = xmalloc(size);

	memset(&stream, 0, sizeof(stream));
	stream.next_out = buf;
	stream.avail_out = size;
221 222
	stream.next_in = fill(1);
	stream.avail_in = input_len;
S
Sergey Vlasov 已提交
223 224 225 226
	inflateInit(&stream);

	for (;;) {
		int ret = inflate(&stream, 0);
227 228
		use(input_len - stream.avail_in);
		if (stream.total_out == size && ret == Z_STREAM_END)
S
Sergey Vlasov 已提交
229 230 231
			break;
		if (ret != Z_OK)
			bad_object(offset, "inflate returned %d", ret);
232 233
		stream.next_in = fill(1);
		stream.avail_in = input_len;
S
Sergey Vlasov 已提交
234 235 236 237 238
	}
	inflateEnd(&stream);
	return buf;
}

239
static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_base)
S
Sergey Vlasov 已提交
240
{
241
	unsigned char *p, c;
242 243
	unsigned long size;
	off_t base_offset;
S
Sergey Vlasov 已提交
244
	unsigned shift;
245
	void *data;
S
Sergey Vlasov 已提交
246

G
Geert Bosch 已提交
247
	obj->idx.offset = consumed_bytes;
248
	input_crc32 = crc32(0, Z_NULL, 0);
249 250 251 252 253

	p = fill(1);
	c = *p;
	use(1);
	obj->type = (c >> 4) & 7;
S
Sergey Vlasov 已提交
254 255 256
	size = (c & 15);
	shift = 4;
	while (c & 0x80) {
257 258 259
		p = fill(1);
		c = *p;
		use(1);
S
Sergey Vlasov 已提交
260 261 262
		size += (c & 0x7fUL) << shift;
		shift += 7;
	}
263
	obj->size = size;
S
Sergey Vlasov 已提交
264

265
	switch (obj->type) {
266
	case OBJ_REF_DELTA:
267 268
		hashcpy(delta_base->sha1, fill(20));
		use(20);
269 270 271
		break;
	case OBJ_OFS_DELTA:
		memset(delta_base, 0, sizeof(*delta_base));
272 273 274
		p = fill(1);
		c = *p;
		use(1);
275 276 277
		base_offset = c & 127;
		while (c & 128) {
			base_offset += 1;
278
			if (!base_offset || MSB(base_offset, 7))
G
Geert Bosch 已提交
279
				bad_object(obj->idx.offset, "offset value overflow for delta base object");
280 281 282
			p = fill(1);
			c = *p;
			use(1);
283 284
			base_offset = (base_offset << 7) + (c & 127);
		}
G
Geert Bosch 已提交
285 286 287
		delta_base->offset = obj->idx.offset - base_offset;
		if (delta_base->offset >= obj->idx.offset)
			bad_object(obj->idx.offset, "delta base offset is out of bound");
288
		break;
S
Sergey Vlasov 已提交
289 290 291 292 293 294
	case OBJ_COMMIT:
	case OBJ_TREE:
	case OBJ_BLOB:
	case OBJ_TAG:
		break;
	default:
G
Geert Bosch 已提交
295
		bad_object(obj->idx.offset, "unknown object type %d", obj->type);
S
Sergey Vlasov 已提交
296
	}
G
Geert Bosch 已提交
297
	obj->hdr_size = consumed_bytes - obj->idx.offset;
298

G
Geert Bosch 已提交
299 300
	data = unpack_entry_data(obj->idx.offset, obj->size);
	obj->idx.crc32 = input_crc32;
301
	return data;
302 303
}

304
static void *get_data_from_pack(struct object_entry *obj)
305
{
306
	off_t from = obj[0].idx.offset + obj[0].hdr_size;
G
Geert Bosch 已提交
307
	unsigned long len = obj[1].idx.offset - from;
308
	unsigned long rdy = 0;
309
	unsigned char *src, *data;
310 311
	z_stream stream;
	int st;
S
Sergey Vlasov 已提交
312

313
	src = xmalloc(len);
314 315 316 317 318 319 320
	data = src;
	do {
		ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
		if (n <= 0)
			die("cannot pread pack file: %s", strerror(errno));
		rdy += n;
	} while (rdy < len);
321 322 323 324
	data = xmalloc(obj->size);
	memset(&stream, 0, sizeof(stream));
	stream.next_out = data;
	stream.avail_out = obj->size;
325
	stream.next_in = src;
326 327 328 329 330 331
	stream.avail_in = len;
	inflateInit(&stream);
	while ((st = inflate(&stream, Z_FINISH)) == Z_OK);
	inflateEnd(&stream);
	if (st != Z_STREAM_END || stream.total_out != obj->size)
		die("serious inflate inconsistency");
332
	free(src);
S
Sergey Vlasov 已提交
333 334 335
	return data;
}

336
static int find_delta(const union delta_base *base)
S
Sergey Vlasov 已提交
337 338 339 340 341 342 343 344
{
	int first = 0, last = nr_deltas;

        while (first < last) {
                int next = (first + last) / 2;
                struct delta_entry *delta = &deltas[next];
                int cmp;

345
                cmp = memcmp(base, &delta->base, UNION_BASE_SZ);
S
Sergey Vlasov 已提交
346 347 348 349 350 351 352 353 354 355 356
                if (!cmp)
                        return next;
                if (cmp < 0) {
                        last = next;
                        continue;
                }
                first = next+1;
        }
        return -first-1;
}

357 358
static int find_delta_children(const union delta_base *base,
			       int *first_index, int *last_index)
S
Sergey Vlasov 已提交
359
{
360
	int first = find_delta(base);
S
Sergey Vlasov 已提交
361 362 363 364 365
	int last = first;
	int end = nr_deltas - 1;

	if (first < 0)
		return -1;
366
	while (first > 0 && !memcmp(&deltas[first - 1].base, base, UNION_BASE_SZ))
S
Sergey Vlasov 已提交
367
		--first;
368
	while (last < end && !memcmp(&deltas[last + 1].base, base, UNION_BASE_SZ))
S
Sergey Vlasov 已提交
369 370 371 372 373 374 375
		++last;
	*first_index = first;
	*last_index = last;
	return 0;
}

static void sha1_object(const void *data, unsigned long size,
376
			enum object_type type, unsigned char *sha1)
S
Sergey Vlasov 已提交
377
{
N
Nicolas Pitre 已提交
378
	hash_sha1_file(data, size, typename(type), sha1);
379
	if (has_sha1_file(sha1)) {
380 381 382 383 384 385 386 387 388
		void *has_data;
		enum object_type has_type;
		unsigned long has_size;
		has_data = read_sha1_file(sha1, &has_type, &has_size);
		if (!has_data)
			die("cannot read existing object %s", sha1_to_hex(sha1));
		if (size != has_size || type != has_type ||
		    memcmp(data, has_data, size) != 0)
			die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1));
389
		free(has_data);
390
	}
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
	if (strict) {
		if (type == OBJ_BLOB) {
			struct blob *blob = lookup_blob(sha1);
			if (blob)
				blob->object.flags |= FLAG_CHECKED;
			else
				die("invalid blob object %s", sha1_to_hex(sha1));
		} else {
			struct object *obj;
			int eaten;
			void *buf = (void *) data;

			/*
			 * we do not need to free the memory here, as the
			 * buf is deleted by the caller.
			 */
			obj = parse_object_buffer(sha1, type, size, buf, &eaten);
			if (!obj)
				die("invalid %s", typename(type));
			if (fsck_object(obj, 1, fsck_error_function))
				die("Error in object");
			if (fsck_walk(obj, mark_link, 0))
				die("Not all child objects of %s are reachable", sha1_to_hex(obj->sha1));

			if (obj->type == OBJ_TREE) {
				struct tree *item = (struct tree *) obj;
				item->buffer = NULL;
			}
			if (obj->type == OBJ_COMMIT) {
				struct commit *commit = (struct commit *) obj;
				commit->buffer = NULL;
			}
			obj->flags |= FLAG_CHECKED;
		}
	}
S
Sergey Vlasov 已提交
426 427
}

428
static void resolve_delta(struct object_entry *delta_obj, void *base_data,
S
Sergey Vlasov 已提交
429 430 431 432 433 434
			  unsigned long base_size, enum object_type type)
{
	void *delta_data;
	unsigned long delta_size;
	void *result;
	unsigned long result_size;
435
	union delta_base delta_base;
S
Sergey Vlasov 已提交
436 437
	int j, first, last;

438 439 440
	delta_obj->real_type = type;
	delta_data = get_data_from_pack(delta_obj);
	delta_size = delta_obj->size;
S
Sergey Vlasov 已提交
441 442 443 444
	result = patch_delta(base_data, base_size, delta_data, delta_size,
			     &result_size);
	free(delta_data);
	if (!result)
G
Geert Bosch 已提交
445 446
		bad_object(delta_obj->idx.offset, "failed to apply delta");
	sha1_object(result, result_size, type, delta_obj->idx.sha1);
447
	nr_resolved_deltas++;
448

G
Geert Bosch 已提交
449
	hashcpy(delta_base.sha1, delta_obj->idx.sha1);
450
	if (!find_delta_children(&delta_base, &first, &last)) {
451 452 453 454 455
		for (j = first; j <= last; j++) {
			struct object_entry *child = objects + deltas[j].obj_no;
			if (child->real_type == OBJ_REF_DELTA)
				resolve_delta(child, result, result_size, type);
		}
456 457 458
	}

	memset(&delta_base, 0, sizeof(delta_base));
G
Geert Bosch 已提交
459
	delta_base.offset = delta_obj->idx.offset;
460
	if (!find_delta_children(&delta_base, &first, &last)) {
461 462 463 464 465
		for (j = first; j <= last; j++) {
			struct object_entry *child = objects + deltas[j].obj_no;
			if (child->real_type == OBJ_OFS_DELTA)
				resolve_delta(child, result, result_size, type);
		}
S
Sergey Vlasov 已提交
466
	}
467

S
Sergey Vlasov 已提交
468 469 470 471 472 473 474
	free(result);
}

static int compare_delta_entry(const void *a, const void *b)
{
	const struct delta_entry *delta_a = a;
	const struct delta_entry *delta_b = b;
475
	return memcmp(&delta_a->base, &delta_b->base, UNION_BASE_SZ);
S
Sergey Vlasov 已提交
476 477
}

478 479
/* Parse all objects and return the pack content SHA1 hash */
static void parse_pack_objects(unsigned char *sha1)
S
Sergey Vlasov 已提交
480
{
N
Nicolas Pitre 已提交
481
	int i;
482
	struct delta_entry *delta = deltas;
S
Sergey Vlasov 已提交
483
	void *data;
484
	struct stat st;
S
Sergey Vlasov 已提交
485 486 487 488 489

	/*
	 * First pass:
	 * - find locations of all objects;
	 * - calculate SHA1 of all non-delta objects;
490
	 * - remember base (SHA1 or offset) for all deltas.
S
Sergey Vlasov 已提交
491
	 */
492
	if (verbose)
493 494 495
		progress = start_progress(
				from_stdin ? "Receiving objects" : "Indexing objects",
				nr_objects);
S
Sergey Vlasov 已提交
496 497
	for (i = 0; i < nr_objects; i++) {
		struct object_entry *obj = &objects[i];
498
		data = unpack_raw_entry(obj, &delta->base);
S
Sergey Vlasov 已提交
499
		obj->real_type = obj->type;
500 501
		if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA) {
			nr_deltas++;
502
			delta->obj_no = i;
503
			delta++;
S
Sergey Vlasov 已提交
504
		} else
G
Geert Bosch 已提交
505
			sha1_object(data, obj->size, obj->type, obj->idx.sha1);
S
Sergey Vlasov 已提交
506
		free(data);
N
Nicolas Pitre 已提交
507
		display_progress(progress, i+1);
S
Sergey Vlasov 已提交
508
	}
G
Geert Bosch 已提交
509
	objects[i].idx.offset = consumed_bytes;
N
Nicolas Pitre 已提交
510
	stop_progress(&progress);
511 512

	/* Check pack integrity */
513
	flush();
514 515
	SHA1_Final(sha1, &input_ctx);
	if (hashcmp(fill(20), sha1))
516
		die("pack is corrupted (SHA1 mismatch)");
517
	use(20);
518 519 520

	/* If input_fd is a file, we should have reached its end now. */
	if (fstat(input_fd, &st))
521
		die("cannot fstat packfile: %s", strerror(errno));
J
Johannes Schindelin 已提交
522 523
	if (S_ISREG(st.st_mode) &&
			lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
524
		die("pack has junk at the end");
S
Sergey Vlasov 已提交
525

N
Nicolas Pitre 已提交
526 527 528
	if (!nr_deltas)
		return;

529
	/* Sort deltas by base SHA1/offset for fast searching */
S
Sergey Vlasov 已提交
530 531 532 533 534 535 536 537 538 539 540
	qsort(deltas, nr_deltas, sizeof(struct delta_entry),
	      compare_delta_entry);

	/*
	 * Second pass:
	 * - for all non-delta objects, look if it is used as a base for
	 *   deltas;
	 * - if used as a base, uncompress the object and apply all deltas,
	 *   recursively checking if the resulting object is used as a base
	 *   for some more deltas.
	 */
541
	if (verbose)
542
		progress = start_progress("Resolving deltas", nr_deltas);
S
Sergey Vlasov 已提交
543 544
	for (i = 0; i < nr_objects; i++) {
		struct object_entry *obj = &objects[i];
545 546
		union delta_base base;
		int j, ref, ref_first, ref_last, ofs, ofs_first, ofs_last;
S
Sergey Vlasov 已提交
547

548
		if (obj->type == OBJ_REF_DELTA || obj->type == OBJ_OFS_DELTA)
S
Sergey Vlasov 已提交
549
			continue;
G
Geert Bosch 已提交
550
		hashcpy(base.sha1, obj->idx.sha1);
551
		ref = !find_delta_children(&base, &ref_first, &ref_last);
552
		memset(&base, 0, sizeof(base));
G
Geert Bosch 已提交
553
		base.offset = obj->idx.offset;
554
		ofs = !find_delta_children(&base, &ofs_first, &ofs_last);
555
		if (!ref && !ofs)
S
Sergey Vlasov 已提交
556
			continue;
557
		data = get_data_from_pack(obj);
558
		if (ref)
559 560 561 562
			for (j = ref_first; j <= ref_last; j++) {
				struct object_entry *child = objects + deltas[j].obj_no;
				if (child->real_type == OBJ_REF_DELTA)
					resolve_delta(child, data,
563
						      obj->size, obj->type);
564
			}
565
		if (ofs)
566 567 568 569
			for (j = ofs_first; j <= ofs_last; j++) {
				struct object_entry *child = objects + deltas[j].obj_no;
				if (child->real_type == OBJ_OFS_DELTA)
					resolve_delta(child, data,
570
						      obj->size, obj->type);
571
			}
S
Sergey Vlasov 已提交
572
		free(data);
N
Nicolas Pitre 已提交
573
		display_progress(progress, nr_resolved_deltas);
S
Sergey Vlasov 已提交
574
	}
575 576
}

577
static int write_compressed(int fd, void *in, unsigned int size, uint32_t *obj_crc)
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
{
	z_stream stream;
	unsigned long maxsize;
	void *out;

	memset(&stream, 0, sizeof(stream));
	deflateInit(&stream, zlib_compression_level);
	maxsize = deflateBound(&stream, size);
	out = xmalloc(maxsize);

	/* Compress it */
	stream.next_in = in;
	stream.avail_in = size;
	stream.next_out = out;
	stream.avail_out = maxsize;
	while (deflate(&stream, Z_FINISH) == Z_OK);
	deflateEnd(&stream);

	size = stream.total_out;
	write_or_die(fd, out, size);
598
	*obj_crc = crc32(*obj_crc, out, size);
599 600 601 602
	free(out);
	return size;
}

603
static void append_obj_to_pack(const unsigned char *sha1, void *buf,
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
			       unsigned long size, enum object_type type)
{
	struct object_entry *obj = &objects[nr_objects++];
	unsigned char header[10];
	unsigned long s = size;
	int n = 0;
	unsigned char c = (type << 4) | (s & 15);
	s >>= 4;
	while (s) {
		header[n++] = c | 0x80;
		c = s & 0x7f;
		s >>= 7;
	}
	header[n++] = c;
	write_or_die(output_fd, header, n);
G
Geert Bosch 已提交
619 620 621 622 623
	obj[0].idx.crc32 = crc32(0, Z_NULL, 0);
	obj[0].idx.crc32 = crc32(obj[0].idx.crc32, header, n);
	obj[1].idx.offset = obj[0].idx.offset + n;
	obj[1].idx.offset += write_compressed(output_fd, buf, size, &obj[0].idx.crc32);
	hashcpy(obj->idx.sha1, sha1);
624 625 626 627 628 629 630 631
}

static int delta_pos_compare(const void *_a, const void *_b)
{
	struct delta_entry *a = *(struct delta_entry **)_a;
	struct delta_entry *b = *(struct delta_entry **)_b;
	return a->obj_no - b->obj_no;
}
S
Sergey Vlasov 已提交
632

633 634 635
static void fix_unresolved_deltas(int nr_unresolved)
{
	struct delta_entry **sorted_by_pos;
N
Nicolas Pitre 已提交
636
	int i, n = 0;
637 638 639 640 641 642 643 644 645 646 647 648

	/*
	 * Since many unresolved deltas may well be themselves base objects
	 * for more unresolved deltas, we really want to include the
	 * smallest number of base objects that would cover as much delta
	 * as possible by picking the
	 * trunc deltas first, allowing for other deltas to resolve without
	 * additional base objects.  Since most base objects are to be found
	 * before deltas depending on them, a good heuristic is to start
	 * resolving deltas in the same order as their position in the pack.
	 */
	sorted_by_pos = xmalloc(nr_unresolved * sizeof(*sorted_by_pos));
S
Sergey Vlasov 已提交
649
	for (i = 0; i < nr_deltas; i++) {
650 651 652
		if (objects[deltas[i].obj_no].real_type != OBJ_REF_DELTA)
			continue;
		sorted_by_pos[n++] = &deltas[i];
S
Sergey Vlasov 已提交
653
	}
654 655 656 657 658 659
	qsort(sorted_by_pos, n, sizeof(*sorted_by_pos), delta_pos_compare);

	for (i = 0; i < n; i++) {
		struct delta_entry *d = sorted_by_pos[i];
		void *data;
		unsigned long size;
660
		enum object_type type;
661 662 663 664
		int j, first, last;

		if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
			continue;
665
		data = read_sha1_file(d->base.sha1, &type, &size);
666 667 668
		if (!data)
			continue;

669
		find_delta_children(&d->base, &first, &last);
670 671 672
		for (j = first; j <= last; j++) {
			struct object_entry *child = objects + deltas[j].obj_no;
			if (child->real_type == OBJ_REF_DELTA)
673
				resolve_delta(child, data, size, type);
674 675
		}

676 677 678
		if (check_sha1_signature(d->base.sha1, data, size, typename(type)))
			die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
		append_obj_to_pack(d->base.sha1, data, size, type);
679
		free(data);
N
Nicolas Pitre 已提交
680
		display_progress(progress, nr_resolved_deltas);
681 682 683 684
	}
	free(sorted_by_pos);
}

685 686
static void final(const char *final_pack_name, const char *curr_pack_name,
		  const char *final_index_name, const char *curr_index_name,
687
		  const char *keep_name, const char *keep_msg,
688 689
		  unsigned char *sha1)
{
690
	const char *report = "pack";
691 692 693 694 695 696
	char name[PATH_MAX];
	int err;

	if (!from_stdin) {
		close(input_fd);
	} else {
697
		fsync_or_die(output_fd, curr_pack_name);
698 699 700 701 702 703
		err = close(output_fd);
		if (err)
			die("error while closing pack file: %s", strerror(errno));
		chmod(curr_pack_name, 0444);
	}

704 705 706 707 708 709 710
	if (keep_msg) {
		int keep_fd, keep_msg_len = strlen(keep_msg);
		if (!keep_name) {
			snprintf(name, sizeof(name), "%s/pack/pack-%s.keep",
				 get_object_directory(), sha1_to_hex(sha1));
			keep_name = name;
		}
711 712 713 714 715 716 717 718 719
		keep_fd = open(keep_name, O_RDWR|O_CREAT|O_EXCL, 0600);
		if (keep_fd < 0) {
			if (errno != EEXIST)
				die("cannot write keep file");
		} else {
			if (keep_msg_len > 0) {
				write_or_die(keep_fd, keep_msg, keep_msg_len);
				write_or_die(keep_fd, "\n", 1);
			}
720 721
			if (close(keep_fd) != 0)
				die("cannot write keep file");
722
			report = "keep";
723 724 725
		}
	}

726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
	if (final_pack_name != curr_pack_name) {
		if (!final_pack_name) {
			snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
				 get_object_directory(), sha1_to_hex(sha1));
			final_pack_name = name;
		}
		if (move_temp_to_file(curr_pack_name, final_pack_name))
			die("cannot store pack file");
	}

	chmod(curr_index_name, 0444);
	if (final_index_name != curr_index_name) {
		if (!final_index_name) {
			snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
				 get_object_directory(), sha1_to_hex(sha1));
			final_index_name = name;
		}
		if (move_temp_to_file(curr_index_name, final_index_name))
			die("cannot store index file");
	}
746 747 748 749 750 751 752

	if (!from_stdin) {
		printf("%s\n", sha1_to_hex(sha1));
	} else {
		char buf[48];
		int len = snprintf(buf, sizeof(buf), "%s\t%s\n",
				   report, sha1_to_hex(sha1));
753
		write_or_die(1, buf, len);
754 755 756 757 758 759 760 761 762 763 764 765 766

		/*
		 * Let's just mimic git-unpack-objects here and write
		 * the last part of the input buffer to stdout.
		 */
		while (input_len) {
			err = xwrite(1, input_buffer + input_offset, input_len);
			if (err <= 0)
				break;
			input_len -= err;
			input_offset += err;
		}
	}
S
Sergey Vlasov 已提交
767 768
}

769
static int git_index_pack_config(const char *k, const char *v, void *cb)
770 771 772 773 774 775 776
{
	if (!strcmp(k, "pack.indexversion")) {
		pack_idx_default_version = git_config_int(k, v);
		if (pack_idx_default_version > 2)
			die("bad pack.indexversion=%d", pack_idx_default_version);
		return 0;
	}
777
	return git_default_config(k, v, cb);
778 779
}

S
Sergey Vlasov 已提交
780 781
int main(int argc, char **argv)
{
782
	int i, fix_thin_pack = 0;
783 784
	char *curr_pack, *pack_name = NULL;
	char *curr_index, *index_name = NULL;
785 786
	const char *keep_name = NULL, *keep_msg = NULL;
	char *index_name_buf = NULL, *keep_name_buf = NULL;
G
Geert Bosch 已提交
787
	struct pack_idx_entry **idx_objects;
J
Junio C Hamano 已提交
788
	unsigned char sha1[20];
S
Sergey Vlasov 已提交
789

790
	git_config(git_index_pack_config, NULL);
791

S
Sergey Vlasov 已提交
792
	for (i = 1; i < argc; i++) {
793
		char *arg = argv[i];
S
Sergey Vlasov 已提交
794 795

		if (*arg == '-') {
796 797
			if (!strcmp(arg, "--stdin")) {
				from_stdin = 1;
798 799
			} else if (!strcmp(arg, "--fix-thin")) {
				fix_thin_pack = 1;
800 801
			} else if (!strcmp(arg, "--strict")) {
				strict = 1;
802 803
			} else if (!strcmp(arg, "--keep")) {
				keep_msg = "";
804
			} else if (!prefixcmp(arg, "--keep=")) {
805
				keep_msg = arg + 7;
806
			} else if (!prefixcmp(arg, "--pack_header=")) {
807 808 809 810 811 812 813 814 815 816 817 818
				struct pack_header *hdr;
				char *c;

				hdr = (struct pack_header *)input_buffer;
				hdr->hdr_signature = htonl(PACK_SIGNATURE);
				hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
				if (*c != ',')
					die("bad %s", arg);
				hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
				if (*c)
					die("bad %s", arg);
				input_len = sizeof(*hdr);
N
Nicolas Pitre 已提交
819 820
			} else if (!strcmp(arg, "-v")) {
				verbose = 1;
821
			} else if (!strcmp(arg, "-o")) {
S
Sergey Vlasov 已提交
822 823 824
				if (index_name || (i+1) >= argc)
					usage(index_pack_usage);
				index_name = argv[++i];
825 826
			} else if (!prefixcmp(arg, "--index-version=")) {
				char *c;
G
Geert Bosch 已提交
827 828
				pack_idx_default_version = strtoul(arg + 16, &c, 10);
				if (pack_idx_default_version > 2)
829 830
					die("bad %s", arg);
				if (*c == ',')
G
Geert Bosch 已提交
831 832
					pack_idx_off32_limit = strtoul(c+1, &c, 0);
				if (*c || pack_idx_off32_limit & 0x80000000)
833
					die("bad %s", arg);
S
Sergey Vlasov 已提交
834 835 836 837 838 839 840 841 842 843
			} else
				usage(index_pack_usage);
			continue;
		}

		if (pack_name)
			usage(index_pack_usage);
		pack_name = arg;
	}

844
	if (!pack_name && !from_stdin)
S
Sergey Vlasov 已提交
845
		usage(index_pack_usage);
846 847
	if (fix_thin_pack && !from_stdin)
		die("--fix-thin cannot be used without --stdin");
848
	if (!index_name && pack_name) {
S
Sergey Vlasov 已提交
849
		int len = strlen(pack_name);
850
		if (!has_extension(pack_name, ".pack"))
S
Sergey Vlasov 已提交
851 852
			die("packfile name '%s' does not end with '.pack'",
			    pack_name);
P
Pavel Roskin 已提交
853
		index_name_buf = xmalloc(len);
S
Sergey Vlasov 已提交
854 855 856 857
		memcpy(index_name_buf, pack_name, len - 5);
		strcpy(index_name_buf + len - 5, ".idx");
		index_name = index_name_buf;
	}
858 859 860 861 862 863 864 865 866 867
	if (keep_msg && !keep_name && pack_name) {
		int len = strlen(pack_name);
		if (!has_extension(pack_name, ".pack"))
			die("packfile name '%s' does not end with '.pack'",
			    pack_name);
		keep_name_buf = xmalloc(len);
		memcpy(keep_name_buf, pack_name, len - 5);
		strcpy(keep_name_buf + len - 5, ".keep");
		keep_name = keep_name_buf;
	}
S
Sergey Vlasov 已提交
868

869
	curr_pack = open_pack_file(pack_name);
S
Sergey Vlasov 已提交
870
	parse_pack_header();
871 872
	objects = xmalloc((nr_objects + 1) * sizeof(struct object_entry));
	deltas = xmalloc(nr_objects * sizeof(struct delta_entry));
873
	parse_pack_objects(sha1);
N
Nicolas Pitre 已提交
874
	if (nr_deltas == nr_resolved_deltas) {
N
Nicolas Pitre 已提交
875
		stop_progress(&progress);
N
Nicolas Pitre 已提交
876 877 878
		/* Flush remaining pack final 20-byte SHA1. */
		flush();
	} else {
879
		if (fix_thin_pack) {
880
			char msg[48];
881
			int nr_unresolved = nr_deltas - nr_resolved_deltas;
N
Nicolas Pitre 已提交
882
			int nr_objects_initial = nr_objects;
883 884 885 886 887 888
			if (nr_unresolved <= 0)
				die("confusion beyond insanity");
			objects = xrealloc(objects,
					   (nr_objects + nr_unresolved + 1)
					   * sizeof(*objects));
			fix_unresolved_deltas(nr_unresolved);
889 890 891
			sprintf(msg, "completed with %d local objects",
				nr_objects - nr_objects_initial);
			stop_progress_msg(&progress, msg);
892
			fixup_pack_header_footer(output_fd, sha1,
893
						 curr_pack, nr_objects);
894 895 896 897 898
		}
		if (nr_deltas != nr_resolved_deltas)
			die("pack has %d unresolved deltas",
			    nr_deltas - nr_resolved_deltas);
	}
S
Sergey Vlasov 已提交
899
	free(deltas);
900 901
	if (strict)
		check_objects();
G
Geert Bosch 已提交
902 903 904 905 906 907 908

	idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *));
	for (i = 0; i < nr_objects; i++)
		idx_objects[i] = &objects[i].idx;
	curr_index = write_idx_file(index_name, idx_objects, nr_objects, sha1);
	free(idx_objects);

909 910 911 912
	final(pack_name, curr_pack,
		index_name, curr_index,
		keep_name, keep_msg,
		sha1);
S
Sergey Vlasov 已提交
913 914
	free(objects);
	free(index_name_buf);
915
	free(keep_name_buf);
N
Nicolas Pitre 已提交
916 917 918 919
	if (pack_name == NULL)
		free(curr_pack);
	if (index_name == NULL)
		free(curr_index);
S
Sergey Vlasov 已提交
920 921 922

	return 0;
}