[PATCH 2/8] worktree: prune corrupted worktree even if locked

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The .git/worktrees/<id>/locked file created by "git worktree lock" is
intended to prevent a missing worktree -- which might reside on a
removable device or network share -- from being pruned. It is not meant
to prevent a corrupt worktree from being pruned, yet it short-circuits
almost all "git worktree prune" corruption checks. This can make it
impossible[1] to prune a worktree which becomes corrupt after the lock
is placed since "git worktree prune" won't prune it, and it may not even
be possible to unlock it with "git worktree unlock", depending upon the
nature of the corruption.

Therefore, delay the check for .git/worktrees/<id>/locked until after
all forms of corruption have been checked so that it behaves as
originally intended (to wit: preventing pruning of a missing worktree
only).

[1]: Impossible, that is, without manually mucking around with
     .git/worktrees/<id>/ administrative files.

Signed-off-by: Eric Sunshine <sunshine@xxxxxxxxxxxxxx>
---
 builtin/worktree.c        |  4 ++--
 t/t2401-worktree-prune.sh | 14 ++++++++++++--
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index 9b15f19fc5..f7351413af 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -79,8 +79,6 @@ static int prune_worktree(const char *id, struct strbuf *reason)
 		strbuf_addstr(reason, _("not a valid directory"));
 		return 1;
 	}
-	if (file_exists(git_path("worktrees/%s/locked", id)))
-		return 0;
 	if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
 		strbuf_addstr(reason, _("gitdir file does not exist"));
 		return 1;
@@ -121,6 +119,8 @@ static int prune_worktree(const char *id, struct strbuf *reason)
 	path[len] = '\0';
 	if (!file_exists(path)) {
 		free(path);
+		if (file_exists(git_path("worktrees/%s/locked", id)))
+			return 0;
 		if (stat(git_path("worktrees/%s/index", id), &st) ||
 		    st.st_mtime <= expire) {
 			strbuf_addstr(reason, _("gitdir file points to non-existent location"));
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index b7d6d5d45a..9be8e97d66 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -69,13 +69,23 @@ test_expect_success 'prune directories with gitdir pointing to nowhere' '
 '
 
 test_expect_success 'not prune locked checkout' '
-	test_when_finished rm -r .git/worktrees &&
-	mkdir -p .git/worktrees/ghi &&
+	test_when_finished rm -fr .git/worktrees ghi &&
+	git worktree add ghi &&
 	: >.git/worktrees/ghi/locked &&
+	rm -r ghi &&
 	git worktree prune &&
 	test -d .git/worktrees/ghi
 '
 
+test_expect_success 'prune corrupt despite lock' '
+	test_when_finished rm -fr .git/worktrees ghi &&
+	mkdir -p .git/worktrees/ghi &&
+	: >.git/worktrees/ghi/gitdir &&
+	: >.git/worktrees/ghi/locked &&
+	git worktree prune &&
+	! test -d .git/worktrees/ghi
+'
+
 test_expect_success 'not prune recent checkouts' '
 	test_when_finished rm -r .git/worktrees &&
 	git worktree add jlm HEAD &&
-- 
2.27.0.290.gba653c62da




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux