Build on Debian GNU/kFreeBSD
[gitweb.git] / pack-objects.c
index 6e1767652c886d48781f7fbeb9599d57b1de09c7..861c7f08ff1b68eee141442411b4706a1bcc2518 100644 (file)
@@ -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 */
@@ -989,9 +991,10 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
 
        /*
         * We do not bother to try a delta that we discarded
-        * on an earlier try.
+        * on an earlier try, but only when reusing delta data.
         */
-       if (trg_entry->in_pack && trg_entry->in_pack == src_entry->in_pack)
+       if (!no_reuse_delta && trg_entry->in_pack &&
+           trg_entry->in_pack == src_entry->in_pack)
                return 0;
 
        /*
@@ -1008,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;
 
@@ -1053,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)
@@ -1081,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) {
@@ -1096,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
@@ -1106,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;
@@ -1204,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++) {