Skip to content

Commit 0a9a787

Browse files
committed
Merge branch 'ap/status-ignored-in-ignored-directory'
Output from "git status --ignored" showed an unexpected interaction with "--untracked". * ap/status-ignored-in-ignored-directory: status: always report ignored tracked directories git-status: Test --ignored behavior dir.c: Make git-status --ignored more consistent
2 parents 94383a8 + a45fb69 commit 0a9a787

File tree

3 files changed

+225
-22
lines changed

3 files changed

+225
-22
lines changed

dir.c

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
842842

843843
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
844844
{
845-
if (cache_name_exists(pathname, len, ignore_case))
845+
if (!(dir->flags & DIR_SHOW_IGNORED) &&
846+
cache_name_exists(pathname, len, ignore_case))
846847
return NULL;
847848

848849
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
@@ -944,8 +945,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
944945
* traversal routine.
945946
*
946947
* Case 1: If we *already* have entries in the index under that
947-
* directory name, we always recurse into the directory to see
948-
* all the files.
948+
* directory name, we recurse into the directory to see all the files,
949+
* unless the directory is excluded and we want to show ignored
950+
* directories
949951
*
950952
* Case 2: If we *already* have that directory name as a gitlink,
951953
* we always continue to see it as a gitlink, regardless of whether
@@ -959,6 +961,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
959961
* just a directory, unless "hide_empty_directories" is
960962
* also true and the directory is empty, in which case
961963
* we just ignore it entirely.
964+
* if we are looking for ignored directories, look if it
965+
* contains only ignored files to decide if it must be shown as
966+
* ignored or not.
962967
* (b) if it looks like a git directory, and we don't have
963968
* 'no_gitlinks' set we treat it as a gitlink, and show it
964969
* as a directory.
@@ -971,12 +976,15 @@ enum directory_treatment {
971976
};
972977

973978
static enum directory_treatment treat_directory(struct dir_struct *dir,
974-
const char *dirname, int len,
979+
const char *dirname, int len, int exclude,
975980
const struct path_simplify *simplify)
976981
{
977982
/* The "len-1" is to strip the final '/' */
978983
switch (directory_exists_in_index(dirname, len-1)) {
979984
case index_directory:
985+
if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
986+
break;
987+
980988
return recurse_into_directory;
981989

982990
case index_gitdir:
@@ -996,13 +1004,68 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
9961004
}
9971005

9981006
/* This is the "show_other_directories" case */
999-
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
1007+
1008+
/*
1009+
* We are looking for ignored files and our directory is not ignored,
1010+
* check if it contains only ignored files
1011+
*/
1012+
if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
1013+
int ignored;
1014+
dir->flags &= ~DIR_SHOW_IGNORED;
1015+
dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
1016+
ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
1017+
dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
1018+
dir->flags |= DIR_SHOW_IGNORED;
1019+
1020+
return ignored ? ignore_directory : show_directory;
1021+
}
1022+
if (!(dir->flags & DIR_SHOW_IGNORED) &&
1023+
!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
10001024
return show_directory;
10011025
if (!read_directory_recursive(dir, dirname, len, 1, simplify))
10021026
return ignore_directory;
10031027
return show_directory;
10041028
}
10051029

1030+
/*
1031+
* Decide what to do when we find a file while traversing the
1032+
* filesystem. Mostly two cases:
1033+
*
1034+
* 1. We are looking for ignored files
1035+
* (a) File is ignored, include it
1036+
* (b) File is in ignored path, include it
1037+
* (c) File is not ignored, exclude it
1038+
*
1039+
* 2. Other scenarios, include the file if not excluded
1040+
*
1041+
* Return 1 for exclude, 0 for include.
1042+
*/
1043+
static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
1044+
{
1045+
struct path_exclude_check check;
1046+
int exclude_file = 0;
1047+
1048+
if (exclude)
1049+
exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
1050+
else if (dir->flags & DIR_SHOW_IGNORED) {
1051+
/* Always exclude indexed files */
1052+
struct cache_entry *ce = index_name_exists(&the_index,
1053+
path->buf, path->len, ignore_case);
1054+
1055+
if (ce)
1056+
return 1;
1057+
1058+
path_exclude_check_init(&check, dir);
1059+
1060+
if (!is_path_excluded(&check, path->buf, path->len, dtype))
1061+
exclude_file = 1;
1062+
1063+
path_exclude_check_clear(&check);
1064+
}
1065+
1066+
return exclude_file;
1067+
}
1068+
10061069
/*
10071070
* This is an inexact early pruning of any recursive directory
10081071
* reading - if the path cannot possibly be in the pathspec,
@@ -1141,27 +1204,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
11411204
if (dtype == DT_UNKNOWN)
11421205
dtype = get_dtype(de, path->buf, path->len);
11431206

1144-
/*
1145-
* Do we want to see just the ignored files?
1146-
* We still need to recurse into directories,
1147-
* even if we don't ignore them, since the
1148-
* directory may contain files that we do..
1149-
*/
1150-
if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
1151-
if (dtype != DT_DIR)
1152-
return path_ignored;
1153-
}
1154-
11551207
switch (dtype) {
11561208
default:
11571209
return path_ignored;
11581210
case DT_DIR:
11591211
strbuf_addch(path, '/');
1160-
switch (treat_directory(dir, path->buf, path->len, simplify)) {
1212+
1213+
switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
11611214
case show_directory:
1162-
if (exclude != !!(dir->flags
1163-
& DIR_SHOW_IGNORED))
1164-
return path_ignored;
11651215
break;
11661216
case recurse_into_directory:
11671217
return path_recurse;
@@ -1171,7 +1221,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
11711221
break;
11721222
case DT_REG:
11731223
case DT_LNK:
1174-
break;
1224+
switch (treat_file(dir, path, exclude, &dtype)) {
1225+
case 1:
1226+
return path_ignored;
1227+
default:
1228+
break;
1229+
}
11751230
}
11761231
return path_handled;
11771232
}

t/t7061-wtstatus-ignore.sh

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/bin/sh
2+
3+
test_description='git-status ignored files'
4+
5+
. ./test-lib.sh
6+
7+
cat >expected <<\EOF
8+
?? .gitignore
9+
?? actual
10+
?? expected
11+
?? untracked/
12+
EOF
13+
14+
test_expect_success 'status untracked directory with --ignored' '
15+
echo "ignored" >.gitignore &&
16+
mkdir untracked &&
17+
: >untracked/ignored &&
18+
: >untracked/uncommitted &&
19+
git status --porcelain --ignored >actual &&
20+
test_cmp expected actual
21+
'
22+
23+
cat >expected <<\EOF
24+
?? .gitignore
25+
?? actual
26+
?? expected
27+
?? untracked/uncommitted
28+
!! untracked/ignored
29+
EOF
30+
31+
test_expect_success 'status untracked directory with --ignored -u' '
32+
git status --porcelain --ignored -u >actual &&
33+
test_cmp expected actual
34+
'
35+
36+
cat >expected <<\EOF
37+
?? .gitignore
38+
?? actual
39+
?? expected
40+
!! ignored/
41+
EOF
42+
43+
test_expect_success 'status ignored directory with --ignore' '
44+
rm -rf untracked &&
45+
mkdir ignored &&
46+
: >ignored/uncommitted &&
47+
git status --porcelain --ignored >actual &&
48+
test_cmp expected actual
49+
'
50+
51+
cat >expected <<\EOF
52+
?? .gitignore
53+
?? actual
54+
?? expected
55+
!! ignored/uncommitted
56+
EOF
57+
58+
test_expect_success 'status ignored directory with --ignore -u' '
59+
git status --porcelain --ignored -u >actual &&
60+
test_cmp expected actual
61+
'
62+
63+
cat >expected <<\EOF
64+
?? .gitignore
65+
?? actual
66+
?? expected
67+
!! untracked-ignored/
68+
EOF
69+
70+
test_expect_success 'status untracked directory with ignored files with --ignore' '
71+
rm -rf ignored &&
72+
mkdir untracked-ignored &&
73+
mkdir untracked-ignored/test &&
74+
: >untracked-ignored/ignored &&
75+
: >untracked-ignored/test/ignored &&
76+
git status --porcelain --ignored >actual &&
77+
test_cmp expected actual
78+
'
79+
80+
cat >expected <<\EOF
81+
?? .gitignore
82+
?? actual
83+
?? expected
84+
!! untracked-ignored/ignored
85+
!! untracked-ignored/test/ignored
86+
EOF
87+
88+
test_expect_success 'status untracked directory with ignored files with --ignore -u' '
89+
git status --porcelain --ignored -u >actual &&
90+
test_cmp expected actual
91+
'
92+
93+
cat >expected <<\EOF
94+
?? .gitignore
95+
?? actual
96+
?? expected
97+
EOF
98+
99+
test_expect_success 'status ignored tracked directory with --ignore' '
100+
rm -rf untracked-ignored &&
101+
mkdir tracked &&
102+
: >tracked/committed &&
103+
git add tracked/committed &&
104+
git commit -m. &&
105+
echo "tracked" >.gitignore &&
106+
git status --porcelain --ignored >actual &&
107+
test_cmp expected actual
108+
'
109+
110+
cat >expected <<\EOF
111+
?? .gitignore
112+
?? actual
113+
?? expected
114+
EOF
115+
116+
test_expect_success 'status ignored tracked directory with --ignore -u' '
117+
git status --porcelain --ignored -u >actual &&
118+
test_cmp expected actual
119+
'
120+
121+
cat >expected <<\EOF
122+
?? .gitignore
123+
?? actual
124+
?? expected
125+
!! tracked/
126+
EOF
127+
128+
test_expect_success 'status ignored tracked directory and uncommitted file with --ignore' '
129+
: >tracked/uncommitted &&
130+
git status --porcelain --ignored >actual &&
131+
test_cmp expected actual
132+
'
133+
134+
cat >expected <<\EOF
135+
?? .gitignore
136+
?? actual
137+
?? expected
138+
!! tracked/uncommitted
139+
EOF
140+
141+
test_expect_success 'status ignored tracked directory and uncommitted file with --ignore -u' '
142+
git status --porcelain --ignored -u >actual &&
143+
test_cmp expected actual
144+
'
145+
146+
test_done

wt-status.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,9 @@ static void wt_status_collect_untracked(struct wt_status *s)
516516

517517
if (s->show_ignored_files) {
518518
dir.nr = 0;
519-
dir.flags = DIR_SHOW_IGNORED | DIR_SHOW_OTHER_DIRECTORIES;
519+
dir.flags = DIR_SHOW_IGNORED;
520+
if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
521+
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
520522
fill_directory(&dir, s->pathspec);
521523
for (i = 0; i < dir.nr; i++) {
522524
struct dir_entry *ent = dir.entries[i];

0 commit comments

Comments
 (0)