Skip to content

Commit 5367469

Browse files
committed
Merge branch 'en/clean-cleanups'
Code clean-up of "git clean" resulted in a fix of recent performance regression. * en/clean-cleanups: clean: optimize and document cases where we recurse into subdirectories clean: consolidate handling of ignored parameters dir, clean: avoid disallowed behavior dir: fix a few confusing comments
2 parents 3204218 + 7233f17 commit 5367469

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

builtin/clean.c

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -924,12 +924,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
924924
0);
925925

926926
memset(&dir, 0, sizeof(dir));
927-
if (ignored_only)
928-
dir.flags |= DIR_SHOW_IGNORED;
929-
930-
if (ignored && ignored_only)
931-
die(_("-x and -X cannot be used together"));
932-
933927
if (!interactive && !dry_run && !force) {
934928
if (config_set)
935929
die(_("clean.requireForce set to true and neither -i, -n, nor -f given; "
@@ -946,6 +940,13 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
946940

947941
dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
948942

943+
if (ignored && ignored_only)
944+
die(_("-x and -X cannot be used together"));
945+
if (!ignored)
946+
setup_standard_excludes(&dir);
947+
if (ignored_only)
948+
dir.flags |= DIR_SHOW_IGNORED;
949+
949950
if (argc) {
950951
/*
951952
* Remaining args implies pathspecs specified, and we should
@@ -954,15 +955,41 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
954955
remove_directories = 1;
955956
}
956957

957-
if (remove_directories)
958-
dir.flags |= DIR_SHOW_IGNORED_TOO | DIR_KEEP_UNTRACKED_CONTENTS;
958+
if (remove_directories && !ignored_only) {
959+
/*
960+
* We need to know about ignored files too:
961+
*
962+
* If (ignored), then we will delete ignored files as well.
963+
*
964+
* If (!ignored), then even though we not are doing
965+
* anything with ignored files, we need to know about them
966+
* so that we can avoid deleting a directory of untracked
967+
* files that also contains an ignored file within it.
968+
*
969+
* For the (!ignored) case, since we only need to avoid
970+
* deleting ignored files, we can set
971+
* DIR_SHOW_IGNORED_TOO_MODE_MATCHING in order to avoid
972+
* recursing into a directory which is itself ignored.
973+
*/
974+
dir.flags |= DIR_SHOW_IGNORED_TOO;
975+
if (!ignored)
976+
dir.flags |= DIR_SHOW_IGNORED_TOO_MODE_MATCHING;
977+
978+
/*
979+
* Let the fill_directory() machinery know that we aren't
980+
* just recursing to collect the ignored files; we want all
981+
* the untracked ones so that we can delete them. (Note:
982+
* we could also set DIR_KEEP_UNTRACKED_CONTENTS when
983+
* ignored_only is true, since DIR_KEEP_UNTRACKED_CONTENTS
984+
* only has effect in combination with DIR_SHOW_IGNORED_TOO. It makes
985+
* the code clearer to exclude it, though.
986+
*/
987+
dir.flags |= DIR_KEEP_UNTRACKED_CONTENTS;
988+
}
959989

960990
if (read_cache() < 0)
961991
die(_("index file corrupt"));
962992

963-
if (!ignored)
964-
setup_standard_excludes(&dir);
965-
966993
pl = add_pattern_list(&dir, EXC_CMDL, "--exclude option");
967994
for (i = 0; i < exclude_list.nr; i++)
968995
add_pattern(exclude_list.items[i].string, "", 0, pl, -(i+1));

dir.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ int fill_directory(struct dir_struct *dir,
193193
const char *prefix;
194194
size_t prefix_len;
195195

196+
unsigned exclusive_flags = DIR_SHOW_IGNORED | DIR_SHOW_IGNORED_TOO;
197+
if ((dir->flags & exclusive_flags) == exclusive_flags)
198+
BUG("DIR_SHOW_IGNORED and DIR_SHOW_IGNORED_TOO are exclusive");
199+
196200
/*
197201
* Calculate common prefix for the pathspec, and
198202
* use that to optimize the directory walk
@@ -1836,7 +1840,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
18361840
* to recurse into untracked/ignored directories if either of the
18371841
* following bits is set:
18381842
* - DIR_SHOW_IGNORED_TOO (because then we need to determine if
1839-
* there are ignored directories below)
1843+
* there are ignored entries below)
18401844
* - DIR_HIDE_EMPTY_DIRECTORIES (because we have to determine if
18411845
* the directory is empty)
18421846
*/
@@ -1854,10 +1858,11 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
18541858
return path_excluded;
18551859

18561860
/*
1857-
* If we have we don't want to know the all the paths under an
1858-
* untracked or ignored directory, we still need to go into the
1859-
* directory to determine if it is empty (because an empty directory
1860-
* should be path_none instead of path_excluded or path_untracked).
1861+
* Even if we don't want to know all the paths under an untracked or
1862+
* ignored directory, we may still need to go into the directory to
1863+
* determine if it is empty (because with DIR_HIDE_EMPTY_DIRECTORIES,
1864+
* an empty directory should be path_none instead of path_excluded or
1865+
* path_untracked).
18611866
*/
18621867
check_only = ((dir->flags & DIR_HIDE_EMPTY_DIRECTORIES) &&
18631868
!(dir->flags & DIR_SHOW_IGNORED_TOO));

0 commit comments

Comments
 (0)