Subject: [PATCH 10/21] tree_entry_interesting(): fix depth limit with overlapping pathspecs

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Wed, 15 Dec 2010 22:02:45 +0700

Suppose we have two pathspecs 'a' and 'a/b' (both are dirs) and depth
limit 1. In current code, pathspecs are checked in input order. When
'a/b' is checked against pathspec 'a', it fails depth limit and
therefore is excluded, although it should match 'a/b' pathspec.

This patch reorders all pathspecs alphabetically, then teaches
tree_entry_interesting() to check against the deepest pathspec first,
so depth limit of a shallower pathspec won't affect a deeper one.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 dir.c       |   13 +++++++++++++
 tree-walk.c |    2 +-
 2 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/dir.c b/dir.c
index 79e88f6..aa0522d 100644
--- a/dir.c
+++ b/dir.c
@@ -1086,6 +1086,15 @@ int remove_path(const char *name)
 	return 0;
 }
 
+static int pathspec_item_cmp(const void *a_, const void *b_)
+{
+	struct pathspec_item *a, *b;
+
+	a = (struct pathspec_item *)a_;
+	b = (struct pathspec_item *)b_;
+	return strcmp(a->match, b->match);
+}
+
 int init_pathspec(struct pathspec *pathspec, const char **paths)
 {
 	const char **p = paths;
@@ -1109,6 +1118,10 @@ int init_pathspec(struct pathspec *pathspec, const char **paths)
 		item->match = path;
 		item->len = strlen(path);
 	}
+
+	qsort(pathspec->items, pathspec->nr,
+	      sizeof(struct pathspec_item), pathspec_item_cmp);
+
 	return 0;
 }
 
diff --git a/tree-walk.c b/tree-walk.c
index 91d7b36..93b05a7 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -568,7 +568,7 @@ int tree_entry_interesting(const struct name_entry *entry,
 
 	pathlen = tree_entry_len(entry->path, entry->sha1);
 
-	for (i = 0; i < ps->nr; i++) {
+	for (i = ps->nr-1; i >= 0; i--) {
 		const struct pathspec_item *item = ps->items+i;
 		const char *match = item->match;
 		int matchlen = item->len;
-- 
1.7.3.3.476.g10a82