rev-list --objects: use full pathname to help hashing.

This helps to group the same files from different revs together,
while spreading files with the same basename in different
directories, to help pack-object.

Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Junio C Hamano 2006-02-22 22:10:24 -08:00
parent eb38cc689e
commit e646de0d14

View file

@ -63,6 +63,36 @@ static int no_merges = 0;
static const char **paths = NULL;
static int remove_empty_trees = 0;
struct name_path {
struct name_path *up;
int elem_len;
const char *elem;
};
static char *path_name(struct name_path *path, const char *name)
{
struct name_path *p;
char *n, *m;
int nlen = strlen(name);
int len = nlen + 1;
for (p = path; p; p = p->up) {
if (p->elem_len)
len += p->elem_len + 1;
}
n = xmalloc(len);
m = n + len - (nlen + 1);
strcpy(m, name);
for (p = path; p; p = p->up) {
if (p->elem_len) {
m -= p->elem_len + 1;
memcpy(m, p->elem, p->elem_len);
m[p->elem_len] = '/';
}
}
return n;
}
static void show_commit(struct commit *commit)
{
commit->object.flags |= SHOWN;
@ -174,17 +204,23 @@ static int process_commit(struct commit * commit)
return CONTINUE;
}
static struct object_list **add_object(struct object *obj, struct object_list **p, const char *name)
static struct object_list **add_object(struct object *obj,
struct object_list **p,
struct name_path *path,
const char *name)
{
struct object_list *entry = xmalloc(sizeof(*entry));
entry->item = obj;
entry->next = *p;
entry->name = name;
entry->name = path_name(path, name);
*p = entry;
return &entry->next;
}
static struct object_list **process_blob(struct blob *blob, struct object_list **p, const char *name)
static struct object_list **process_blob(struct blob *blob,
struct object_list **p,
struct name_path *path,
const char *name)
{
struct object *obj = &blob->object;
@ -193,13 +229,17 @@ static struct object_list **process_blob(struct blob *blob, struct object_list *
if (obj->flags & (UNINTERESTING | SEEN))
return p;
obj->flags |= SEEN;
return add_object(obj, p, name);
return add_object(obj, p, path, name);
}
static struct object_list **process_tree(struct tree *tree, struct object_list **p, const char *name)
static struct object_list **process_tree(struct tree *tree,
struct object_list **p,
struct name_path *path,
const char *name)
{
struct object *obj = &tree->object;
struct tree_entry_list *entry;
struct name_path me;
if (!tree_objects)
return p;
@ -208,15 +248,18 @@ static struct object_list **process_tree(struct tree *tree, struct object_list *
if (parse_tree(tree) < 0)
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
p = add_object(obj, p, name);
p = add_object(obj, p, path, name);
me.up = path;
me.elem = name;
me.elem_len = strlen(name);
entry = tree->entries;
tree->entries = NULL;
while (entry) {
struct tree_entry_list *next = entry->next;
if (entry->directory)
p = process_tree(entry->item.tree, p, entry->name);
p = process_tree(entry->item.tree, p, &me, entry->name);
else
p = process_blob(entry->item.blob, p, entry->name);
p = process_blob(entry->item.blob, p, &me, entry->name);
free(entry);
entry = next;
}
@ -231,7 +274,7 @@ static void show_commit_list(struct commit_list *list)
while (list) {
struct commit *commit = pop_most_recent_commit(&list, SEEN);
p = process_tree(commit->tree, p, "");
p = process_tree(commit->tree, p, NULL, "");
if (process_commit(commit) == STOP)
break;
}
@ -242,15 +285,15 @@ static void show_commit_list(struct commit_list *list)
continue;
if (obj->type == tag_type) {
obj->flags |= SEEN;
p = add_object(obj, p, name);
p = add_object(obj, p, NULL, name);
continue;
}
if (obj->type == tree_type) {
p = process_tree((struct tree *)obj, p, name);
p = process_tree((struct tree *)obj, p, NULL, name);
continue;
}
if (obj->type == blob_type) {
p = process_blob((struct blob *)obj, p, name);
p = process_blob((struct blob *)obj, p, NULL, name);
continue;
}
die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
@ -674,7 +717,7 @@ static struct commit_list *limit_list(struct commit_list *list)
static void add_pending_object(struct object *obj, const char *name)
{
add_object(obj, &pending_objects, name);
add_object(obj, &pending_objects, NULL, name);
}
static struct commit *get_commit_reference(const char *name, const unsigned char *sha1, unsigned int flags)