const unsigned char null_sha1[20];
+static const char *no_log_pack_access = "no_log_pack_access";
+static const char *log_pack_access;
+
/*
* This is meant to hold a *small* number of objects that you would
* want read_sha1_file() to be able to return, but yet you do not want
#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 */
{
static FILE *log_file;
+ if (!log_pack_access)
+ log_pack_access = getenv("GIT_TRACE_PACK_ACCESS");
+ if (!log_pack_access)
+ log_pack_access = no_log_pack_access;
+ if (log_pack_access == no_log_pack_access)
+ return;
+
if (!log_file) {
log_file = fopen(log_pack_access, "w");
if (!log_file) {
error("cannot open pack access log '%s' for writing: %s",
log_pack_access, strerror(errno));
- log_pack_access = NULL;
+ log_pack_access = no_log_pack_access;
return;
}
}
int delta_stack_nr = 0, delta_stack_alloc = UNPACK_ENTRY_STACK_PREALLOC;
int base_from_cache = 0;
- if (log_pack_access)
+ if (log_pack_access != no_log_pack_access)
write_pack_access_log(p, obj_offset);
/* PHASE 1: drill down to the innermost base object */
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);
}
}
-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;
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));
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;
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);
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);