1515#include "quote.h"
1616
1717static int force = -1 ; /* unset */
18+ static struct string_list del_list = STRING_LIST_INIT_DUP ;
1819
1920static const char * const builtin_clean_usage [] = {
2021 N_ ("git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..." ),
@@ -148,12 +149,13 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
148149 int dry_run = 0 , remove_directories = 0 , quiet = 0 , ignored = 0 ;
149150 int ignored_only = 0 , config_set = 0 , errors = 0 , gone = 1 ;
150151 int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT ;
151- struct strbuf directory = STRBUF_INIT ;
152+ struct strbuf abs_path = STRBUF_INIT ;
152153 struct dir_struct dir ;
153154 static const char * * pathspec ;
154155 struct strbuf buf = STRBUF_INIT ;
155156 struct string_list exclude_list = STRING_LIST_INIT_NODUP ;
156157 struct exclude_list * el ;
158+ struct string_list_item * item ;
157159 const char * qname ;
158160 char * seen = NULL ;
159161 struct option options [] = {
@@ -223,6 +225,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
223225 int matches = 0 ;
224226 struct cache_entry * ce ;
225227 struct stat st ;
228+ const char * rel ;
226229
227230 /*
228231 * Remove the '/' at the end that directory
@@ -242,13 +245,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
242245 continue ; /* Yup, this one exists unmerged */
243246 }
244247
245- /*
246- * we might have removed this as part of earlier
247- * recursive directory removal, so lstat() here could
248- * fail with ENOENT.
249- */
250248 if (lstat (ent -> name , & st ))
251- continue ;
249+ die_errno ( "Cannot lstat '%s'" , ent -> name ) ;
252250
253251 if (pathspec ) {
254252 memset (seen , 0 , argc > 0 ? argc : 1 );
@@ -257,33 +255,61 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
257255 }
258256
259257 if (S_ISDIR (st .st_mode )) {
260- strbuf_addstr (& directory , ent -> name );
261258 if (remove_directories || (matches == MATCHED_EXACTLY )) {
262- if (remove_dirs (& directory , prefix , rm_flags , dry_run , quiet , & gone ))
263- errors ++ ;
264- if (gone && !quiet ) {
265- qname = quote_path_relative (directory .buf , prefix , & buf );
266- printf (dry_run ? _ (msg_would_remove ) : _ (msg_remove ), qname );
267- }
259+ rel = relative_path (ent -> name , prefix , & buf );
260+ string_list_append (& del_list , rel );
268261 }
269- strbuf_reset (& directory );
270262 } else {
271263 if (pathspec && !matches )
272264 continue ;
273- res = dry_run ? 0 : unlink (ent -> name );
265+ rel = relative_path (ent -> name , prefix , & buf );
266+ string_list_append (& del_list , rel );
267+ }
268+ }
269+
270+ /* TODO: do interactive git-clean here, which will modify del_list */
271+
272+ for_each_string_list_item (item , & del_list ) {
273+ struct stat st ;
274+
275+ if (prefix )
276+ strbuf_addstr (& abs_path , prefix );
277+
278+ strbuf_addstr (& abs_path , item -> string );
279+
280+ /*
281+ * we might have removed this as part of earlier
282+ * recursive directory removal, so lstat() here could
283+ * fail with ENOENT.
284+ */
285+ if (lstat (abs_path .buf , & st ))
286+ continue ;
287+
288+ if (S_ISDIR (st .st_mode )) {
289+ if (remove_dirs (& abs_path , prefix , rm_flags , dry_run , quiet , & gone ))
290+ errors ++ ;
291+ if (gone && !quiet ) {
292+ qname = quote_path_relative (item -> string , NULL , & buf );
293+ printf (dry_run ? _ (msg_would_remove ) : _ (msg_remove ), qname );
294+ }
295+ } else {
296+ res = dry_run ? 0 : unlink (abs_path .buf );
274297 if (res ) {
275- qname = quote_path_relative (ent -> name , prefix , & buf );
298+ qname = quote_path_relative (item -> string , NULL , & buf );
276299 warning (_ (msg_warn_remove_failed ), qname );
277300 errors ++ ;
278301 } else if (!quiet ) {
279- qname = quote_path_relative (ent -> name , prefix , & buf );
302+ qname = quote_path_relative (item -> string , NULL , & buf );
280303 printf (dry_run ? _ (msg_would_remove ) : _ (msg_remove ), qname );
281304 }
282305 }
306+ strbuf_reset (& abs_path );
283307 }
284308 free (seen );
285309
286- strbuf_release (& directory );
310+ strbuf_release (& abs_path );
311+ strbuf_release (& buf );
312+ string_list_clear (& del_list , 0 );
287313 string_list_clear (& exclude_list , 0 );
288314 return (errors != 0 );
289315}
0 commit comments