X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-pack-objects.c;h=8cf24f407915e6988b86a0ee40a4884dab9f5358;hb=8b969a5fb5e5891d9ad4c236fd9487c4673bfa2a;hp=807be8c3f8a051d9171cf2ee3c9f973f77a2ff08;hpb=85023577a8f4b540aa64aa37f6f44578c0c305a3;p=git.git diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 807be8c3f..8cf24f407 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -17,7 +17,7 @@ static const char pack_usage[] = "\ git-pack-objects [{ -q | --progress | --all-progress }] \n\ [--local] [--incremental] [--window=N] [--depth=N] \n\ [--no-reuse-delta] [--delta-base-offset] [--non-empty] \n\ - [--revs [--unpacked | --all]*] [--stdout | base-name] \n\ + [--revs [--unpacked | --all]*] [--reflog] [--stdout | base-name] \n\ [delta->sha1, type, &othersize); + enum object_type type; + void *otherbuf = read_sha1_file(entry->delta->sha1, &type, &othersize); void *delta_buf; if (!otherbuf) @@ -276,7 +276,52 @@ static int encode_header(enum object_type type, unsigned long size, unsigned cha * we are going to reuse the existing object data as is. make * sure it is not corrupt. */ -static int check_inflate(unsigned char *data, unsigned long len, unsigned long expect) +static int check_pack_inflate(struct packed_git *p, + struct pack_window **w_curs, + unsigned long offset, + unsigned long len, + unsigned long expect) +{ + z_stream stream; + unsigned char fakebuf[4096], *in; + int st; + + memset(&stream, 0, sizeof(stream)); + inflateInit(&stream); + do { + in = use_pack(p, w_curs, offset, &stream.avail_in); + stream.next_in = in; + stream.next_out = fakebuf; + stream.avail_out = sizeof(fakebuf); + st = inflate(&stream, Z_FINISH); + offset += stream.next_in - in; + } while (st == Z_OK || st == Z_BUF_ERROR); + inflateEnd(&stream); + return (st == Z_STREAM_END && + stream.total_out == expect && + stream.total_in == len) ? 0 : -1; +} + +static void copy_pack_data(struct sha1file *f, + struct packed_git *p, + struct pack_window **w_curs, + unsigned long offset, + unsigned long len) +{ + unsigned char *in; + unsigned int avail; + + while (len) { + in = use_pack(p, w_curs, offset, &avail); + if (avail > len) + avail = len; + sha1write(f, in, avail); + offset += avail; + len -= avail; + } +} + +static int check_loose_inflate(unsigned char *data, unsigned long len, unsigned long expect) { z_stream stream; unsigned char fakebuf[4096]; @@ -323,14 +368,14 @@ static int revalidate_loose_object(struct object_entry *entry, return -1; map += used; mapsize -= used; - return check_inflate(map, mapsize, size); + return check_loose_inflate(map, mapsize, size); } static unsigned long write_object(struct sha1file *f, struct object_entry *entry) { unsigned long size; - char type[10]; + enum object_type type; void *buf; unsigned char header[10]; unsigned hdrlen, datalen; @@ -371,7 +416,7 @@ static unsigned long write_object(struct sha1file *f, } if (!to_reuse) { - buf = read_sha1_file(entry->sha1, type, &size); + buf = read_sha1_file(entry->sha1, &type, &size); if (!buf) die("unable to read %s", sha1_to_hex(entry->sha1)); if (size != entry->size) @@ -416,6 +461,8 @@ static unsigned long write_object(struct sha1file *f, } else { struct packed_git *p = entry->in_pack; + struct pack_window *w_curs = NULL; + unsigned long offset; if (entry->delta) { obj_type = (allow_ofs_delta && entry->delta->offset) ? @@ -437,16 +484,14 @@ static unsigned long write_object(struct sha1file *f, hdrlen += 20; } - use_packed_git(p); - buf = (char *) p->pack_base - + entry->in_pack_offset - + entry->in_pack_header_size; + offset = entry->in_pack_offset + entry->in_pack_header_size; 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)) + if (!pack_to_stdout && check_pack_inflate(p, &w_curs, + offset, datalen, entry->size)) die("corrupt delta in pack %s", sha1_to_hex(entry->sha1)); - sha1write(f, buf, datalen); - unuse_packed_git(p); + copy_pack_data(f, p, &w_curs, offset, datalen); + unuse_pack(&w_curs); reused++; } if (entry->delta) @@ -524,7 +569,7 @@ static void write_index_file(void) sha1_to_hex(object_list_sha1), "idx"); struct object_entry **list = sorted_by_sha; struct object_entry **last = list + nr_result; - unsigned int array[256]; + uint32_t array[256]; /* * Write the first-level table (the list is sorted, @@ -542,7 +587,7 @@ static void write_index_file(void) array[i] = htonl(next - sorted_by_sha); list = next; } - sha1write(f, array, 256 * sizeof(int)); + sha1write(f, array, 256 * 4); /* * Write the actual SHA1 entries.. @@ -550,7 +595,7 @@ static void write_index_file(void) list = sorted_by_sha; for (i = 0; i < nr_result; i++) { struct object_entry *entry = *list++; - unsigned int offset = htonl(entry->offset); + uint32_t offset = htonl(entry->offset); sha1write(f, &offset, 4); sha1write(f, entry->sha1, 20); } @@ -720,7 +765,7 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1) struct pbase_tree_cache *ent, *nent; void *data; unsigned long size; - char type[20]; + enum object_type type; int neigh; int my_ix = pbase_tree_cache_ix(sha1); int available_ix = -1; @@ -747,10 +792,10 @@ static struct pbase_tree_cache *pbase_tree_get(const unsigned char *sha1) /* Did not find one. Either we got a bogus request or * we need to read and perhaps cache. */ - data = read_sha1_file(sha1, type, &size); + data = read_sha1_file(sha1, &type, &size); if (!data) return NULL; - if (strcmp(type, tree_type)) { + if (type != OBJ_TREE) { free(data); return NULL; } @@ -809,19 +854,19 @@ static void add_pbase_object(struct tree_desc *tree, while (tree_entry(tree,&entry)) { unsigned long size; - char type[20]; + enum object_type type; if (entry.pathlen != cmplen || memcmp(entry.path, name, cmplen) || !has_sha1_file(entry.sha1) || - sha1_object_info(entry.sha1, type, &size)) + (type = sha1_object_info(entry.sha1, &size)) < 0) continue; if (name[cmplen] != '/') { unsigned hash = name_hash(fullname); add_object_entry(entry.sha1, hash, 1); return; } - if (!strcmp(type, tree_type)) { + if (type == OBJ_TREE) { struct tree_desc sub; struct pbase_tree_cache *tree; const char *down = name+cmplen+1; @@ -933,26 +978,21 @@ static void add_preferred_base(unsigned char *sha1) static void check_object(struct object_entry *entry) { - char type[20]; - 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->pack_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. */ used = unpack_object_header_gently(buf, left, &entry->in_pack_type, &size); - if (!used || left - used <= 20) - die("corrupt pack for %s", sha1_to_hex(entry->sha1)); /* Check if it is delta, and the base is also an object * we are going to pack. If so we will reuse the existing @@ -961,21 +1001,26 @@ static void check_object(struct object_entry *entry) if (!no_reuse_delta) { unsigned char c, *base_name; unsigned long ofs; + unsigned long used_0; /* there is at least 20 bytes left in the pack */ switch (entry->in_pack_type) { case OBJ_REF_DELTA: - base_name = buf + used; + base_name = use_pack(p, &w_curs, + entry->in_pack_offset + used, NULL); used += 20; break; case OBJ_OFS_DELTA: - c = buf[used++]; + buf = use_pack(p, &w_curs, + entry->in_pack_offset + used, NULL); + used_0 = 0; + c = buf[used_0++]; ofs = c & 127; while (c & 128) { ofs += 1; if (!ofs || ofs & ~(~0UL >> 7)) die("delta base offset overflow in pack for %s", sha1_to_hex(entry->sha1)); - c = buf[used++]; + c = buf[used_0++]; ofs = (ofs << 7) + (c & 127); } if (ofs >= entry->in_pack_offset) @@ -983,6 +1028,7 @@ static void check_object(struct object_entry *entry) sha1_to_hex(entry->sha1)); ofs = entry->in_pack_offset - ofs; base_name = find_packed_object_name(p, ofs); + used += used_0; break; default: base_name = NULL; @@ -990,7 +1036,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) { @@ -1014,21 +1060,10 @@ static void check_object(struct object_entry *entry) /* Otherwise we would do the usual */ } - if (sha1_object_info(entry->sha1, type, &entry->size)) + entry->type = sha1_object_info(entry->sha1, &entry->size); + if (entry->type < 0) die("unable to get type of object %s", sha1_to_hex(entry->sha1)); - - if (!strcmp(type, commit_type)) { - entry->type = OBJ_COMMIT; - } else if (!strcmp(type, tree_type)) { - entry->type = OBJ_TREE; - } else if (!strcmp(type, blob_type)) { - entry->type = OBJ_BLOB; - } else if (!strcmp(type, tag_type)) { - entry->type = OBJ_TAG; - } else - die("unable to pack object %s of type %s", - sha1_to_hex(entry->sha1), type); } static unsigned int check_delta_limit(struct object_entry *me, unsigned int n) @@ -1158,7 +1193,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, struct object_entry *trg_entry = trg->entry; struct object_entry *src_entry = src->entry; unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz; - char type[10]; + enum object_type type; void *delta_buf; /* Don't bother doing diffs between different types */ @@ -1209,13 +1244,13 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, /* Load data if not already done */ if (!trg->data) { - trg->data = read_sha1_file(trg_entry->sha1, type, &sz); + trg->data = read_sha1_file(trg_entry->sha1, &type, &sz); if (sz != trg_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(trg_entry->sha1), sz, trg_size); } if (!src->data) { - src->data = read_sha1_file(src_entry->sha1, type, &sz); + src->data = read_sha1_file(src_entry->sha1, &type, &sz); if (sz != src_size) die("object %s inconsistent object length (%lu vs %lu)", sha1_to_hex(src_entry->sha1), sz, src_size); @@ -1503,9 +1538,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) int use_internal_rev_list = 0; int thin = 0; int i; - const char *rp_av[64]; + const char **rp_av; + int rp_ac_alloc = 64; int rp_ac; + rp_av = xcalloc(rp_ac_alloc, sizeof(*rp_av)); + rp_av[0] = "pack-objects"; rp_av[1] = "--objects"; /* --thin will make it --objects-edge */ rp_ac = 2; @@ -1531,14 +1569,14 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) incremental = 1; continue; } - if (!strncmp("--window=", arg, 9)) { + if (!prefixcmp(arg, "--window=")) { char *end; window = strtoul(arg+9, &end, 0); if (!arg[9] || *end) usage(pack_usage); continue; } - if (!strncmp("--depth=", arg, 8)) { + if (!prefixcmp(arg, "--depth=")) { char *end; depth = strtoul(arg+8, &end, 0); if (!arg[8] || *end) @@ -1574,11 +1612,15 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) continue; } if (!strcmp("--unpacked", arg) || - !strncmp("--unpacked=", arg, 11) || + !prefixcmp(arg, "--unpacked=") || + !strcmp("--reflog", arg) || !strcmp("--all", arg)) { use_internal_rev_list = 1; - if (ARRAY_SIZE(rp_av) - 1 <= rp_ac) - die("too many internal rev-list options"); + if (rp_ac >= rp_ac_alloc - 1) { + rp_ac_alloc = alloc_nr(rp_ac_alloc); + rp_av = xrealloc(rp_av, + rp_ac_alloc * sizeof(*rp_av)); + } rp_av[rp_ac++] = arg; continue; }