Change pack file format. Hopefully for the last time.

This also adds a header with a signature, version info, and the number
of objects to the pack file.  It also encodes the file length and type
more efficiently.
This commit is contained in:
Linus Torvalds
2005-06-28 14:21:02 -07:00
parent d22b9290ab
commit a733cb606f
4 changed files with 175 additions and 74 deletions

View File

@ -1,6 +1,7 @@
#include "cache.h"
#include "object.h"
#include "delta.h"
#include "pack.h"
static int dry_run;
static int nr_entries;
@ -92,7 +93,7 @@ static int check_index(void)
}
static int unpack_non_delta_entry(struct pack_entry *entry,
int kind,
enum object_type kind,
unsigned char *data,
unsigned long size,
unsigned long left)
@ -101,9 +102,9 @@ static int unpack_non_delta_entry(struct pack_entry *entry,
z_stream stream;
char *buffer;
unsigned char sha1[20];
char *type_s;
char *type;
printf("%s %c %lu\n", sha1_to_hex(entry->sha1), kind, size);
printf("%s %c %lu\n", sha1_to_hex(entry->sha1), ".CTBGD"[kind], size);
if (dry_run)
return 0;
@ -121,18 +122,18 @@ static int unpack_non_delta_entry(struct pack_entry *entry,
if ((st != Z_STREAM_END) || stream.total_out != size)
goto err_finish;
switch (kind) {
case 'C': type_s = "commit"; break;
case 'T': type_s = "tree"; break;
case 'B': type_s = "blob"; break;
case 'G': type_s = "tag"; break;
case OBJ_COMMIT: type = "commit"; break;
case OBJ_TREE: type = "tree"; break;
case OBJ_BLOB: type = "blob"; break;
case OBJ_TAG: type = "tag"; break;
default: goto err_finish;
}
if (write_sha1_file(buffer, size, type_s, sha1) < 0)
if (write_sha1_file(buffer, size, type, sha1) < 0)
die("failed to write %s (%s)",
sha1_to_hex(entry->sha1), type_s);
printf("%s %s\n", sha1_to_hex(sha1), type_s);
sha1_to_hex(entry->sha1), type);
printf("%s %s\n", sha1_to_hex(sha1), type);
if (memcmp(sha1, entry->sha1, 20))
die("resulting %s have wrong SHA1", type_s);
die("resulting %s have wrong SHA1", type);
finish:
st = 0;
@ -237,28 +238,44 @@ static int unpack_delta_entry(struct pack_entry *entry,
static void unpack_entry(struct pack_entry *entry)
{
unsigned long offset, size, left;
unsigned char *pack;
unsigned char *pack, c;
int type;
/* Have we done this one already due to deltas based on it? */
if (lookup_object(entry->sha1))
return;
offset = ntohl(entry->offset);
if (offset > pack_size - 5)
die("object offset outside of pack file");
if (offset >= pack_size)
goto bad;
pack = pack_base + offset;
size = (pack[1] << 24) + (pack[2] << 16) + (pack[3] << 8) + pack[4];
left = pack_size - offset - 5;
switch (*pack) {
case 'C': case 'T': case 'B': case 'G':
unpack_non_delta_entry(entry, *pack, pack+5, size, left);
break;
case 'D':
unpack_delta_entry(entry, pack+5, size, left);
break;
default:
die("corrupted pack file");
c = *pack++;
offset++;
type = (c >> 4) & 7;
size = (c & 15);
while (c & 0x80) {
if (offset >= pack_size)
goto bad;
offset++;
c = *pack++;
size = (size << 7) + (c & 0x7f);
}
left = pack_size - offset;
switch (type) {
case OBJ_COMMIT:
case OBJ_TREE:
case OBJ_BLOB:
case OBJ_TAG:
unpack_non_delta_entry(entry, type, pack, size, left);
return;
case OBJ_DELTA:
unpack_delta_entry(entry, pack+5, size, left);
return;
}
bad:
die("corrupted pack file");
}
/*