This makes it match the new delta encoding, and admittedly makes the
code easier to follow.
This also updates the PACK file version to 2, since this (and the delta
encoding change in the previous commit) are incompatible with the old
format.
tag.o date.o index.o diff-delta.o patch-delta.o entry.o \
epoch.o refs.o csum-file.o
LIB_FILE=libgit.a
tag.o date.o index.o diff-delta.o patch-delta.o entry.o \
epoch.o refs.o csum-file.o
LIB_FILE=libgit.a
-LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h
+LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h csum-file.h pack.h
LIB_H += strbuf.h
LIB_OBJS += strbuf.o
LIB_H += strbuf.h
LIB_OBJS += strbuf.o
*/
static int encode_header(enum object_type type, unsigned long size, unsigned char *hdr)
{
*/
static int encode_header(enum object_type type, unsigned long size, unsigned char *hdr)
{
unsigned char c;
if (type < OBJ_COMMIT || type > OBJ_DELTA)
die("bad type %d", type);
unsigned char c;
if (type < OBJ_COMMIT || type > OBJ_DELTA)
die("bad type %d", type);
- /*
- * Shift the size up by 7 bits at a time,
- * until you get bits in the "high four".
- * That will be our beginning. We'll have
- * four size bits in 28..31, then groups
- * of seven in 21..27, 14..20, 7..13 and
- * finally 0..6.
- */
- if (size) {
- n = 5;
- while (!(size & 0xfe000000)) {
- size <<= 7;
- n--;
- }
- }
- c = (type << 4) | (size >> 28);
- for (i = 1; i < n; i++) {
+ c = (type << 4) | (size & 15);
+ size >>= 4;
+ while (size) {
- c = (size >> 21) & 0x7f;
- size <<= 7;
+ c = size & 0x7f;
+ size >>= 7;
+ n++;
else
f = sha1create("%s.%s", base_name, "pack");
hdr.hdr_signature = htonl(PACK_SIGNATURE);
else
f = sha1create("%s.%s", base_name, "pack");
hdr.hdr_signature = htonl(PACK_SIGNATURE);
- hdr.hdr_version = htonl(1);
+ hdr.hdr_version = htonl(PACK_VERSION);
hdr.hdr_entries = htonl(nr_objects);
sha1write(f, &hdr, sizeof(hdr));
offset = sizeof(hdr);
hdr.hdr_entries = htonl(nr_objects);
sha1write(f, &hdr, sizeof(hdr));
offset = sizeof(hdr);
#ifndef PACK_H
#define PACK_H
#ifndef PACK_H
#define PACK_H
+/*
+ * The packed object type is stored in 3 bits.
+ * The type value 0 is a reserved prefix if ever there is more than 7
+ * object types, or any future format extensions.
+ */
- OBJ_NONE,
- OBJ_COMMIT,
- OBJ_TREE,
- OBJ_BLOB,
- OBJ_TAG,
- OBJ_DELTA,
+ OBJ_EXT = 0,
+ OBJ_COMMIT = 1,
+ OBJ_TREE = 2,
+ OBJ_BLOB = 3,
+ OBJ_TAG = 4,
+ /* 5/6 for future expansion */
+ OBJ_DELTA = 7,
};
/*
* Packed object header
*/
#define PACK_SIGNATURE 0x5041434b /* "PACK" */
};
/*
* Packed object header
*/
#define PACK_SIGNATURE 0x5041434b /* "PACK" */
struct pack_header {
unsigned int hdr_signature;
unsigned int hdr_version;
struct pack_header {
unsigned int hdr_signature;
unsigned int hdr_version;
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
enum object_type *type, unsigned long *sizep)
{
static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
enum object_type *type, unsigned long *sizep)
{
unsigned char *pack, c;
unsigned long size;
unsigned char *pack, c;
unsigned long size;
offset++;
*type = (c >> 4) & 7;
size = c & 15;
offset++;
*type = (c >> 4) & 7;
size = c & 15;
while (c & 0x80) {
if (offset >= p->pack_size)
die("object offset outside of pack file");
c = *pack++;
offset++;
while (c & 0x80) {
if (offset >= p->pack_size)
die("object offset outside of pack file");
c = *pack++;
offset++;
- size = (size << 7) | (c & 0x7f);
+ size += (c & 0x7f) << shift;
+ shift += 7;
}
*sizep = size;
return offset;
}
*sizep = size;
return offset;
static void unpack_one(void)
{
static void unpack_one(void)
{
unsigned char *pack, c;
unsigned long size;
enum object_type type;
unsigned char *pack, c;
unsigned long size;
enum object_type type;
use(1);
type = (c >> 4) & 7;
size = (c & 15);
use(1);
type = (c >> 4) & 7;
size = (c & 15);
while (c & 0x80) {
pack = fill(1);
c = *pack++;
use(1);
while (c & 0x80) {
pack = fill(1);
c = *pack++;
use(1);
- size = (size << 7) + (c & 0x7f);
+ size += (c & 0x7f) << shift;
+ shift += 7;
}
switch (type) {
case OBJ_COMMIT:
}
switch (type) {
case OBJ_COMMIT:
if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
die("bad pack file");
if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
die("bad pack file");
+ if (version != PACK_VERSION)
die("unable to handle pack file version %d", version);
fprintf(stderr, "Unpacking %d objects\n", nr_objects);
die("unable to handle pack file version %d", version);
fprintf(stderr, "Unpacking %d objects\n", nr_objects);