Skip to content

Commit 580a5d7

Browse files
newrengitster
authored andcommitted
dir: new flag to remove_dir_recurse() to spare the original_cwd
remove_dir_recurse(), and its non-static wrapper called remove_dir_recursively(), both take flags for modifying its behavior. As with the previous commits, we would generally like to protect the original_cwd, but we want to forced user commands (e.g. 'git rm -rf ...') or other special cases to remove it. Add a flag for this purpose. After reading through every caller of remove_dir_recursively() in the current codebase, there was only one that should be adjusted and that one only in a very unusual circumstance. Add a pair of new testcases to highlight that very specific case involving submodules && --git-dir && --work-tree. Acked-by: Derrick Stolee <[email protected]> Acked-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 63bbe8b commit 580a5d7

File tree

4 files changed

+14
-9
lines changed

4 files changed

+14
-9
lines changed

builtin/rm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,12 +399,13 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
399399
if (!index_only) {
400400
int removed = 0, gitmodules_modified = 0;
401401
struct strbuf buf = STRBUF_INIT;
402+
int flag = force ? REMOVE_DIR_PURGE_ORIGINAL_CWD : 0;
402403
for (i = 0; i < list.nr; i++) {
403404
const char *path = list.entry[i].name;
404405
if (list.entry[i].is_submodule) {
405406
strbuf_reset(&buf);
406407
strbuf_addstr(&buf, path);
407-
if (remove_dir_recursively(&buf, 0))
408+
if (remove_dir_recursively(&buf, flag))
408409
die(_("could not remove '%s'"), path);
409410

410411
removed = 1;

dir.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3204,6 +3204,7 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
32043204
int ret = 0, original_len = path->len, len, kept_down = 0;
32053205
int only_empty = (flag & REMOVE_DIR_EMPTY_ONLY);
32063206
int keep_toplevel = (flag & REMOVE_DIR_KEEP_TOPLEVEL);
3207+
int purge_original_cwd = (flag & REMOVE_DIR_PURGE_ORIGINAL_CWD);
32073208
struct object_id submodule_head;
32083209

32093210
if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
@@ -3259,9 +3260,14 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
32593260
closedir(dir);
32603261

32613262
strbuf_setlen(path, original_len);
3262-
if (!ret && !keep_toplevel && !kept_down)
3263-
ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1;
3264-
else if (kept_up)
3263+
if (!ret && !keep_toplevel && !kept_down) {
3264+
if (!purge_original_cwd &&
3265+
startup_info->original_cwd &&
3266+
!strcmp(startup_info->original_cwd, path->buf))
3267+
ret = -1; /* Do not remove current working directory */
3268+
else
3269+
ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1;
3270+
} else if (kept_up)
32653271
/*
32663272
* report the uplevel that it is not an error that we
32673273
* did not rmdir() our directory.

dir.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ int get_sparse_checkout_patterns(struct pattern_list *pl);
495495
/* Remove the contents of path, but leave path itself. */
496496
#define REMOVE_DIR_KEEP_TOPLEVEL 04
497497

498+
/* Remove the_original_cwd too */
499+
#define REMOVE_DIR_PURGE_ORIGINAL_CWD 0x08
500+
498501
/*
499502
* Remove path and its contents, recursively. flags is a combination
500503
* of the above REMOVE_DIR_* constants. Return 0 on success.

t/t2501-cwd-empty.sh

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,11 +291,6 @@ test_submodule_removal () {
291291
test_status=
292292
test "$path_status" = dir && test_status=test_must_fail
293293

294-
# Actually, while path_status=dir && test_status=test_must_fail
295-
# reflect our desired behavior, current behavior is:
296-
path_status=missing
297-
test_status=
298-
299294
test_when_finished "git reset --hard HEAD~1" &&
300295
test_when_finished "rm -rf .git/modules/my_submodule" &&
301296

0 commit comments

Comments
 (0)