teach sha1_object_info_extended a "disk_size" query
authorJeff King <peff@peff.net>
Sun, 7 Jul 2013 10:04:00 +0000 (06:04 -0400)
committerJunio C Hamano <gitster@pobox.com>
Sun, 7 Jul 2013 17:53:22 +0000 (10:53 -0700)
Using sha1_object_info_extended, a caller can find out the
type of an object, its size, and information about where it
is stored. In addition to the object's "true" size, it can
also be useful to know the size that the object takes on
disk (e.g., to generate statistics about which refs consume
space).

This patch adds a "disk_sizep" field to "struct object_info",
and fills it in during sha1_object_info_extended if it is
non-NULL.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
cache.h
sha1_file.c
diff --git a/cache.h b/cache.h
index 94ca1acf704bd2dfdc561b6b2d3d64740b975f61..f2915509a64b828f1b0bd78cecb9f091577ac874 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1099,6 +1099,7 @@ extern int unpack_object_header(struct packed_git *, struct pack_window **, off_
 struct object_info {
        /* Request */
        unsigned long *sizep;
+       unsigned long *disk_sizep;
 
        /* Response */
        enum {
index 79ef052b1139354f2d6a8e77cd238d9eb1f0d5ec..6baed676dcf131464806e06c8cdd1f10d5df076d 100644 (file)
@@ -1694,7 +1694,8 @@ static int retry_bad_packed_offset(struct packed_git *p, off_t obj_offset)
 #define POI_STACK_PREALLOC 64
 
 static int packed_object_info(struct packed_git *p, off_t obj_offset,
-                             unsigned long *sizep, int *rtype)
+                             unsigned long *sizep, int *rtype,
+                             unsigned long *disk_sizep)
 {
        struct pack_window *w_curs = NULL;
        unsigned long size;
@@ -1728,6 +1729,11 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
                }
        }
 
+       if (disk_sizep) {
+               struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
+               *disk_sizep = revidx[1].offset - obj_offset;
+       }
+
        while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
                off_t base_offset;
                /* Push the object we're going to leave behind */
@@ -2338,7 +2344,8 @@ struct packed_git *find_sha1_pack(const unsigned char *sha1,
 
 }
 
-static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep)
+static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep,
+                                 unsigned long *disk_sizep)
 {
        int status;
        unsigned long mapsize, size;
@@ -2349,6 +2356,8 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
        map = map_sha1_file(sha1, &mapsize);
        if (!map)
                return error("unable to find %s", sha1_to_hex(sha1));
+       if (disk_sizep)
+               *disk_sizep = mapsize;
        if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
                status = error("unable to unpack %s header",
                               sha1_to_hex(sha1));
@@ -2372,13 +2381,15 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
        if (co) {
                if (oi->sizep)
                        *(oi->sizep) = co->size;
+               if (oi->disk_sizep)
+                       *(oi->disk_sizep) = 0;
                oi->whence = OI_CACHED;
                return co->type;
        }
 
        if (!find_pack_entry(sha1, &e)) {
                /* Most likely it's a loose object. */
-               status = sha1_loose_object_info(sha1, oi->sizep);
+               status = sha1_loose_object_info(sha1, oi->sizep, oi->disk_sizep);
                if (status >= 0) {
                        oi->whence = OI_LOOSE;
                        return status;
@@ -2390,7 +2401,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
                        return status;
        }
 
-       status = packed_object_info(e.p, e.offset, oi->sizep, &rtype);
+       status = packed_object_info(e.p, e.offset, oi->sizep, &rtype,
+                                   oi->disk_sizep);
        if (status < 0) {
                mark_bad_packed_object(e.p, sha1);
                status = sha1_object_info_extended(sha1, oi);