git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 2/7] Fix ignoring of pathspecs with rev-list --objects

From
Elijah Newren <newren@gmail.com>
Date
Aug 25, 2010, 02:53 UTC
Message-ID
<1282704795-29661-3-git-send-email-newren@gmail.com>
In-Reply-To
<1282704795-29661-1-git-send-email-newren@gmail.com>

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>
---
 diff.h                   |    1 +
 list-objects.c           |   20 +++++++++++++++++++-
 t/t6000-rev-list-misc.sh |    2 +-
 tree-diff.c              |    2 +-
 4 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/diff.h b/diff.h
index 6fff024..35130b8 100644
--- a/diff.h
+++ b/diff.h
@@ -169,6 +169,7 @@ extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
 			  const char *base, struct diff_options *opt);
 extern int diff_root_tree_sha1(const unsigned char *new, const char *base,
                                struct diff_options *opt);
+extern int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt);
 
 struct combine_diff_path {
 	struct combine_diff_path *next;
diff --git a/list-objects.c b/list-objects.c
index 8953548..daa50bf 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -67,6 +67,7 @@ static void process_tree(struct rev_info *revs,
 	struct tree_desc desc;
 	struct name_entry entry;
 	struct name_path me;
+	int all_interesting = (revs->diffopt.nr_paths == 0);
 
 	if (!revs->tree_objects)
 		return;
@@ -84,7 +85,24 @@ static void process_tree(struct rev_info *revs,
 
 	init_tree_desc(&desc, tree->buffer, tree->size);
 
-	while (tree_entry(&desc, &entry)) {
+	for (; desc.size; update_tree_entry(&desc)) {
+		entry = desc.entry;
+
+		if (!all_interesting) {
+			char *full_path = path_name(path, name);
+			int full_path_len = strlen(full_path);
+			int showit = tree_entry_interesting(&desc, full_path, full_path_len,
+							    &revs->diffopt);
+			free(full_path);
+
+			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),
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
index 2c403ac..1bc395c 100755
--- a/t/t6000-rev-list-misc.sh
+++ b/t/t6000-rev-list-misc.sh
@@ -12,7 +12,7 @@ test_expect_success setup '
 	git commit -mone
 '
 
-test_expect_failure 'rev-list --objects heeds pathspecs' '
+test_expect_success 'rev-list --objects heeds pathspecs' '
 
 	git rev-list --objects HEAD -- wanted_file >output &&
 	grep wanted_file output &&
diff --git a/tree-diff.c b/tree-diff.c
index cd659c6..2fb670b 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -91,7 +91,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
  *  - zero for no
  *  - negative for "no, and no subsequent entries will be either"
  */
-static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
+int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
 {
 	const char *path;
 	const unsigned char *sha1;
-- 
1.7.2.2.39.gf7e23
Previous: Elijah NewrenNext: Nguyen Thai Ngoc Duy
Message 3 of 16 in “Minor bug fix and optimizations for revision/tree walking”
  1. 0/7 Minor bug fix and optimizations for revision/tree walkingElijah Newren, Aug 25, 2010
  2. 1/7 Add testcase showing how pathspecs are ignored with rev-list --objectsElijah Newren, Aug 25, 2010
  3. 2/7 Fix ignoring of pathspecs with rev-list --objectsElijah Newren, Aug 25, 2010
  4. Nguyen Thai Ngoc DuyAug 25, 2010
  5. Elijah NewrenAug 25, 2010
  6. Elijah NewrenAug 26, 2010
  7. Nguyen Thai Ngoc DuyAug 26, 2010
  8. Junio C HamanoAug 26, 2010
  9. 3/7 tree-walk: Correct bitrotted comment about tree_entry()Elijah Newren, Aug 25, 2010
  10. 4/7 tree_entry_interesting(): Make return value more specificElijah Newren, Aug 25, 2010
  11. 5/7 diff_tree(): Skip skip_uninteresting() when all remaining paths interestingElijah Newren, Aug 25, 2010
  12. Junio C HamanoAug 25, 2010
  13. Elijah NewrenAug 25, 2010
  14. Junio C HamanoAug 26, 2010
  15. 6/7 list-objects.c: Avoid recomputing interesting-ness for subtrees when possibleElijah Newren, Aug 25, 2010
  16. 7/7 tree-diff.c: Avoid recomputing interesting-ness for subtrees when possibleElijah Newren, Aug 25, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.