summaryrefslogtreecommitdiff
path: root/list-objects.c
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2010-12-17 13:26:47 (GMT)
committerJunio C Hamano <gitster@pobox.com>2011-02-03 22:10:46 (GMT)
commitcc5fa2fdafa186d6e1e310828b22d0028e1fb51b (patch)
treeb29c740aed0ae94a7e2367d0f82cccfd42574b01 /list-objects.c
parentf577b92fe75643228674c0dcb2a4747587cf541d (diff)
downloadgit-cc5fa2fdafa186d6e1e310828b22d0028e1fb51b.zip
git-cc5fa2fdafa186d6e1e310828b22d0028e1fb51b.tar.gz
git-cc5fa2fdafa186d6e1e310828b22d0028e1fb51b.tar.bz2
Make rev-list --objects work together with pathspecs
When traversing commits, the selection of commits would heed the list of pathspecs passed, but subsequent walking of the trees of those commits would not. This resulted in 'rev-list --objects HEAD -- <paths>' displaying objects at unwanted paths. Have process_tree() call tree_entry_interesting() to determine which paths are interesting and should be walked. Naturally, this change can provide a large speedup when paths are specified together with --objects, since many tree entries are now correctly ignored. Interestingly, though, this change also gives me a small (~1%) but repeatable speedup even when no paths are specified with --objects. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'list-objects.c')
-rw-r--r--list-objects.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/list-objects.c b/list-objects.c
index 8953548..61f6cc9 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -61,12 +61,15 @@ static void process_tree(struct rev_info *revs,
struct tree *tree,
show_object_fn show,
struct name_path *path,
+ struct strbuf *base,
const char *name)
{
struct object *obj = &tree->object;
struct tree_desc desc;
struct name_entry entry;
struct name_path me;
+ int all_interesting = (revs->diffopt.pathspec.nr == 0);
+ int baselen = base->len;
if (!revs->tree_objects)
return;
@@ -82,13 +85,32 @@ static void process_tree(struct rev_info *revs,
me.elem = name;
me.elem_len = strlen(name);
+ if (!all_interesting) {
+ strbuf_addstr(base, name);
+ if (base->len)
+ strbuf_addch(base, '/');
+ }
+
init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
+ if (!all_interesting) {
+ int showit = tree_entry_interesting(&entry,
+ base, 0,
+ &revs->diffopt.pathspec);
+
+ if (showit < 0)
+ break;
+ else if (!showit)
+ continue;
+ else if (showit == 2)
+ all_interesting = 1;
+ }
+
if (S_ISDIR(entry.mode))
process_tree(revs,
lookup_tree(entry.sha1),
- show, &me, entry.path);
+ show, &me, base, entry.path);
else if (S_ISGITLINK(entry.mode))
process_gitlink(revs, entry.sha1,
show, &me, entry.path);
@@ -97,6 +119,7 @@ static void process_tree(struct rev_info *revs,
lookup_blob(entry.sha1),
show, &me, entry.path);
}
+ strbuf_setlen(base, baselen);
free(tree->buffer);
tree->buffer = NULL;
}
@@ -146,7 +169,9 @@ void traverse_commit_list(struct rev_info *revs,
{
int i;
struct commit *commit;
+ struct strbuf base;
+ strbuf_init(&base, PATH_MAX);
while ((commit = get_revision(revs)) != NULL) {
add_pending_tree(revs, commit->tree);
show_commit(commit, data);
@@ -164,7 +189,7 @@ void traverse_commit_list(struct rev_info *revs,
}
if (obj->type == OBJ_TREE) {
process_tree(revs, (struct tree *)obj, show_object,
- NULL, name);
+ NULL, &base, name);
continue;
}
if (obj->type == OBJ_BLOB) {
@@ -181,4 +206,5 @@ void traverse_commit_list(struct rev_info *revs,
revs->pending.alloc = 0;
revs->pending.objects = NULL;
}
+ strbuf_release(&base);
}