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
*/
static int encode_header(enum object_type type, unsigned long size, unsigned char *hdr)
{
- int n = 1, i;
+ int n = 1;
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) {
*hdr++ = c | 0x80;
- c = (size >> 21) & 0x7f;
- size <<= 7;
+ c = size & 0x7f;
+ size >>= 7;
+ n++;
}
*hdr = c;
return n;
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);
#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.
+ */
enum object_type {
- 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" */
+#define PACK_VERSION 2
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)
{
+ unsigned shift;
unsigned char *pack, c;
unsigned long size;
offset++;
*type = (c >> 4) & 7;
size = c & 15;
+ shift = 4;
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;
static void unpack_one(void)
{
+ unsigned shift;
unsigned char *pack, c;
unsigned long size;
enum object_type type;
use(1);
type = (c >> 4) & 7;
size = (c & 15);
+ shift = 4;
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:
if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
die("bad pack file");
- if (version != 1)
+ if (version != PACK_VERSION)
die("unable to handle pack file version %d", version);
fprintf(stderr, "Unpacking %d objects\n", nr_objects);