X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=pack-objects.c;h=861c7f08ff1b68eee141442411b4706a1bcc2518;hb=0881d2d1303a067a02e3811d43a1aed04a47945e;hp=ba6525d1f4786dad167994bf7a635c13b2b08ef6;hpb=1d7f171c3a456b980d821ee0f68e01535a5f7e36;p=git.git diff --git a/pack-objects.c b/pack-objects.c index ba6525d1f..861c7f08f 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -28,7 +28,7 @@ struct object_entry { struct object_entry *delta; /* delta base object */ struct packed_git *in_pack; /* already in pack */ unsigned int in_pack_offset; - struct object_entry *delta_child; /* delitified objects who bases me */ + struct object_entry *delta_child; /* deltified objects who bases me */ struct object_entry *delta_sibling; /* other deltified objects who * uses the same base as me */ @@ -39,7 +39,7 @@ struct object_entry { }; /* - * Objects we are going to pack are colected in objects array (dynamically + * Objects we are going to pack are collected in objects array (dynamically * expanded). nr_objects & nr_alloc controls this array. They are stored * in the order we see -- typically rev-list --objects order that gives us * nice "minimum seek" order. @@ -63,6 +63,7 @@ static const char *base_name; static unsigned char pack_file_sha1[20]; static int progress = 1; static volatile sig_atomic_t progress_update = 0; +static int window = 10; /* * The object names in objects array are hashed with this hashtable, @@ -970,11 +971,12 @@ struct unpacked { * one. */ static int try_delta(struct unpacked *trg, struct unpacked *src, - struct delta_index *src_index, unsigned max_depth) + unsigned max_depth) { struct object_entry *trg_entry = trg->entry; struct object_entry *src_entry = src->entry; - unsigned long size, src_size, delta_size, sizediff, max_size; + unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz; + char type[10]; void *delta_buf; /* Don't bother doing diffs between different types */ @@ -987,6 +989,14 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, if (trg_entry->preferred_base) return -1; + /* + * We do not bother to try a delta that we discarded + * on an earlier try, but only when reusing delta data. + */ + if (!no_reuse_delta && trg_entry->in_pack && + trg_entry->in_pack == src_entry->in_pack) + return 0; + /* * If the current object is at pack edge, take the depth the * objects that depend on the current object into account -- @@ -1001,19 +1011,38 @@ static int try_delta(struct unpacked *trg, struct unpacked *src, return 0; /* Now some size filtering heuristics. */ - size = trg_entry->size; - max_size = size/2 - 20; + trg_size = trg_entry->size; + max_size = trg_size/2 - 20; max_size = max_size * (max_depth - src_entry->depth) / max_depth; if (max_size == 0) return 0; if (trg_entry->delta && trg_entry->delta_size <= max_size) max_size = trg_entry->delta_size-1; src_size = src_entry->size; - sizediff = src_size < size ? size - src_size : 0; + sizediff = src_size < trg_size ? trg_size - src_size : 0; if (sizediff >= max_size) return 0; - delta_buf = create_delta(src_index, trg->data, size, &delta_size, max_size); + /* Load data if not already done */ + if (!trg->data) { + 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); + if (sz != src_size) + die("object %s inconsistent object length (%lu vs %lu)", + sha1_to_hex(src_entry->sha1), sz, src_size); + } + if (!src->index) { + src->index = create_delta_index(src->data, src_size); + if (!src->index) + die("out of memory"); + } + + delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size); if (!delta_buf) return 0; @@ -1046,8 +1075,6 @@ static void find_deltas(struct object_entry **list, int window, int depth) while (--i >= 0) { struct object_entry *entry = list[i]; struct unpacked *n = array + idx; - unsigned long size; - char type[10]; int j; if (!entry->preferred_base) @@ -1074,11 +1101,8 @@ static void find_deltas(struct object_entry **list, int window, int depth) free_delta_index(n->index); n->index = NULL; free(n->data); + n->data = NULL; n->entry = entry; - n->data = read_sha1_file(entry->sha1, type, &size); - if (size != entry->size) - die("object %s inconsistent object length (%lu vs %lu)", - sha1_to_hex(entry->sha1), size, entry->size); j = window; while (--j > 0) { @@ -1089,7 +1113,7 @@ static void find_deltas(struct object_entry **list, int window, int depth) m = array + other_idx; if (!m->entry) break; - if (try_delta(n, m, m->index, depth) < 0) + if (try_delta(n, m, depth) < 0) break; } /* if we made n a delta, and if n is already at max @@ -1099,10 +1123,6 @@ static void find_deltas(struct object_entry **list, int window, int depth) if (entry->delta && depth <= entry->depth) continue; - n->index = create_delta_index(n->data, size); - if (!n->index) - die("out of memory"); - idx++; if (idx >= window) idx = 0; @@ -1197,16 +1217,26 @@ static void setup_progress_signal(void) setitimer(ITIMER_REAL, &v, NULL); } +static int git_pack_config(const char *k, const char *v) +{ + if(!strcmp(k, "pack.window")) { + window = git_config_int(k, v); + return 0; + } + return git_default_config(k, v); +} + int main(int argc, char **argv) { SHA_CTX ctx; char line[40 + 1 + PATH_MAX + 2]; - int window = 10, depth = 10, pack_to_stdout = 0; + int depth = 10, pack_to_stdout = 0; struct object_entry **list; int num_preferred_base = 0; int i; setup_git_directory(); + git_config(git_pack_config); progress = isatty(2); for (i = 1; i < argc; i++) { @@ -1221,6 +1251,10 @@ int main(int argc, char **argv) local = 1; continue; } + if (!strcmp("--progress", arg)) { + progress = 1; + continue; + } if (!strcmp("--incremental", arg)) { incremental = 1; continue;