iterator: sort subdirs properly with pathlist When given a pathlist, don't assume that directories sort before files. Walk through any list of entries sorting before us to make sure that we've exhausted all entries that *aren't* directories. Eg, if we're searching for 'foo/bar', and we have a 'foo.c', keep advancing the pathlist to keep looking for an entry prefixed with 'foo/'.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
diff --git a/src/iterator.c b/src/iterator.c
index 28629c7..9fa7cab 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -1071,13 +1071,22 @@ static dirload_pathlist_match_t dirload_pathlist_match(
&idx, pathlist, pathlist->_cmp, path) != GIT_ENOTFOUND)
return DIRLOAD_PATHLIST_EXACT;
- /* the explicit path we searched for was not found, but this may be
- * a directory and the pathlist contains a file in it. check.
+ /* the explicit path that we've seen in the directory iterator was
+ * not found - however, we may have hit a subdirectory in the directory
+ * iterator. examine the pathlist to see if it contains children of the
+ * current path. if so, indicate that we've found a subdirectory that
+ * is worth examining.
*/
- if ((matched = git_vector_get(pathlist, idx)) != NULL &&
- prefixcomp(matched, path) == 0 &&
- matched[path_len] == '/')
- return DIRLOAD_PATHLIST_DIRECTORY;
+ while ((matched = git_vector_get(pathlist, idx)) != NULL &&
+ prefixcomp(matched, path) == 0) {
+
+ if (matched[path_len] == '/')
+ return DIRLOAD_PATHLIST_DIRECTORY;
+ else if (matched[path_len] > '/')
+ break;
+
+ idx++;
+ }
return DIRLOAD_PATHLIST_NONE;
}
diff --git a/tests/repo/iterator.c b/tests/repo/iterator.c
index 8af7bc5..84dfbe1 100644
--- a/tests/repo/iterator.c
+++ b/tests/repo/iterator.c
@@ -26,7 +26,7 @@ static void expect_iterator_items(
const git_index_entry *entry;
int count, error;
int no_trees = !(git_iterator_flags(i) & GIT_ITERATOR_INCLUDE_TREES);
- bool v = false;
+ bool v = true;
if (expected_flat < 0) { v = true; expected_flat = -expected_flat; }
if (expected_total < 0) { v = true; expected_total = -expected_total; }
@@ -1236,8 +1236,11 @@ void test_repo_iterator__workdirfilelist(void)
cl_git_pass(git_vector_insert(&filelist, "c"));
cl_git_pass(git_vector_insert(&filelist, "D"));
cl_git_pass(git_vector_insert(&filelist, "e"));
+ cl_git_pass(git_vector_insert(&filelist, "k.a"));
+ cl_git_pass(git_vector_insert(&filelist, "k.b"));
cl_git_pass(git_vector_insert(&filelist, "k/1"));
cl_git_pass(git_vector_insert(&filelist, "k/a"));
+ cl_git_pass(git_vector_insert(&filelist, "kZZZZZZZ"));
cl_git_pass(git_vector_insert(&filelist, "L/1"));
g_repo = cl_git_sandbox_init("icase");
@@ -1284,8 +1287,11 @@ void test_repo_iterator__workdirfilelist_icase(void)
cl_git_pass(git_vector_insert(&filelist, "c"));
cl_git_pass(git_vector_insert(&filelist, "D"));
cl_git_pass(git_vector_insert(&filelist, "e"));
+ cl_git_pass(git_vector_insert(&filelist, "k.a"));
+ cl_git_pass(git_vector_insert(&filelist, "k.b"));
cl_git_pass(git_vector_insert(&filelist, "k/1"));
cl_git_pass(git_vector_insert(&filelist, "k/a"));
+ cl_git_pass(git_vector_insert(&filelist, "kZZZZ"));
cl_git_pass(git_vector_insert(&filelist, "L/1"));
g_repo = cl_git_sandbox_init("icase");