@@ -36,6 +36,8 @@ static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
3636static const char * msg_would_skip_git_dir = N_ ("Would skip repository %s\n" );
3737static const char * msg_warn_remove_failed = N_ ("failed to remove %s" );
3838static const char * msg_warn_lstat_failed = N_ ("could not lstat %s\n" );
39+ static const char * msg_skip_cwd = N_ ("Refusing to remove current working directory\n" );
40+ static const char * msg_would_skip_cwd = N_ ("Would refuse to remove current working directory\n" );
3941
4042enum color_clean {
4143 CLEAN_COLOR_RESET = 0 ,
@@ -153,6 +155,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
153155{
154156 DIR * dir ;
155157 struct strbuf quoted = STRBUF_INIT ;
158+ struct strbuf realpath = STRBUF_INIT ;
159+ struct strbuf real_ocwd = STRBUF_INIT ;
156160 struct dirent * e ;
157161 int res = 0 , ret = 0 , gone = 1 , original_len = path -> len , len ;
158162 struct string_list dels = STRING_LIST_INIT_DUP ;
@@ -231,16 +235,36 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
231235 strbuf_setlen (path , original_len );
232236
233237 if (* dir_gone ) {
234- res = dry_run ? 0 : rmdir (path -> buf );
235- if (!res )
236- * dir_gone = 1 ;
237- else {
238- int saved_errno = errno ;
239- quote_path (path -> buf , prefix , & quoted , 0 );
240- errno = saved_errno ;
241- warning_errno (_ (msg_warn_remove_failed ), quoted .buf );
238+ /*
239+ * Normalize path components in path->buf, e.g. change '\' to
240+ * '/' on Windows.
241+ */
242+ strbuf_realpath (& realpath , path -> buf , 1 );
243+
244+ /*
245+ * path and realpath are absolute; for comparison, we would
246+ * like to transform startup_info->original_cwd to an absolute
247+ * path too.
248+ */
249+ if (startup_info -> original_cwd )
250+ strbuf_realpath (& real_ocwd ,
251+ startup_info -> original_cwd , 1 );
252+
253+ if (!strbuf_cmp (& realpath , & real_ocwd )) {
254+ printf ("%s" , dry_run ? _ (msg_would_skip_cwd ) : _ (msg_skip_cwd ));
242255 * dir_gone = 0 ;
243- ret = 1 ;
256+ } else {
257+ res = dry_run ? 0 : rmdir (path -> buf );
258+ if (!res )
259+ * dir_gone = 1 ;
260+ else {
261+ int saved_errno = errno ;
262+ quote_path (path -> buf , prefix , & quoted , 0 );
263+ errno = saved_errno ;
264+ warning_errno (_ (msg_warn_remove_failed ), quoted .buf );
265+ * dir_gone = 0 ;
266+ ret = 1 ;
267+ }
244268 }
245269 }
246270
@@ -250,6 +274,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
250274 printf (dry_run ? _ (msg_would_remove ) : _ (msg_remove ), dels .items [i ].string );
251275 }
252276out :
277+ strbuf_release (& realpath );
278+ strbuf_release (& real_ocwd );
253279 strbuf_release (& quoted );
254280 string_list_clear (& dels , 0 );
255281 return ret ;
0 commit comments