send-email: don't call methods on undefined values
[gitweb.git] / sha1_file.c
index 16f08d475cde5e96282aa830dd3373277c2b898f..4c2365f48f7ce361e009d5f4d9323184f6782d34 100644 (file)
@@ -1697,7 +1697,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;
@@ -1731,6 +1732,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 */
@@ -2145,8 +2151,17 @@ void *unpack_entry(struct packed_git *p, off_t obj_offset,
                data = patch_delta(base, base_size,
                                   delta_data, delta_size,
                                   &size);
+
+               /*
+                * We could not apply the delta; warn the user, but keep going.
+                * Our failure will be noticed either in the next iteration of
+                * the loop, or if this is the final delta, in the caller when
+                * we return NULL. Those code paths will take care of making
+                * a more explicit warning and retrying with another copy of
+                * the object.
+                */
                if (!data)
-                       die("failed to apply delta");
+                       error("failed to apply delta");
 
                free(delta_data);
        }
@@ -2348,7 +2363,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;
@@ -2359,6 +2375,8 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
        map = map_sha1_file(sha1, &mapsize);
        if (!map)
                return -1;
+       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));
@@ -2382,13 +2400,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;
@@ -2400,7 +2420,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);
@@ -2419,7 +2440,7 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi)
 
 int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 {
-       struct object_info oi;
+       struct object_info oi = {0};
 
        oi.sizep = sizep;
        return sha1_object_info_extended(sha1, &oi);