When we taught read_directory_recursive() to recurse into untracked
directories in search of ignored files given DIR_SHOW_IGNORED_TOO, that
had the side effect of teaching it to collect the untracked contents of
untracked directories. It does not make sense to return these, so we
teach read_directory() to strip dir->entries of any such untracked
contents.
---
dir.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/dir.c b/dir.c
index 25cb9eadf..f0ddb4608 100644
--- a/dir.c
+++ b/dir.c
@@ -2075,6 +2075,50 @@ int read_directory(struct dir_struct *dir, const char
*path,
read_directory_recursive(dir, path, len, untracked, 0,
pathspec);
QSORT(dir->entries, dir->nr, cmp_name);
QSORT(dir->ignored, dir->ignored_nr, cmp_name);
+
+ // if collecting ignored files, never consider a directory containing
+ // ignored files to be untracked
+ if (dir->flags & DIR_SHOW_IGNORED_TOO) {
+ int i, j, nr_removed = 0;
+
+ // remove from dir->entries untracked contents of untracked dirs
+ for (i = 0; i < dir->nr; i++) {
+ if (!dir->entries[i])
+ continue;
+
+ for (j = i + 1; j < dir->nr; j++) {
+ if (!dir->entries[j])
+ continue;
+ if (check_contains(dir->entries[i],
dir->entries[j])) {
+ nr_removed++;
+ free(dir->entries[j]);
+ dir->entries[j] = NULL;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ // strip dir->entries of NULLs
+ if (nr_removed) {
+ for (i = 0;;) {
+ while (i < dir->nr && dir->entries[i])
+ i++;
+ if (i == dir->nr)
+ break;
+ j = i;
+ while (j < dir->nr && !dir->entries[j])
+ j++;
+ if (j == dir->nr)
+ break;
+ dir->entries[i] = dir->entries[j];
+ dir->entries[j] = NULL;
+ }
+ dir->nr -= nr_removed;
+ }
+ }
+
if (dir->untracked) {
static struct trace_key trace_untracked_stats =
TRACE_KEY_INIT(UNTRACKED_STATS);
trace_printf_key(&trace_untracked_stats,
--
2.12.2