}
}
+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;
#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;
}
}
+ 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 */
error("failed to unpack compressed delta "
"at offset %"PRIuMAX" from %s",
(uintmax_t)curpos, p->pack_name);
- free(base);
data = NULL;
continue;
}
}
-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 mapsize, size;
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));
+ 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));
*sizep = size;
git_inflate_end(&stream);
munmap(map, mapsize);
- return status;
+ if (typep)
+ *typep = status;
+ return 0;
}
/* returns enum object_type or negative */
{
struct cached_object *co;
struct pack_entry e;
- int status, rtype;
+ int type, rtype;
co = find_cached_object(sha1);
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);
- if (status >= 0) {
+ if (!sha1_loose_object_info(sha1, &type,
+ oi->sizep, oi->disk_sizep)) {
oi->whence = OI_LOOSE;
- return status;
+ return type;
}
/* Not a loose object; someone else may have just packed it. */
reprepare_packed_git();
if (!find_pack_entry(sha1, &e))
- return status;
+ return -1;
}
- status = packed_object_info(e.p, e.offset, oi->sizep, &rtype);
- if (status < 0) {
+ type = packed_object_info(e.p, e.offset, oi->sizep, &rtype,
+ oi->disk_sizep);
+ if (type < 0) {
mark_bad_packed_object(e.p, sha1);
- status = sha1_object_info_extended(sha1, oi);
+ type = sha1_object_info_extended(sha1, oi);
} else if (in_delta_base_cache(e.p, e.offset)) {
oi->whence = OI_DBCACHED;
} else {
rtype == OBJ_OFS_DELTA);
}
- return status;
+ return type;
}
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);