Skip to content

Commit 85fd059

Browse files
committed
Merge branch 'ap/status-ignored-in-ignored-directory' into maint
Output from "git status --ignored" did not work well when used 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 3a51e4b + a45fb69 commit 85fd059

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
@@ -732,7 +732,8 @@ static struct dir_entry *dir_entry_new(const char *pathname, int len)
732732

733733
static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
734734
{
735-
if (cache_name_exists(pathname, len, ignore_case))
735+
if (!(dir->flags & DIR_SHOW_IGNORED) &&
736+
cache_name_exists(pathname, len, ignore_case))
736737
return NULL;
737738

738739
ALLOC_GROW(dir->entries, dir->nr+1, dir->alloc);
@@ -834,8 +835,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
834835
* traversal routine.
835836
*
836837
* Case 1: If we *already* have entries in the index under that
837-
* directory name, we always recurse into the directory to see
838-
* all the files.
838+
* directory name, we recurse into the directory to see all the files,
839+
* unless the directory is excluded and we want to show ignored
840+
* directories
839841
*
840842
* Case 2: If we *already* have that directory name as a gitlink,
841843
* we always continue to see it as a gitlink, regardless of whether
@@ -849,6 +851,9 @@ static enum exist_status directory_exists_in_index(const char *dirname, int len)
849851
* just a directory, unless "hide_empty_directories" is
850852
* also true and the directory is empty, in which case
851853
* we just ignore it entirely.
854+
* if we are looking for ignored directories, look if it
855+
* contains only ignored files to decide if it must be shown as
856+
* ignored or not.
852857
* (b) if it looks like a git directory, and we don't have
853858
* 'no_gitlinks' set we treat it as a gitlink, and show it
854859
* as a directory.
@@ -861,12 +866,15 @@ enum directory_treatment {
861866
};
862867

863868
static enum directory_treatment treat_directory(struct dir_struct *dir,
864-
const char *dirname, int len,
869+
const char *dirname, int len, int exclude,
865870
const struct path_simplify *simplify)
866871
{
867872
/* The "len-1" is to strip the final '/' */
868873
switch (directory_exists_in_index(dirname, len-1)) {
869874
case index_directory:
875+
if ((dir->flags & DIR_SHOW_OTHER_DIRECTORIES) && exclude)
876+
break;
877+
870878
return recurse_into_directory;
871879

872880
case index_gitdir:
@@ -886,13 +894,68 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
886894
}
887895

888896
/* This is the "show_other_directories" case */
889-
if (!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
897+
898+
/*
899+
* We are looking for ignored files and our directory is not ignored,
900+
* check if it contains only ignored files
901+
*/
902+
if ((dir->flags & DIR_SHOW_IGNORED) && !exclude) {
903+
int ignored;
904+
dir->flags &= ~DIR_SHOW_IGNORED;
905+
dir->flags |= DIR_HIDE_EMPTY_DIRECTORIES;
906+
ignored = read_directory_recursive(dir, dirname, len, 1, simplify);
907+
dir->flags &= ~DIR_HIDE_EMPTY_DIRECTORIES;
908+
dir->flags |= DIR_SHOW_IGNORED;
909+
910+
return ignored ? ignore_directory : show_directory;
911+
}
912+
if (!(dir->flags & DIR_SHOW_IGNORED) &&
913+
!(dir->flags & DIR_HIDE_EMPTY_DIRECTORIES))
890914
return show_directory;
891915
if (!read_directory_recursive(dir, dirname, len, 1, simplify))
892916
return ignore_directory;
893917
return show_directory;
894918
}
895919

920+
/*
921+
* Decide what to do when we find a file while traversing the
922+
* filesystem. Mostly two cases:
923+
*
924+
* 1. We are looking for ignored files
925+
* (a) File is ignored, include it
926+
* (b) File is in ignored path, include it
927+
* (c) File is not ignored, exclude it
928+
*
929+
* 2. Other scenarios, include the file if not excluded
930+
*
931+
* Return 1 for exclude, 0 for include.
932+
*/
933+
static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude, int *dtype)
934+
{
935+
struct path_exclude_check check;
936+
int exclude_file = 0;
937+
938+
if (exclude)
939+
exclude_file = !(dir->flags & DIR_SHOW_IGNORED);
940+
else if (dir->flags & DIR_SHOW_IGNORED) {
941+
/* Always exclude indexed files */
942+
struct cache_entry *ce = index_name_exists(&the_index,
943+
path->buf, path->len, ignore_case);
944+
945+
if (ce)
946+
return 1;
947+
948+
path_exclude_check_init(&check, dir);
949+
950+
if (!path_excluded(&check, path->buf, path->len, dtype))
951+
exclude_file = 1;
952+
953+
path_exclude_check_clear(&check);
954+
}
955+
956+
return exclude_file;
957+
}
958+
896959
/*
897960
* This is an inexact early pruning of any recursive directory
898961
* reading - if the path cannot possibly be in the pathspec,
@@ -1031,27 +1094,14 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
10311094
if (dtype == DT_UNKNOWN)
10321095
dtype = get_dtype(de, path->buf, path->len);
10331096

1034-
/*
1035-
* Do we want to see just the ignored files?
1036-
* We still need to recurse into directories,
1037-
* even if we don't ignore them, since the
1038-
* directory may contain files that we do..
1039-
*/
1040-
if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
1041-
if (dtype != DT_DIR)
1042-
return path_ignored;
1043-
}
1044-
10451097
switch (dtype) {
10461098
default:
10471099
return path_ignored;
10481100
case DT_DIR:
10491101
strbuf_addch(path, '/');
1050-
switch (treat_directory(dir, path->buf, path->len, simplify)) {
1102+
1103+
switch (treat_directory(dir, path->buf, path->len, exclude, simplify)) {
10511104
case show_directory:
1052-
if (exclude != !!(dir->flags
1053-
& DIR_SHOW_IGNORED))
1054-
return path_ignored;
10551105
break;
10561106
case recurse_into_directory:
10571107
return path_recurse;
@@ -1061,7 +1111,12 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
10611111
break;
10621112
case DT_REG:
10631113
case DT_LNK:
1064-
break;
1114+
switch (treat_file(dir, path, exclude, &dtype)) {
1115+
case 1:
1116+
return path_ignored;
1117+
default:
1118+
break;
1119+
}
10651120
}
10661121
return path_handled;
10671122
}

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)