@@ -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 ));
0 commit comments