From: Elijah Newren <newren@xxxxxxxxx> dir has a convenient remove_path() helper that will both remove a file in a directory and remove its containing directory if it becomes empty as a result of the removal, recursing all the way up. However, we do not want the current working directory to be removed, even if it becomes empty. dir also has a remove_dir_recursively() function which appears to mostly be used to remove metadata directories or temporary directories or submodules or worktrees. I am not sure if it needs to be protected against removing the current working directory, but did so for good measure. Signed-off-by: Elijah Newren <newren@xxxxxxxxx> --- dir.c | 11 ++++++++--- t/t2501-cwd-empty.sh | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dir.c b/dir.c index 94489298f4c..15e7639a158 100644 --- a/dir.c +++ b/dir.c @@ -3259,9 +3259,12 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) closedir(dir); strbuf_setlen(path, original_len); - if (!ret && !keep_toplevel && !kept_down) - ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1; - else if (kept_up) + if (!ret && !keep_toplevel && !kept_down) { + if (the_cwd && !strcmp(the_cwd, path->buf)) + ret = -1; /* Do not remove current working directory */ + else + ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1; + } else if (kept_up) /* * report the uplevel that it is not an error that we * did not rmdir() our directory. @@ -3327,6 +3330,8 @@ int remove_path(const char *name) slash = dirs + (slash - name); do { *slash = '\0'; + if (the_cwd && !strcmp(the_cwd, dirs)) + break; } while (rmdir(dirs) == 0 && (slash = strrchr(dirs, '/'))); free(dirs); } diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index ff4e7cd89fa..4362e7b15e5 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -191,7 +191,7 @@ test_expect_success 'revert fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'rm does not remove cwd incidentally' ' +test_expect_success 'rm does not remove cwd incidentally' ' test_when_finished "git reset --hard" && git checkout foo/bar/baz && @@ -205,7 +205,7 @@ test_expect_failure 'rm does not remove cwd incidentally' ' test_path_is_dir foo ' -test_expect_failure 'apply does not remove cwd incidentally' ' +test_expect_success 'apply does not remove cwd incidentally' ' test_when_finished "git reset --hard" && git checkout foo/bar/baz && -- gitgitgadget