@matheusbsbs / matheus-bagliano / commits / 64bd76b1de
Fork 0

pack-objects: allow "fixing" a corrupted pack without a full repack

When the pack data to be reused is found to be bad, let's fall back to full object access through the generic path which has its own strategies to find alternate object sources in that case. This allows for "fixing" a corrupted pack simply by copying either another pack containing the object(s) found to be bad, or the loose object itself, into the object store and launch a repack without the need for -f. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nicolas Pitre committed Oct 29, 2008 at 19:02 UTC 64bd76b1de75483dea646c39c390113ffc821299
1 file changed +19 -9
builtin-pack-objects.c
+19 -9
@@ -277,6 +277,7 @@ static unsigned long write_object(struct sha1file *f,
277 */
278
279 if (!to_reuse) {
280 + no_reuse:
281 if (!usable_delta) {
282 buf = read_sha1_file(entry->idx.sha1, &type, &size);
283 if (!buf)
@@ -358,20 +359,30 @@ static unsigned long write_object(struct sha1file *f,
359 struct revindex_entry *revidx;
360 off_t offset;
361
361 - if (entry->delta) {
362 + if (entry->delta)
363 type = (allow_ofs_delta && entry->delta->idx.offset) ?
364 OBJ_OFS_DELTA : OBJ_REF_DELTA;
364 - reused_delta++;
365 - }
365 hdrlen = encode_header(type, entry->size, header);
366 +
367 offset = entry->in_pack_offset;
368 revidx = find_pack_revindex(p, offset);
369 datalen = revidx[1].offset - offset;
370 if (!pack_to_stdout && p->index_version > 1 &&
371 - check_pack_crc(p, &w_curs, offset, datalen, revidx->nr))
372 - die("bad packed object CRC for %s", sha1_to_hex(entry->idx.sha1));
371 + check_pack_crc(p, &w_curs, offset, datalen, revidx->nr)) {
372 + error("bad packed object CRC for %s", sha1_to_hex(entry->idx.sha1));
373 + unuse_pack(&w_curs);
374 + goto no_reuse;
375 + }
376 +
377 offset += entry->in_pack_header_size;
378 datalen -= entry->in_pack_header_size;
379 + if (!pack_to_stdout && p->index_version == 1 &&
380 + check_pack_inflate(p, &w_curs, offset, datalen, entry->size)) {
381 + error("corrupt packed object for %s", sha1_to_hex(entry->idx.sha1));
382 + unuse_pack(&w_curs);
383 + goto no_reuse;
384 + }
385 +
386 if (type == OBJ_OFS_DELTA) {
387 off_t ofs = entry->idx.offset - entry->delta->idx.offset;
388 unsigned pos = sizeof(dheader) - 1;
@@ -383,21 +394,19 @@ static unsigned long write_object(struct sha1file *f,
394 sha1write(f, header, hdrlen);
395 sha1write(f, dheader + pos, sizeof(dheader) - pos);
396 hdrlen += sizeof(dheader) - pos;
397 + reused_delta++;
398 } else if (type == OBJ_REF_DELTA) {
399 if (limit && hdrlen + 20 + datalen + 20 >= limit)
400 return 0;
401 sha1write(f, header, hdrlen);
402 sha1write(f, entry->delta->idx.sha1, 20);
403 hdrlen += 20;
404 + reused_delta++;
405 } else {
406 if (limit && hdrlen + datalen + 20 >= limit)
407 return 0;
408 sha1write(f, header, hdrlen);
409 }
397 -
398 - if (!pack_to_stdout && p->index_version == 1 &&
399 - check_pack_inflate(p, &w_curs, offset, datalen, entry->size))
400 - die("corrupt packed object for %s", sha1_to_hex(entry->idx.sha1));
410 copy_pack_data(f, p, &w_curs, offset, datalen);
411 unuse_pack(&w_curs);
412 reused++;
@@ -1074,6 +1083,7 @@ static void check_object(struct object_entry *entry)
1083 */
1084 entry->type = entry->in_pack_type;
1085 entry->delta = base_entry;
1086 + entry->delta_size = entry->size;
1087 entry->delta_sibling = base_entry->delta_child;
1088 base_entry->delta_child = entry;
1089 unuse_pack(&w_curs);