aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-02-22 22:10:24 -0800
committerJunio C Hamano <junkio@cox.net>2006-02-23 23:44:42 -0800
commite646de0d14bac20ef6e156c1742b9e62fb0b9020 (patch)
tree2514f45e7d93ab264162dff916ad55e613d96c14
parenteb38cc689e84a8fd01c1856e889fe8d3b4f1bfb4 (diff)
downloadgit-e646de0d14bac20ef6e156c1742b9e62fb0b9020.tar.gz
git-e646de0d14bac20ef6e156c1742b9e62fb0b9020.tar.xz
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>
-rw-r--r--rev-list.c69
1 files changed, 56 insertions, 13 deletions
diff --git a/rev-list.c b/rev-list.c
index b5de0759f..dda6fcaa9 100644
--- a/rev-list.c
+++ b/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)