sha1_loose_object_info: make type lookup optional
authorJeff King <peff@peff.net>
Fri, 12 Jul 2013 06:30:48 +0000 (02:30 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 12 Jul 2013 17:10:04 +0000 (10:10 -0700)
Until recently, the only items to request from
sha1_object_info_extended were type and size. This meant
that we always had to open a loose object file to determine
one or the other. But with the addition of the disk_size
query, it's possible that we can fulfill the query without
even opening the object file at all. However, since the
function interface always returns the type, we have no way
of knowing whether the caller cares about it or not.

This patch only modified sha1_loose_object_info to make type
lookup optional using an out-parameter, similar to the way
the size is handled (and the return value is "0" or "-1" for
success or error, respectively).

There should be no functional change yet, though, as
sha1_object_info_extended, the only caller, will always ask
for a type.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sha1_file.c
index f13dea3355b6428b5d4a3faf6f54269569422038..285337819e3b9f8ca608a9e47e2e65fff8d725ce 100644 (file)
@@ -1303,6 +1303,26 @@ static int git_open_noatime(const char *name)
        }
 }
 
        }
 }
 
+static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
+{
+       char *name = sha1_file_name(sha1);
+       struct alternate_object_database *alt;
+
+       if (!lstat(name, st))
+               return 0;
+
+       prepare_alt_odb();
+       errno = ENOENT;
+       for (alt = alt_odb_list; alt; alt = alt->next) {
+               name = alt->name;
+               fill_sha1_path(name, sha1);
+               if (!lstat(alt->base, st))
+                       return 0;
+       }
+
+       return -1;
+}
+
 static int open_sha1_file(const unsigned char *sha1)
 {
        int fd;
 static int open_sha1_file(const unsigned char *sha1)
 {
        int fd;
@@ -2344,7 +2364,9 @@ 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,
+                                 enum object_type *typep,
+                                 unsigned long *sizep,
                                  unsigned long *disk_sizep)
 {
        int status;
                                  unsigned long *disk_sizep)
 {
        int status;
@@ -2353,6 +2375,20 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
        git_zstream stream;
        char hdr[32];
 
        git_zstream stream;
        char hdr[32];
 
+       /*
+        * If we don't care about type or size, then we don't
+        * need to look inside the object at all.
+        */
+       if (!typep && !sizep) {
+               if (disk_sizep) {
+                       struct stat st;
+                       if (stat_sha1_file(sha1, &st) < 0)
+                               return -1;
+                       *disk_sizep = st.st_size;
+               }
+               return 0;
+       }
+
        map = map_sha1_file(sha1, &mapsize);
        if (!map)
                return error("unable to find %s", sha1_to_hex(sha1));
        map = map_sha1_file(sha1, &mapsize);
        if (!map)
                return error("unable to find %s", sha1_to_hex(sha1));
@@ -2367,7 +2403,9 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
                *sizep = size;
        git_inflate_end(&stream);
        munmap(map, mapsize);
                *sizep = size;
        git_inflate_end(&stream);
        munmap(map, mapsize);
-       return status;
+       if (typep)
+               *typep = status;
+       return 0;
 }
 
 /* returns enum object_type or negative */
 }
 
 /* returns enum object_type or negative */
@@ -2389,8 +2427,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
 
        if (!find_pack_entry(sha1, &e)) {
                /* Most likely it's a loose object. */
 
        if (!find_pack_entry(sha1, &e)) {
                /* Most likely it's a loose object. */
-               type = sha1_loose_object_info(sha1, oi->sizep, oi->disk_sizep);
-               if (type >= 0) {
+               if (!sha1_loose_object_info(sha1, &type,
+                                           oi->sizep, oi->disk_sizep)) {
                        oi->whence = OI_LOOSE;
                        return type;
                }
                        oi->whence = OI_LOOSE;
                        return type;
                }
@@ -2398,7 +2436,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
                /* Not a loose object; someone else may have just packed it. */
                reprepare_packed_git();
                if (!find_pack_entry(sha1, &e))
                /* Not a loose object; someone else may have just packed it. */
                reprepare_packed_git();
                if (!find_pack_entry(sha1, &e))
-                       return type;
+                       return -1;
        }
 
        type = packed_object_info(e.p, e.offset, oi->sizep, &rtype,
        }
 
        type = packed_object_info(e.p, e.offset, oi->sizep, &rtype,