summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2022-01-05 22:01:28 (GMT)
committerJunio C Hamano <gitster@pobox.com>2022-01-05 22:01:28 (GMT)
commitda81d473fcfa67dfbcf0504d2b5225885e51e532 (patch)
tree69f054e9d22dac00cf4b68705f3ab28dbb51a0b2 /unpack-trees.c
parentd0c99fcc618fc71cff261246b9d5605cbd225329 (diff)
parent324b170b88475811cb0506a30b4710ffc89ae936 (diff)
downloadgit-da81d473fcfa67dfbcf0504d2b5225885e51e532.zip
git-da81d473fcfa67dfbcf0504d2b5225885e51e532.tar.gz
git-da81d473fcfa67dfbcf0504d2b5225885e51e532.tar.bz2
Merge branch 'en/keep-cwd'
Many git commands that deal with working tree files try to remove a directory that becomes empty (i.e. "git switch" from a branch that has the directory to another branch that does not would attempt remove all files in the directory and the directory itself). This drops users into an unfamiliar situation if the command was run in a subdirectory that becomes subject to removal due to the command. The commands have been taught to keep an empty directory if it is the directory they were started in to avoid surprising users. * en/keep-cwd: t2501: simplify the tests since we can now assume desired behavior dir: new flag to remove_dir_recurse() to spare the original_cwd dir: avoid incidentally removing the original_cwd in remove_path() stash: do not attempt to remove startup_info->original_cwd rebase: do not attempt to remove startup_info->original_cwd clean: do not attempt to remove startup_info->original_cwd symlinks: do not include startup_info->original_cwd in dir removal unpack-trees: add special cwd handling unpack-trees: refuse to remove startup_info->original_cwd setup: introduce startup_info->original_cwd t2501: add various tests for removing the current working directory
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index 98e2f2e..360844b 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -36,6 +36,9 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_WARNING_TYPES] = {
/* ERROR_NOT_UPTODATE_DIR */
"Updating '%s' would lose untracked files in it",
+ /* ERROR_CWD_IN_THE_WAY */
+ "Refusing to remove '%s' since it is the current working directory.",
+
/* ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN */
"Untracked working tree file '%s' would be overwritten by merge.",
@@ -131,6 +134,9 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
msgs[ERROR_NOT_UPTODATE_DIR] =
_("Updating the following directories would lose untracked files in them:\n%s");
+ msgs[ERROR_CWD_IN_THE_WAY] =
+ _("Refusing to remove the current working directory:\n%s");
+
if (!strcmp(cmd, "checkout"))
msg = advice_enabled(ADVICE_COMMIT_BEFORE_MERGE)
? _("The following untracked working tree files would be removed by checkout:\n%%s"
@@ -2159,10 +2165,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
cnt++;
}
- /*
- * Then we need to make sure that we do not lose a locally
- * present file that is not ignored.
- */
+ /* Do not lose a locally present file that is not ignored. */
pathbuf = xstrfmt("%.*s/", namelen, ce->name);
memset(&d, 0, sizeof(d));
@@ -2173,6 +2176,12 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
free(pathbuf);
if (i)
return add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name);
+
+ /* Do not lose startup_info->original_cwd */
+ if (startup_info->original_cwd &&
+ !strcmp(startup_info->original_cwd, ce->name))
+ return add_rejected_path(o, ERROR_CWD_IN_THE_WAY, ce->name);
+
return cnt;
}
@@ -2265,9 +2274,18 @@ static int verify_absent_1(const struct cache_entry *ce,
int len;
struct stat st;
- if (o->index_only || !o->update ||
- o->reset == UNPACK_RESET_OVERWRITE_UNTRACKED)
+ if (o->index_only || !o->update)
+ return 0;
+
+ if (o->reset == UNPACK_RESET_OVERWRITE_UNTRACKED) {
+ /* Avoid nuking startup_info->original_cwd... */
+ if (startup_info->original_cwd &&
+ !strcmp(startup_info->original_cwd, ce->name))
+ return add_rejected_path(o, ERROR_CWD_IN_THE_WAY,
+ ce->name);
+ /* ...but nuke anything else. */
return 0;
+ }
len = check_leading_path(ce->name, ce_namelen(ce), 0);
if (!len)