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:
parent
eb38cc689e
commit
e646de0d14
69
rev-list.c
69
rev-list.c
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user