compute a CRC32 for each object as stored in a pack
[gitweb.git] / builtin-pack-objects.c
index 45ac3e482acc1c0f8f2bad043f1ba50019dec505..03e36f01830bc246eaccac85a36a0368d15c9995 100644 (file)
@@ -44,6 +44,7 @@ struct object_entry {
                                 * be used as the base objectto delta huge
                                 * objects against.
                                 */
+       uint32_t crc32;         /* crc of raw pack data for this object */
 };
 
 /*
@@ -164,7 +165,7 @@ static int cmp_offset(const void *a_, const void *b_)
 static void prepare_pack_revindex(struct pack_revindex *rix)
 {
        struct packed_git *p = rix->p;
-       int num_ent = num_packed_objects(p);
+       int num_ent = p->num_objects;
        int i;
        const char *index = p->index_data;
 
@@ -198,7 +199,7 @@ static struct revindex_entry * find_packed_object(struct packed_git *p,
                prepare_pack_revindex(rix);
        revindex = rix->revindex;
        lo = 0;
-       hi = num_packed_objects(p) + 1;
+       hi = p->num_objects + 1;
        do {
                int mi = (lo + hi) / 2;
                if (revindex[mi].offset == ofs) {
@@ -369,7 +370,7 @@ static int revalidate_loose_object(struct object_entry *entry,
        return check_loose_inflate(map, mapsize, size);
 }
 
-static off_t write_object(struct sha1file *f,
+static unsigned long write_object(struct sha1file *f,
                                  struct object_entry *entry)
 {
        unsigned long size;
@@ -381,6 +382,9 @@ static off_t write_object(struct sha1file *f,
        enum object_type obj_type;
        int to_reuse = 0;
 
+       if (!pack_to_stdout)
+               crc32_begin(f);
+
        obj_type = entry->type;
        if (! entry->in_pack)
                to_reuse = 0;   /* can't reuse what we don't have */
@@ -496,6 +500,8 @@ static off_t write_object(struct sha1file *f,
        if (entry->delta)
                written_delta++;
        written++;
+       if (!pack_to_stdout)
+               entry->crc32 = crc32_end(f);
        return hdrlen + datalen;
 }
 
@@ -503,16 +509,23 @@ static off_t write_one(struct sha1file *f,
                               struct object_entry *e,
                               off_t offset)
 {
+       unsigned long size;
+
+       /* offset is non zero if object is written already. */
        if (e->offset || e->preferred_base)
-               /* offset starts from header size and cannot be zero
-                * if it is written already.
-                */
                return offset;
-       /* if we are deltified, write out its base object first. */
+
+       /* if we are deltified, write out base object first. */
        if (e->delta)
                offset = write_one(f, e->delta, offset);
+
        e->offset = offset;
-       return offset + write_object(f, e);
+       size = write_object(f, e);
+
+       /* make sure off_t is sufficiently large not to wrap */
+       if (offset > offset + size)
+               die("pack too large for current definition of off_t");
+       return offset + size;
 }
 
 static void write_pack_file(void)
@@ -1014,7 +1027,7 @@ static void check_object(struct object_entry *entry)
                                ofs = c & 127;
                                while (c & 128) {
                                        ofs += 1;
-                                       if (!ofs || ofs & ~(~0UL >> 7))
+                                       if (!ofs || MSB(ofs, 7))
                                                die("delta base offset overflow in pack for %s",
                                                    sha1_to_hex(entry->sha1));
                                        c = buf[used_0++];