This uses the same hashing algorithm to the "preferred base
tree" objects and the incoming pathnames, to group the same
files from different revs together, while spreading files with
the same basename in different directories.
Signed-off-by: Junio C Hamano <junkio@cox.net>
-static int add_object_entry(const unsigned char *sha1, const char *name, int exclude)
+struct name_path {
+ struct name_path *up;
+ const char *elem;
+ int len;
+};
+
+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;
+
+ if (n != name && n[-1] == '\n')
+ n--;
+ while (name <= --n) {
+ unsigned char c = *n;
+ hash = hash * 11 + c;
+ }
+ for (p = path; p; p = p->up) {
+ hash = hash * 11 + '/';
+ n = p->elem + p->len;
+ while (p->elem <= --n) {
+ unsigned char c = *n;
+ hash = hash * 11 + c;
+ }
+ }
+ return hash;
+}
+
+static int add_object_entry(const unsigned char *sha1, unsigned hash, int exclude)
unsigned int idx = nr_objects;
struct object_entry *entry;
struct packed_git *p;
unsigned int idx = nr_objects;
struct object_entry *entry;
struct packed_git *p;
if ((entry = locate_object_entry(sha1)) != NULL)
goto already_added;
if ((entry = locate_object_entry(sha1)) != NULL)
goto already_added;
- while (*name) {
- unsigned char c = *name++;
- if (isspace(c))
- continue;
- hash = hash * 11 + c;
- }
-
if (idx >= nr_alloc) {
unsigned int needed = (idx + 1024) * 3 / 2;
objects = xrealloc(objects, needed * sizeof(*entry));
if (idx >= nr_alloc) {
unsigned int needed = (idx + 1024) * 3 / 2;
objects = xrealloc(objects, needed * sizeof(*entry));
-static void add_pbase_tree(struct tree_desc *tree)
+static void add_pbase_tree(struct tree_desc *tree, struct name_path *up)
{
while (tree->size) {
const unsigned char *sha1;
const char *name;
{
while (tree->size) {
const unsigned char *sha1;
const char *name;
unsigned long size;
char type[20];
unsigned long size;
char type[20];
if (sha1_object_info(sha1, type, &size))
continue;
if (sha1_object_info(sha1, type, &size))
continue;
- if (!add_object_entry(sha1, name, 1))
+ hash = name_hash(up, name);
+ if (!add_object_entry(sha1, hash, 1))
continue;
if (!strcmp(type, "tree")) {
struct tree_desc sub;
void *elem;
continue;
if (!strcmp(type, "tree")) {
struct tree_desc sub;
void *elem;
elem = read_sha1_file(sha1, type, &sub.size);
sub.buf = elem;
if (sub.buf) {
elem = read_sha1_file(sha1, type, &sub.size);
sub.buf = elem;
if (sub.buf) {
+ me.up = up;
+ me.elem = name;
+ me.len = strlen(name);
+ add_pbase_tree(&sub, &me);
{
struct tree_desc tree;
void *elem;
{
struct tree_desc tree;
void *elem;
elem = read_object_with_reference(sha1, "tree", &tree.size, NULL);
tree.buf = elem;
if (!tree.buf)
return;
elem = read_object_with_reference(sha1, "tree", &tree.size, NULL);
tree.buf = elem;
if (!tree.buf)
return;
- if (add_object_entry(sha1, "", 1))
- add_pbase_tree(&tree);
+ if (add_object_entry(sha1, name_hash(NULL, ""), 1))
+ add_pbase_tree(&tree, NULL);
}
if (get_sha1_hex(line, sha1))
die("expected sha1, got garbage:\n %s", line);
}
if (get_sha1_hex(line, sha1))
die("expected sha1, got garbage:\n %s", line);
- add_object_entry(sha1, line+40, 0);
+ add_object_entry(sha1, name_hash(NULL, line+41), 0);
}
if (progress)
fprintf(stderr, "Done counting %d objects.\n", nr_objects);
}
if (progress)
fprintf(stderr, "Done counting %d objects.\n", nr_objects);