From: Linus Torvalds Date: Tue, 28 Jun 2005 22:20:10 +0000 (-0700) Subject: Merge fighting fsck-cache updates from Junio X-Git-Tag: v0.99~137 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/fead2836a16829fba427635f92d7df9acf771a55?ds=inline;hp=-c Merge fighting fsck-cache updates from Junio It's just easier to let git help out with the merge than it is to try to fix up the diffs. --- fead2836a16829fba427635f92d7df9acf771a55 diff --combined sha1_file.c index 5c6e964a35,17546061c1..25208d2da3 --- a/sha1_file.c +++ b/sha1_file.c @@@ -10,7 -10,6 +10,7 @@@ #include #include "cache.h" #include "delta.h" +#include "pack.h" #ifndef O_NOATIME #if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) @@@ -185,10 -184,7 +185,7 @@@ char *sha1_file_name(const unsigned cha return base; } - static struct alternate_object_database { - char *base; - char *name; - } *alt_odb; + struct alternate_object_database *alt_odb; /* * Prepare alternate object database registry. @@@ -206,13 -202,15 +203,15 @@@ * pointed by base fields of the array elements with one xmalloc(); * the string pool immediately follows the array. */ - static void prepare_alt_odb(void) + void prepare_alt_odb(void) { int pass, totlen, i; const char *cp, *last; char *op = NULL; const char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : ""; + if (alt_odb) + return; /* The first pass counts how large an area to allocate to * hold the entire alt_odb structure, including array of * structs and path buffers for them. The second pass fills @@@ -259,8 -257,7 +258,7 @@@ static char *find_sha1_file(const unsig if (!stat(name, st)) return name; - if (!alt_odb) - prepare_alt_odb(); + prepare_alt_odb(); for (i = 0; (name = alt_odb[i].name) != NULL; i++) { fill_sha1_path(name, sha1); if (!stat(alt_odb[i].base, st)) @@@ -272,15 -269,7 +270,7 @@@ #define PACK_MAX_SZ (1<<26) static int pack_used_ctr; static unsigned long pack_mapped; - static struct packed_git { - struct packed_git *next; - unsigned long index_size; - unsigned long pack_size; - unsigned int *index_base; - void *pack_base; - unsigned int pack_last_used; - char pack_name[0]; /* something like ".git/objects/pack/xxxxx.pack" */ - } *packed_git; + struct packed_git *packed_git; struct pack_entry { unsigned int offset; @@@ -396,7 -385,6 +386,7 @@@ static struct packed_git *add_packed_gi p->pack_size = st.st_size; p->index_base = idx_map; p->next = NULL; + p->pack_base = NULL; p->pack_last_used = 0; return p; } @@@ -431,7 -419,7 +421,7 @@@ static void prepare_packed_git_one(cha } } - static void prepare_packed_git(void) + void prepare_packed_git(void) { int i; static int run_once = 0; @@@ -440,8 -428,7 +430,7 @@@ return; prepare_packed_git_one(get_object_directory()); - if (!alt_odb) - prepare_alt_odb(); + prepare_alt_odb(); for (i = 0; alt_odb[i].base != NULL; i++) { alt_odb[i].name[0] = 0; prepare_packed_git_one(alt_odb[i].base); @@@ -667,60 -654,37 +656,60 @@@ static int packed_delta_info(unsigned c return 0; } +static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset, + enum object_type *type, unsigned long *sizep) +{ + unsigned char *pack, c; + unsigned long size; + + if (offset >= p->pack_size) + die("object offset outside of pack file"); + + pack = p->pack_base + offset; + c = *pack++; + offset++; + *type = (c >> 4) & 7; + size = c & 15; + while (c & 0x80) { + if (offset >= p->pack_size) + die("object offset outside of pack file"); + c = *pack++; + offset++; + size = (size << 7) | (c & 0x7f); + } + *sizep = size; + return offset; +} + static int packed_object_info(struct pack_entry *entry, char *type, unsigned long *sizep) { struct packed_git *p = entry->p; unsigned long offset, size, left; unsigned char *pack; - - offset = entry->offset; - if (p->pack_size - 5 < offset) - die("object offset outside of pack file"); + enum object_type kind; if (use_packed_git(p)) die("cannot map packed file"); + offset = unpack_object_header(p, entry->offset, &kind, &size); pack = p->pack_base + offset; - size = (pack[1] << 24) + (pack[2] << 16) + (pack[3] << 8) + pack[4]; - left = p->pack_size - offset - 5; - switch (*pack) { - case 'D': - return packed_delta_info(pack+5, size, left, type, sizep); + left = p->pack_size - offset; + + switch (kind) { + case OBJ_DELTA: + return packed_delta_info(pack, size, left, type, sizep); break; - case 'C': + case OBJ_COMMIT: strcpy(type, "commit"); break; - case 'T': + case OBJ_TREE: strcpy(type, "tree"); break; - case 'B': + case OBJ_BLOB: strcpy(type, "blob"); break; - case 'G': + case OBJ_TAG: strcpy(type, "tag"); break; default: @@@ -812,36 -776,55 +801,52 @@@ static void *unpack_entry(struct pack_e struct packed_git *p = entry->p; unsigned long offset, size, left; unsigned char *pack; - - offset = entry->offset; - if (p->pack_size - 5 < offset) - die("object offset outside of pack file"); + enum object_type kind; if (use_packed_git(p)) die("cannot map packed file"); + offset = unpack_object_header(p, entry->offset, &kind, &size); pack = p->pack_base + offset; - size = (pack[1] << 24) + (pack[2] << 16) + (pack[3] << 8) + pack[4]; - left = p->pack_size - offset - 5; - switch (*pack) { - case 'D': - return unpack_delta_entry(pack+5, size, left, type, sizep); - case 'C': + left = p->pack_size - offset; + switch (kind) { + case OBJ_DELTA: + return unpack_delta_entry(pack, size, left, type, sizep); + case OBJ_COMMIT: strcpy(type, "commit"); break; - case 'T': + case OBJ_TREE: strcpy(type, "tree"); break; - case 'B': + case OBJ_BLOB: strcpy(type, "blob"); break; - case 'G': + case OBJ_TAG: strcpy(type, "tag"); break; default: die("corrupted pack file"); } *sizep = size; - return unpack_non_delta_entry(pack+5, size, left); + return unpack_non_delta_entry(pack, size, left); } + int num_packed_objects(const struct packed_git *p) + { + /* See check_packed_git_idx and pack-objects.c */ + return (p->index_size - 20 - 20 - 4*256) / 24; + } + + int nth_packed_object_sha1(const struct packed_git *p, int n, + unsigned char* sha1) + { + void *index = p->index_base + 256; + if (n < 0 || num_packed_objects(p) <= n) + return -1; + memcpy(sha1, (index + 24 * n + 4), 20); + return 0; + } + static int find_pack_entry_1(const unsigned char *sha1, struct pack_entry *e, struct packed_git *p) {