From: Junio C Hamano Date: Thu, 9 Nov 2006 17:40:59 +0000 (-0800) Subject: Merge branch 'maint' X-Git-Tag: v1.4.4-rc2~7 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/6a96b32d3b045c6e8d1b553fd6b64e03db9b0e45?ds=inline;hp=-c Merge branch 'maint' * maint: Nicer error messages in case saving an object to db goes wrong --- 6a96b32d3b045c6e8d1b553fd6b64e03db9b0e45 diff --combined sha1_file.c index 6ea59b5588,c9fdaa3d7e..09456d23f8 --- a/sha1_file.c +++ b/sha1_file.c @@@ -663,7 -663,7 +663,7 @@@ void prepare_packed_git(void prepare_packed_git_run_once = 1; } -static void reprepare_packed_git(void) +void reprepare_packed_git(void) { prepare_packed_git_run_once = 0; prepare_packed_git(); @@@ -877,61 -877,26 +877,61 @@@ void * unpack_sha1_file(void *map, unsi return unpack_sha1_rest(&stream, hdr, *size); } +static unsigned long get_delta_base(struct packed_git *p, + unsigned long offset, + enum object_type kind, + unsigned long delta_obj_offset, + unsigned long *base_obj_offset) +{ + unsigned char *base_info = (unsigned char *) p->pack_base + offset; + unsigned long base_offset; + + /* there must be at least 20 bytes left regardless of delta type */ + if (p->pack_size <= offset + 20) + die("truncated pack file"); + + if (kind == OBJ_OFS_DELTA) { + unsigned used = 0; + unsigned char c = base_info[used++]; + base_offset = c & 127; + while (c & 128) { + base_offset += 1; + if (!base_offset || base_offset & ~(~0UL >> 7)) + die("offset value overflow for delta base object"); + c = base_info[used++]; + base_offset = (base_offset << 7) + (c & 127); + } + base_offset = delta_obj_offset - base_offset; + if (base_offset >= delta_obj_offset) + die("delta base offset out of bound"); + offset += used; + } else if (kind == OBJ_REF_DELTA) { + /* The base entry _must_ be in the same pack */ + base_offset = find_pack_entry_one(base_info, p); + if (!base_offset) + die("failed to find delta-pack base object %s", + sha1_to_hex(base_info)); + offset += 20; + } else + die("I am totally screwed"); + *base_obj_offset = base_offset; + return offset; +} + /* forward declaration for a mutually recursive function */ 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, unsigned long offset, + enum object_type kind, + unsigned long obj_offset, char *type, unsigned long *sizep) { unsigned long base_offset; - unsigned char *base_sha1 = (unsigned char *) p->pack_base + offset; - if (p->pack_size < offset + 20) - die("truncated pack file"); - /* The base entry _must_ be in the same pack */ - base_offset = find_pack_entry_one(base_sha1, p); - if (!base_offset) - die("failed to find delta-pack base object %s", - sha1_to_hex(base_sha1)); - offset += 20; + offset = get_delta_base(p, 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 @@@ -994,6 -959,25 +994,6 @@@ static unsigned long unpack_object_head return offset + used; } -int check_reuse_pack_delta(struct packed_git *p, unsigned long offset, - unsigned char *base, unsigned long *sizep, - enum object_type *kindp) -{ - unsigned long ptr; - int status = -1; - - use_packed_git(p); - ptr = offset; - ptr = unpack_object_header(p, ptr, kindp, sizep); - if (*kindp != OBJ_DELTA) - goto done; - hashcpy(base, (unsigned char *) p->pack_base + ptr); - status = 0; - done: - unuse_packed_git(p); - return status; -} - void packed_object_info_detail(struct packed_git *p, unsigned long offset, char *type, @@@ -1002,12 -986,11 +1002,12 @@@ unsigned int *delta_chain_length, unsigned char *base_sha1) { - unsigned long val; + 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); for (;;) { @@@ -1022,13 -1005,7 +1022,13 @@@ strcpy(type, type_names[kind]); *store_size = 0; /* notyet */ return; - case OBJ_DELTA: + case OBJ_OFS_DELTA: + get_delta_base(p, 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); @@@ -1038,7 -1015,6 +1038,7 @@@ offset = find_pack_entry_one(next_sha1, p); break; } + obj_offset = offset; offset = unpack_object_header(p, offset, &kind, &val); (*delta_chain_length)++; } @@@ -1047,15 -1023,15 +1047,15 @@@ static int packed_object_info(struct packed_git *p, unsigned long offset, char *type, unsigned long *sizep) { - unsigned long size; + unsigned long size, obj_offset = offset; enum object_type kind; offset = unpack_object_header(p, offset, &kind, &size); - if (kind == OBJ_DELTA) - return packed_delta_info(p, offset, type, sizep); - switch (kind) { + case OBJ_OFS_DELTA: + case OBJ_REF_DELTA: + return packed_delta_info(p, offset, kind, obj_offset, type, sizep); case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: @@@ -1101,15 -1077,23 +1101,15 @@@ static void *unpack_compressed_entry(st static void *unpack_delta_entry(struct packed_git *p, unsigned long offset, unsigned long delta_size, + enum object_type kind, + unsigned long obj_offset, char *type, unsigned long *sizep) { void *delta_data, *result, *base; unsigned long result_size, base_size, base_offset; - unsigned char *base_sha1; - - if (p->pack_size < offset + 20) - die("truncated pack file"); - /* The base entry _must_ be in the same pack */ - base_sha1 = (unsigned char*)p->pack_base + offset; - base_offset = find_pack_entry_one(base_sha1, p); - if (!base_offset) - die("failed to find delta-pack base object %s", - sha1_to_hex(base_sha1)); - offset += 20; + offset = get_delta_base(p, offset, kind, obj_offset, &base_offset); base = unpack_entry_gently(p, base_offset, type, &base_size); if (!base) die("failed to read delta base object at %lu from %s", @@@ -1146,14 -1130,13 +1146,14 @@@ static void *unpack_entry(struct pack_e void *unpack_entry_gently(struct packed_git *p, unsigned long offset, char *type, unsigned long *sizep) { - unsigned long size; + unsigned long size, obj_offset = offset; enum object_type kind; offset = unpack_object_header(p, offset, &kind, &size); switch (kind) { - case OBJ_DELTA: - return unpack_delta_entry(p, offset, size, type, sizep); + case OBJ_OFS_DELTA: + case OBJ_REF_DELTA: + return unpack_delta_entry(p, offset, size, kind, obj_offset, type, sizep); case OBJ_COMMIT: case OBJ_TREE: case OBJ_BLOB: @@@ -1203,24 -1186,6 +1203,24 @@@ unsigned long find_pack_entry_one(cons return 0; } +static int matches_pack_name(struct packed_git *p, const char *ig) +{ + const char *last_c, *c; + + if (!strcmp(p->pack_name, ig)) + return 0; + + for (c = p->pack_name, last_c = c; *c;) + if (*c == '/') + last_c = ++c; + else + ++c; + if (!strcmp(last_c, ig)) + return 0; + + return 1; +} + static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed) { struct packed_git *p; @@@ -1232,7 -1197,7 +1232,7 @@@ if (ignore_packed) { const char **ig; for (ig = ignore_packed; *ig; ig++) - if (!strcmp(p->pack_name, *ig)) + if (!matches_pack_name(p, *ig)) break; if (*ig) continue; @@@ -1455,8 -1420,7 +1455,7 @@@ int move_temp_to_file(const char *tmpfi unlink(tmpfile); if (ret) { if (ret != EEXIST) { - fprintf(stderr, "unable to write sha1 filename %s: %s\n", filename, strerror(ret)); - return -1; + return error("unable to write sha1 filename %s: %s\n", filename, strerror(ret)); } /* FIXME!!! Collision check here ? */ } @@@ -1566,16 -1530,17 +1565,17 @@@ int write_sha1_file(void *buf, unsigne } if (errno != ENOENT) { - fprintf(stderr, "sha1 file %s: %s\n", filename, strerror(errno)); - return -1; + return error("sha1 file %s: %s\n", filename, strerror(errno)); } snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); fd = mkstemp(tmpfile); if (fd < 0) { - fprintf(stderr, "unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno)); - return -1; + if (errno == EPERM) + return error("insufficient permission for adding an object to repository database %s\n", get_object_directory()); + else + return error("unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno)); } /* Set it up */ @@@ -1690,9 -1655,12 +1690,12 @@@ int write_sha1_from_fd(const unsigned c snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); local = mkstemp(tmpfile); - if (local < 0) - return error("Couldn't open %s for %s", - tmpfile, sha1_to_hex(sha1)); + if (local < 0) { + if (errno == EPERM) + return error("insufficient permission for adding an object to repository database %s\n", get_object_directory()); + else + return error("unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno)); + } memset(&stream, 0, sizeof(stream));