Skip to content

Commit fb89888

Browse files
Samuel Lijingitster
authored andcommitted
dir: hide untracked contents of untracked dirs
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 doesn't always make sense to return these, though (we do need them for `clean -d`), so we introduce a flag (DIR_KEEP_UNTRACKED_CONTENTS) to control whether or not read_directory() strips dir->entries of the untracked contents of untracked dirs. We also introduce check_contains() to check if one dir_entry corresponds to a path which contains the path corresponding to another dir_entry. This also fixes known breakages in t7061, since status --ignored now searches untracked directories for ignored files. Signed-off-by: Samuel Lijin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent df5bcdf commit fb89888

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed

Documentation/technical/api-directory-listing.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ The notable options are:
3333
Similar to `DIR_SHOW_IGNORED`, but return ignored files in `ignored[]`
3434
in addition to untracked files in `entries[]`.
3535

36+
`DIR_KEEP_UNTRACKED_CONTENTS`:::
37+
38+
Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is set, the
39+
untracked contents of untracked directories are also returned in
40+
`entries[]`.
41+
3642
`DIR_COLLECT_IGNORED`:::
3743

3844
Special mode for git-add. Return ignored files in `ignored[]` and

dir.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,14 @@ static int cmp_name(const void *p1, const void *p2)
18131813
return name_compare(e1->name, e1->len, e2->name, e2->len);
18141814
}
18151815

1816+
/* check if *out lexically strictly contains *in */
1817+
static int check_contains(const struct dir_entry *out, const struct dir_entry *in)
1818+
{
1819+
return (out->len < in->len) &&
1820+
(out->name[out->len - 1] == '/') &&
1821+
!memcmp(out->name, in->name, out->len);
1822+
}
1823+
18161824
static int treat_leading_path(struct dir_struct *dir,
18171825
const char *path, int len,
18181826
const struct pathspec *pathspec)
@@ -2028,6 +2036,29 @@ int read_directory(struct dir_struct *dir, const char *path,
20282036
read_directory_recursive(dir, path, len, untracked, 0, pathspec);
20292037
QSORT(dir->entries, dir->nr, cmp_name);
20302038
QSORT(dir->ignored, dir->ignored_nr, cmp_name);
2039+
2040+
/*
2041+
* If DIR_SHOW_IGNORED_TOO is set, read_directory_recursive() will
2042+
* also pick up untracked contents of untracked dirs; by default
2043+
* we discard these, but given DIR_KEEP_UNTRACKED_CONTENTS we do not.
2044+
*/
2045+
if ((dir->flags & DIR_SHOW_IGNORED_TOO) &&
2046+
!(dir->flags & DIR_KEEP_UNTRACKED_CONTENTS)) {
2047+
int i, j;
2048+
2049+
/* remove from dir->entries untracked contents of untracked dirs */
2050+
for (i = j = 0; j < dir->nr; j++) {
2051+
if (i && check_contains(dir->entries[i - 1], dir->entries[j])) {
2052+
free(dir->entries[j]);
2053+
dir->entries[j] = NULL;
2054+
} else {
2055+
dir->entries[i++] = dir->entries[j];
2056+
}
2057+
}
2058+
2059+
dir->nr = i;
2060+
}
2061+
20312062
if (dir->untracked) {
20322063
static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS);
20332064
trace_printf_key(&trace_untracked_stats,

dir.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ struct dir_struct {
151151
DIR_NO_GITLINKS = 1<<3,
152152
DIR_COLLECT_IGNORED = 1<<4,
153153
DIR_SHOW_IGNORED_TOO = 1<<5,
154-
DIR_COLLECT_KILLED_ONLY = 1<<6
154+
DIR_COLLECT_KILLED_ONLY = 1<<6,
155+
DIR_KEEP_UNTRACKED_CONTENTS = 1<<7
155156
} flags;
156157
struct dir_entry **entries;
157158
struct dir_entry **ignored;

t/t7061-wtstatus-ignore.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ cat >expected <<\EOF
1212
!! untracked/ignored
1313
EOF
1414

15-
test_expect_failure 'status untracked directory with --ignored' '
15+
test_expect_success 'status untracked directory with --ignored' '
1616
echo "ignored" >.gitignore &&
1717
mkdir untracked &&
1818
: >untracked/ignored &&
@@ -21,7 +21,7 @@ test_expect_failure 'status untracked directory with --ignored' '
2121
test_cmp expected actual
2222
'
2323

24-
test_expect_failure 'same with gitignore starting with BOM' '
24+
test_expect_success 'same with gitignore starting with BOM' '
2525
printf "\357\273\277ignored\n" >.gitignore &&
2626
mkdir -p untracked &&
2727
: >untracked/ignored &&

0 commit comments

Comments
 (0)