summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Elijah Newren <newren@gmail.com>2021-12-09 05:08:30 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2021-12-09 13:33:13 -0800
commitc65744e7d7f512f3666da5964f0ace90325dd94a (patch)
treec0dbbd7387bc94c8ac31c94dd9673069fc3edbbc
parentsymlinks: do not include startup_info->original_cwd in dir removal (diff)
downloadtgif-c65744e7d7f512f3666da5964f0ace90325dd94a.tar.xz
clean: do not attempt to remove startup_info->original_cwd
Acked-by: Derrick Stolee <stolee@gmail.com> Acked-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--builtin/clean.c44
-rwxr-xr-xt/t2501-cwd-empty.sh5
2 files changed, 38 insertions, 11 deletions
diff --git a/builtin/clean.c b/builtin/clean.c
index 98a2860409..3ff02bbbff 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -36,6 +36,8 @@ static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
static const char *msg_warn_remove_failed = N_("failed to remove %s");
static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
+static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n");
+static const char *msg_would_skip_cwd = N_("Would refuse to remove current working directory\n");
enum color_clean {
CLEAN_COLOR_RESET = 0,
@@ -153,6 +155,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
{
DIR *dir;
struct strbuf quoted = STRBUF_INIT;
+ struct strbuf realpath = STRBUF_INIT;
+ struct strbuf real_ocwd = STRBUF_INIT;
struct dirent *e;
int res = 0, ret = 0, gone = 1, original_len = path->len, len;
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,
strbuf_setlen(path, original_len);
if (*dir_gone) {
- res = dry_run ? 0 : rmdir(path->buf);
- if (!res)
- *dir_gone = 1;
- else {
- int saved_errno = errno;
- quote_path(path->buf, prefix, &quoted, 0);
- errno = saved_errno;
- warning_errno(_(msg_warn_remove_failed), quoted.buf);
+ /*
+ * Normalize path components in path->buf, e.g. change '\' to
+ * '/' on Windows.
+ */
+ strbuf_realpath(&realpath, path->buf, 1);
+
+ /*
+ * path and realpath are absolute; for comparison, we would
+ * like to transform startup_info->original_cwd to an absolute
+ * path too.
+ */
+ if (startup_info->original_cwd)
+ strbuf_realpath(&real_ocwd,
+ startup_info->original_cwd, 1);
+
+ if (!strbuf_cmp(&realpath, &real_ocwd)) {
+ printf("%s", dry_run ? _(msg_would_skip_cwd) : _(msg_skip_cwd));
*dir_gone = 0;
- ret = 1;
+ } else {
+ res = dry_run ? 0 : rmdir(path->buf);
+ if (!res)
+ *dir_gone = 1;
+ else {
+ int saved_errno = errno;
+ quote_path(path->buf, prefix, &quoted, 0);
+ errno = saved_errno;
+ warning_errno(_(msg_warn_remove_failed), quoted.buf);
+ *dir_gone = 0;
+ ret = 1;
+ }
}
}
@@ -250,6 +274,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
printf(dry_run ? _(msg_would_remove) : _(msg_remove), dels.items[i].string);
}
out:
+ strbuf_release(&realpath);
+ strbuf_release(&real_ocwd);
strbuf_release(&quoted);
string_list_clear(&dels, 0);
return ret;
diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh
index e4502d24d5..b1182390ba 100755
--- a/t/t2501-cwd-empty.sh
+++ b/t/t2501-cwd-empty.sh
@@ -230,8 +230,9 @@ test_incidental_untracked_dir_removal () {
}
test_expect_success 'clean does not remove cwd incidentally' '
- test_incidental_untracked_dir_removal failure \
- git -C .. clean -fd -e warnings . >warnings
+ test_incidental_untracked_dir_removal success \
+ git -C .. clean -fd -e warnings . >warnings &&
+ grep "Refusing to remove current working directory" warnings
'
test_expect_success 'stash does not remove cwd incidentally' '