diff options
-rw-r--r-- | builtin-pack-objects.c | 16 | ||||
-rw-r--r-- | cache.h | 4 | ||||
-rw-r--r-- | pack-check.c | 22 | ||||
-rw-r--r-- | sha1_file.c | 110 |
4 files changed, 85 insertions, 67 deletions
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 4a00a1206f..6d7ae7f1ae 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -416,6 +416,7 @@ static unsigned long write_object(struct sha1file *f, } else { struct packed_git *p = entry->in_pack; + struct pack_window *w_curs = NULL; if (entry->delta) { obj_type = (allow_ofs_delta && entry->delta->offset) ? @@ -437,16 +438,14 @@ static unsigned long write_object(struct sha1file *f, hdrlen += 20; } - use_packed_git(p); - buf = p->windows->base - + entry->in_pack_offset - + entry->in_pack_header_size; + buf = use_pack(p, &w_curs, entry->in_pack_offset + + entry->in_pack_header_size, NULL); datalen = find_packed_object_size(p, entry->in_pack_offset) - entry->in_pack_header_size; if (!pack_to_stdout && check_inflate(buf, datalen, entry->size)) die("corrupt delta in pack %s", sha1_to_hex(entry->sha1)); sha1write(f, buf, datalen); - unuse_packed_git(p); + unuse_pack(&w_curs); reused++; } if (entry->delta) @@ -937,14 +936,13 @@ static void check_object(struct object_entry *entry) if (entry->in_pack && !entry->preferred_base) { struct packed_git *p = entry->in_pack; + struct pack_window *w_curs = NULL; unsigned long left = p->pack_size - entry->in_pack_offset; unsigned long size, used; unsigned char *buf; struct object_entry *base_entry = NULL; - use_packed_git(p); - buf = p->windows->base; - buf += entry->in_pack_offset; + buf = use_pack(p, &w_curs, entry->in_pack_offset, NULL); /* We want in_pack_type even if we do not reuse delta. * There is no point not reusing non-delta representations. @@ -990,7 +988,7 @@ static void check_object(struct object_entry *entry) if (base_name) base_entry = locate_object_entry(base_name); } - unuse_packed_git(p); + unuse_pack(&w_curs); entry->in_pack_header_size = used; if (base_entry) { @@ -397,8 +397,8 @@ extern void install_packed_git(struct packed_git *pack); extern struct packed_git *find_sha1_pack(const unsigned char *sha1, struct packed_git *packs); -extern int use_packed_git(struct packed_git *); -extern void unuse_packed_git(struct packed_git *); +extern unsigned char* use_pack(struct packed_git *, struct pack_window **, unsigned long, unsigned int *); +extern void unuse_pack(struct pack_window **); extern struct packed_git *add_packed_git(char *, int, int); extern int num_packed_objects(const struct packed_git *p); extern int nth_packed_object_sha1(const struct packed_git *, int, unsigned char*); diff --git a/pack-check.c b/pack-check.c index 761cc852e9..972916f406 100644 --- a/pack-check.c +++ b/pack-check.c @@ -1,7 +1,8 @@ #include "cache.h" #include "pack.h" -static int verify_packfile(struct packed_git *p) +static int verify_packfile(struct packed_git *p, + struct pack_window **w_curs) { unsigned long index_size = p->index_size; void *index_base = p->index_base; @@ -13,7 +14,7 @@ static int verify_packfile(struct packed_git *p) int nr_objects, err, i; /* Header consistency check */ - pack_base = p->windows->base; + pack_base = use_pack(p, w_curs, 0, NULL); hdr = (struct pack_header*)pack_base; if (hdr->hdr_signature != htonl(PACK_SIGNATURE)) return error("Packfile %s signature mismatch", p->pack_name); @@ -72,13 +73,14 @@ static int verify_packfile(struct packed_git *p) #define MAX_CHAIN 40 -static void show_pack_info(struct packed_git *p) +static void show_pack_info(struct packed_git *p, + struct pack_window **w_curs) { struct pack_header *hdr; int nr_objects, i; unsigned int chain_histogram[MAX_CHAIN]; - hdr = (struct pack_header*)p->windows->base; + hdr = (struct pack_header*)use_pack(p, w_curs, 0, NULL); nr_objects = ntohl(hdr->hdr_entries); memset(chain_histogram, 0, sizeof(chain_histogram)); @@ -142,18 +144,18 @@ int verify_pack(struct packed_git *p, int verbose) if (!ret) { /* Verify pack file */ - use_packed_git(p); - ret = verify_packfile(p); - unuse_packed_git(p); + struct pack_window *w_curs = NULL; + ret = verify_packfile(p, &w_curs); + unuse_pack(&w_curs); } if (verbose) { if (ret) printf("%s: bad\n", p->pack_name); else { - use_packed_git(p); - show_pack_info(p); - unuse_packed_git(p); + struct pack_window *w_curs = NULL; + show_pack_info(p, &w_curs); + unuse_pack(&w_curs); printf("%s: ok\n", p->pack_name); } } diff --git a/sha1_file.c b/sha1_file.c index 79d2d9dacd..4d80527baf 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -470,10 +470,13 @@ static int unuse_one_packed_git(void) return 1; } -void unuse_packed_git(struct packed_git *p) +void unuse_pack(struct pack_window **w_cursor) { - if (p->windows) - p->windows->inuse_cnt--; + struct pack_window *w = *w_cursor; + if (w) { + w->inuse_cnt--; + *w_cursor = NULL; + } } static void open_packed_git(struct packed_git *p) @@ -518,13 +521,16 @@ static void open_packed_git(struct packed_git *p) die("packfile %s does not match index", p->pack_name); } -int use_packed_git(struct packed_git *p) +unsigned char* use_pack(struct packed_git *p, + struct pack_window **w_cursor, + unsigned long offset, + unsigned int *left) { + struct pack_window *win = p->windows; + if (p->pack_fd == -1) open_packed_git(p); - if (!p->windows) { - struct pack_window *win; - + if (!win) { pack_mapped += p->pack_size; while (packed_git_limit < pack_mapped && unuse_one_packed_git()) ; /* nothing */ @@ -535,9 +541,14 @@ int use_packed_git(struct packed_git *p) die("packfile %s cannot be mapped.", p->pack_name); p->windows = win; } - p->windows->last_used = pack_used_ctr++; - p->windows->inuse_cnt++; - return 0; + if (win != *w_cursor) { + win->last_used = pack_used_ctr++; + win->inuse_cnt++; + *w_cursor = win; + } + if (left) + *left = win->len - offset; + return win->base + offset; } struct packed_git *add_packed_git(char *path, int path_len, int local) @@ -883,12 +894,13 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned l } static unsigned long get_delta_base(struct packed_git *p, + struct pack_window **w_curs, unsigned long offset, enum object_type kind, unsigned long delta_obj_offset, unsigned long *base_obj_offset) { - unsigned char *base_info = p->windows->base + offset; + unsigned char *base_info = use_pack(p, w_curs, offset, NULL); unsigned long base_offset; /* there must be at least 20 bytes left regardless of delta type */ @@ -928,6 +940,7 @@ static int packed_object_info(struct packed_git *p, unsigned long offset, char *type, unsigned long *sizep); static int packed_delta_info(struct packed_git *p, + struct pack_window **w_curs, unsigned long offset, enum object_type kind, unsigned long obj_offset, @@ -936,7 +949,8 @@ static int packed_delta_info(struct packed_git *p, { unsigned long base_offset; - offset = get_delta_base(p, offset, kind, obj_offset, &base_offset); + offset = get_delta_base(p, w_curs, offset, kind, + obj_offset, &base_offset); /* We choose to only get the type of the base object and * ignore potentially corrupt pack file that expects the delta @@ -955,8 +969,7 @@ static int packed_delta_info(struct packed_git *p, memset(&stream, 0, sizeof(stream)); - stream.next_in = p->windows->base + offset; - stream.avail_in = p->pack_size - offset; + stream.next_in = use_pack(p, w_curs, offset, &stream.avail_in); stream.next_out = delta_head; stream.avail_out = sizeof(delta_head); @@ -982,16 +995,18 @@ static int packed_delta_info(struct packed_git *p, return 0; } -static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset, - enum object_type *type, unsigned long *sizep) +static unsigned long unpack_object_header(struct packed_git *p, + struct pack_window **w_curs, + unsigned long offset, + enum object_type *type, + unsigned long *sizep) { + unsigned char *base; + unsigned int left; unsigned long used; - if (p->pack_size <= offset) - die("object offset outside of pack file"); - - used = unpack_object_header_gently(p->windows->base + offset, - p->pack_size - offset, type, sizep); + base = use_pack(p, w_curs, offset, &left); + used = unpack_object_header_gently(base, left, type, sizep); if (!used) die("object offset outside of pack file"); @@ -1006,13 +1021,14 @@ void packed_object_info_detail(struct packed_git *p, unsigned int *delta_chain_length, unsigned char *base_sha1) { + struct pack_window *w_curs = NULL; unsigned long obj_offset, val; unsigned char *next_sha1; enum object_type kind; *delta_chain_length = 0; obj_offset = offset; - offset = unpack_object_header(p, offset, &kind, size); + offset = unpack_object_header(p, &w_curs, offset, &kind, size); for (;;) { switch (kind) { @@ -1025,25 +1041,24 @@ void packed_object_info_detail(struct packed_git *p, case OBJ_TAG: strcpy(type, type_names[kind]); *store_size = 0; /* notyet */ + unuse_pack(&w_curs); return; case OBJ_OFS_DELTA: - get_delta_base(p, offset, kind, obj_offset, &offset); + get_delta_base(p, &w_curs, offset, kind, + obj_offset, &offset); if (*delta_chain_length == 0) { /* TODO: find base_sha1 as pointed by offset */ } break; case OBJ_REF_DELTA: - if (p->pack_size <= offset + 20) - die("pack file %s records an incomplete delta base", - p->pack_name); - next_sha1 = p->windows->base + offset; + next_sha1 = use_pack(p, &w_curs, offset, NULL); if (*delta_chain_length == 0) hashcpy(base_sha1, next_sha1); offset = find_pack_entry_one(next_sha1, p); break; } obj_offset = offset; - offset = unpack_object_header(p, offset, &kind, &val); + offset = unpack_object_header(p, &w_curs, offset, &kind, &val); (*delta_chain_length)++; } } @@ -1051,20 +1066,26 @@ void packed_object_info_detail(struct packed_git *p, static int packed_object_info(struct packed_git *p, unsigned long offset, char *type, unsigned long *sizep) { + struct pack_window *w_curs = NULL; unsigned long size, obj_offset = offset; enum object_type kind; + int r; - offset = unpack_object_header(p, offset, &kind, &size); + offset = unpack_object_header(p, &w_curs, offset, &kind, &size); switch (kind) { case OBJ_OFS_DELTA: case OBJ_REF_DELTA: - return packed_delta_info(p, offset, kind, obj_offset, type, sizep); + r = packed_delta_info(p, &w_curs, offset, kind, + obj_offset, type, sizep); + unuse_pack(&w_curs); + return r; case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: case OBJ_TAG: strcpy(type, type_names[kind]); + unuse_pack(&w_curs); break; default: die("pack %s contains unknown object type %d", @@ -1076,6 +1097,7 @@ static int packed_object_info(struct packed_git *p, unsigned long offset, } static void *unpack_compressed_entry(struct packed_git *p, + struct pack_window **w_curs, unsigned long offset, unsigned long size) { @@ -1086,8 +1108,7 @@ static void *unpack_compressed_entry(struct packed_git *p, buffer = xmalloc(size + 1); buffer[size] = 0; memset(&stream, 0, sizeof(stream)); - stream.next_in = p->windows->base + offset; - stream.avail_in = p->pack_size - offset; + stream.next_in = use_pack(p, w_curs, offset, &stream.avail_in); stream.next_out = buffer; stream.avail_out = size; @@ -1103,6 +1124,7 @@ static void *unpack_compressed_entry(struct packed_git *p, } static void *unpack_delta_entry(struct packed_git *p, + struct pack_window **w_curs, unsigned long offset, unsigned long delta_size, enum object_type kind, @@ -1113,13 +1135,14 @@ static void *unpack_delta_entry(struct packed_git *p, void *delta_data, *result, *base; unsigned long result_size, base_size, base_offset; - offset = get_delta_base(p, offset, kind, obj_offset, &base_offset); + offset = get_delta_base(p, w_curs, offset, kind, + obj_offset, &base_offset); base = unpack_entry(p, base_offset, type, &base_size); if (!base) die("failed to read delta base object at %lu from %s", base_offset, p->pack_name); - delta_data = unpack_compressed_entry(p, offset, delta_size); + delta_data = unpack_compressed_entry(p, w_curs, offset, delta_size); result = patch_delta(base, base_size, delta_data, delta_size, &result_size); @@ -1134,17 +1157,17 @@ static void *unpack_delta_entry(struct packed_git *p, void *unpack_entry(struct packed_git *p, unsigned long offset, char *type, unsigned long *sizep) { + struct pack_window *w_curs = NULL; unsigned long size, obj_offset = offset; enum object_type kind; void *retval; - if (use_packed_git(p)) - die("cannot map packed file"); - offset = unpack_object_header(p, offset, &kind, &size); + offset = unpack_object_header(p, &w_curs, offset, &kind, &size); switch (kind) { case OBJ_OFS_DELTA: case OBJ_REF_DELTA: - retval = unpack_delta_entry(p, offset, size, kind, obj_offset, type, sizep); + retval = unpack_delta_entry(p, &w_curs, offset, size, + kind, obj_offset, type, sizep); break; case OBJ_COMMIT: case OBJ_TREE: @@ -1152,12 +1175,12 @@ void *unpack_entry(struct packed_git *p, unsigned long offset, case OBJ_TAG: strcpy(type, type_names[kind]); *sizep = size; - retval = unpack_compressed_entry(p, offset, size); + retval = unpack_compressed_entry(p, &w_curs, offset, size); break; default: die("unknown object type %i in %s", kind, p->pack_name); } - unuse_packed_git(p); + unuse_pack(&w_curs); return retval; } @@ -1284,7 +1307,6 @@ static int sha1_loose_object_info(const unsigned char *sha1, char *type, unsigne int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep) { - int status; struct pack_entry e; if (!find_pack_entry(sha1, &e, NULL)) { @@ -1292,11 +1314,7 @@ int sha1_object_info(const unsigned char *sha1, char *type, unsigned long *sizep if (!find_pack_entry(sha1, &e, NULL)) return sha1_loose_object_info(sha1, type, sizep); } - if (use_packed_git(e.p)) - die("cannot map packed file"); - status = packed_object_info(e.p, e.offset, type, sizep); - unuse_packed_git(e.p); - return status; + return packed_object_info(e.p, e.offset, type, sizep); } static void *read_packed_sha1(const unsigned char *sha1, char *type, unsigned long *size) |