aboutsummaryrefslogtreecommitdiff
path: root/pack-objects.c
diff options
context:
space:
mode:
Diffstat (limited to 'pack-objects.c')
-rw-r--r--pack-objects.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/pack-objects.c b/pack-objects.c
index 2320bcf31..095bcb828 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -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;
}