pack-objects: hash basename and direname a bit differently.
[git.git] / pack-objects.c
index 3a16b7e..095bcb8 100644 (file)
@@ -445,18 +445,29 @@ struct name_path {
        int len;
 };
 
+#define DIRBITS 12
+
 static unsigned name_hash(struct name_path *path, const char *name)
 {
        struct name_path *p = path;
        const char *n = name + strlen(name);
-       unsigned hash = 0;
+       unsigned hash = 0, name_hash = 0, name_done = 0;
 
        if (n != name && n[-1] == '\n')
                n--;
        while (name <= --n) {
                unsigned char c = *n;
+               if (c == '/' && !name_done) {
+                       name_hash = hash;
+                       name_done = 1;
+                       hash = 0;
+               }
                hash = hash * 11 + c;
        }
+       if (!name_done) {
+               name_hash = hash;
+               hash = 0;
+       }
        for (p = path; p; p = p->up) {
                hash = hash * 11 + '/';
                n = p->elem + p->len;
@@ -465,6 +476,26 @@ static unsigned name_hash(struct name_path *path, const char *name)
                        hash = hash * 11 + c;
                }
        }
+       /*
+        * Make sure "Makefile" and "t/Makefile" are hashed separately
+        * but close enough.
+        */
+       hash = (name_hash<<DIRBITS) | (hash & ((1U<<DIRBITS )-1));
+
+       if (0) { /* debug */
+               n = name + strlen(name);
+               if (n != name && n[-1] == '\n')
+                       n--;
+               while (name <= --n)
+                       fputc(*n, stderr);
+               for (p = path; p; p = p->up) {
+                       fputc('/', stderr);
+                       n = p->elem + p->len;
+                       while (p->elem <= --n)
+                               fputc(*n, stderr);
+               }
+               fprintf(stderr, "\t%08x\n", hash);
+       }
        return hash;
 }
 
@@ -663,10 +694,23 @@ static void get_object_details(void)
        prepare_pack_ix();
        for (i = 0, entry = objects; i < nr_objects; i++, entry++)
                check_object(entry);
-       for (i = 0, entry = objects; i < nr_objects; i++, entry++)
-               if (!entry->delta && entry->delta_child)
-                       entry->delta_limit =
-                               check_delta_limit(entry, 1);
+
+       if (nr_objects == nr_result) {
+               /*
+                * Depth of objects that depend on the entry -- this
+                * is subtracted from depth-max to break too deep
+                * delta chain because of delta data reusing.
+                * However, we loosen this restriction when we know we
+                * are creating a thin pack -- it will have to be
+                * expanded on the other end anyway, so do not
+                * artificially cut the delta chain and let it go as
+                * deep as it wants.
+                */
+               for (i = 0, entry = objects; i < nr_objects; i++, entry++)
+                       if (!entry->delta && entry->delta_child)
+                               entry->delta_limit =
+                                       check_delta_limit(entry, 1);
+       }
 }
 
 typedef int (*entry_sort_t)(const struct object_entry *, const struct object_entry *);