Skip to content

Commit

Permalink
Make rev-list --objects work together with pathspecs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Elijah Newren authored and Junio C Hamano committed Feb 3, 2011
1 parent f577b92 commit cc5fa2f
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions list-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand All @@ -181,4 +206,5 @@ void traverse_commit_list(struct rev_info *revs,
revs->pending.alloc = 0;
revs->pending.objects = NULL;
}
strbuf_release(&base);
}

0 comments on commit cc5fa2f

Please sign in to comment.