git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 7/7] worktree remove: allow it when $GIT_WORK_TREE is already gone

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Feb 12, 2018, 09:49 UTC
Message-ID
<20180212094940.23834-8-pclouds@gmail.com>
In-Reply-To
<20180212094940.23834-1-pclouds@gmail.com>
"git worktree remove" basically consists of two things
- delete $GIT_WORK_TREE
- delete $GIT_DIR (which is $SUPER_GIT_DIR/worktrees/something)

If $GIT_WORK_TREE is already gone for some reason, we should be able to finish the job by deleting $GIT_DIR.

Two notes:
- $GIT_WORK_TREE _can_ be missing if the worktree is locked. In that
  case we must not delete $GIT_DIR because the real $GIT_WORK_TREE may
  be in a usb stick somewhere. This is already handled because we
  check for lock first.
- validate_worktree() is still called because it may do more checks in
  future (and it already does something else, like checking main
  worktree, but that's irrelevant in this case)
Noticed-by: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/worktree.c       | 12 +++++++-----
 t/t2028-worktree-move.sh | 17 +++++++++++++++++
 worktree.c               |  9 ++++++++-
 worktree.h               |  5 ++++-
 4 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 990e47b315..f77ef994c4 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -674,7 +674,7 @@ static int move_worktree(int ac, const char **av, const char *prefix)
 			    reason);
 		die(_("cannot move a locked working tree"));
 	}
-	if (validate_worktree(wt, &errmsg))
+	if (validate_worktree(wt, &errmsg, 0))
 		die(_("validation failed, cannot move working tree: %s"),
 		    errmsg.buf);
 	strbuf_release(&errmsg);
@@ -799,15 +799,17 @@ static int remove_worktree(int ac, const char **av, const char *prefix)
 			    reason);
 		die(_("cannot remove a locked working tree"));
 	}
-	if (validate_worktree(wt, &errmsg))
+	if (validate_worktree(wt, &errmsg, WT_VALIDATE_WORKTREE_MISSING_OK))
 		die(_("validation failed, cannot remove working tree: %s"),
 		    errmsg.buf);
 	strbuf_release(&errmsg);
 
-	if (!force)
-		check_clean_worktree(wt, av[0]);
+	if (file_exists(wt->path)) {
+		if (!force)
+			check_clean_worktree(wt, av[0]);
 
-	ret |= delete_git_work_tree(wt);
+		ret |= delete_git_work_tree(wt);
+	}
 	/*
 	 * continue on even if ret is non-zero, there's no going back
 	 * from here.
diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
index 4718c4552f..082368d8c6 100755
--- a/t/t2028-worktree-move.sh
+++ b/t/t2028-worktree-move.sh
@@ -126,4 +126,21 @@ test_expect_success 'force remove worktree with untracked file' '
 	test_path_is_missing destination
 '
 
+test_expect_success 'remove missing worktree' '
+	git worktree add to-be-gone &&
+	test -d .git/worktrees/to-be-gone &&
+	mv to-be-gone gone &&
+	git worktree remove to-be-gone &&
+	test_path_is_missing .git/worktrees/to-be-gone
+'
+
+test_expect_success 'NOT remove missing-but-locked worktree' '
+	git worktree add gone-but-locked &&
+	git worktree lock gone-but-locked &&
+	test -d .git/worktrees/gone-but-locked &&
+	mv gone-but-locked really-gone-now &&
+	test_must_fail git worktree remove gone-but-locked &&
+	test_path_is_dir .git/worktrees/gone-but-locked
+'
+
 test_done
diff --git a/worktree.c b/worktree.c
index 0373faf0dc..28989cf06e 100644
--- a/worktree.c
+++ b/worktree.c
@@ -267,7 +267,8 @@ static void strbuf_addf_gently(struct strbuf *buf, const char *fmt, ...)
 	va_end(params);
 }
 
-int validate_worktree(const struct worktree *wt, struct strbuf *errmsg)
+int validate_worktree(const struct worktree *wt, struct strbuf *errmsg,
+		      unsigned flags)
 {
 	struct strbuf wt_path = STRBUF_INIT;
 	char *path = NULL;
@@ -303,6 +304,12 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg)
 		goto done;
 	}
 
+	if (flags & WT_VALIDATE_WORKTREE_MISSING_OK &&
+	    !file_exists(wt->path)) {
+		ret = 0;
+		goto done;
+	}
+
 	if (!file_exists(wt_path.buf)) {
 		strbuf_addf_gently(errmsg, _("'%s' does not exist"), wt_path.buf);
 		goto done;
diff --git a/worktree.h b/worktree.h
index a913428c3d..fe38ce10c3 100644
--- a/worktree.h
+++ b/worktree.h
@@ -61,12 +61,15 @@ extern int is_main_worktree(const struct worktree *wt);
  */
 extern const char *is_worktree_locked(struct worktree *wt);
 
+#define WT_VALIDATE_WORKTREE_MISSING_OK (1 << 0)
+
 /*
  * Return zero if the worktree is in good condition. Error message is
  * returned if "errmsg" is not NULL.
  */
 extern int validate_worktree(const struct worktree *wt,
-			     struct strbuf *errmsg);
+			     struct strbuf *errmsg,
+			     unsigned flags);
 
 /*
  * Update worktrees/xxx/gitdir with the new path.
-- 
2.16.1.399.g632f88eed1
Previous: Nguyễn Thái Ngọc DuyNext: Nguyễn Thái Ngọc Duy
Message 42 of 49 in “nd/worktree-move reboot”
  1. 0/7 nd/worktree-move rebootNguyễn Thái Ngọc Duy, Jan 24, 2018
  2. 1/7 worktree.c: add validate_worktree()Nguyễn Thái Ngọc Duy, Jan 24, 2018
  3. 2/7 worktree.c: add update_worktree_location()Nguyễn Thái Ngọc Duy, Jan 24, 2018
  4. Eric SunshineFeb 2, 2018
  5. Duy NguyenFeb 2, 2018
  6. 3/7 worktree move: new commandNguyễn Thái Ngọc Duy, Jan 24, 2018
  7. Eric SunshineFeb 2, 2018
  8. Eric SunshineFeb 2, 2018
  9. Duy NguyenFeb 5, 2018
  10. Jeff KingFeb 6, 2018
  11. Martin ÅgrenFeb 6, 2018
  12. Duy NguyenFeb 12, 2018
  13. Martin ÅgrenFeb 12, 2018
  14. Duy NguyenFeb 13, 2018
  15. Jeff KingFeb 14, 2018
  16. Duy NguyenFeb 14, 2018
  17. Junio C HamanoFeb 14, 2018
  18. t/known-leaky: add list of known-leaky test scriptsMartin Ågren, Feb 14, 2018
  19. Jeff KingFeb 19, 2018
  20. Martin ÅgrenFeb 20, 2018
  21. Jeff KingFeb 20, 2018
  22. Junio C HamanoFeb 21, 2018
  23. Jeff KingFeb 21, 2018
  24. Kaartic SivaraamFeb 25, 2018
  25. Martin ÅgrenFeb 26, 2018
  26. 4/7 worktree move: accept destination as directoryNguyễn Thái Ngọc Duy, Jan 24, 2018
  27. Eric SunshineFeb 2, 2018
  28. 5/7 worktree move: refuse to move worktrees with submodulesNguyễn Thái Ngọc Duy, Jan 24, 2018
  29. Eric SunshineFeb 2, 2018
  30. 6/7 worktree remove: new commandNguyễn Thái Ngọc Duy, Jan 24, 2018
  31. Eric SunshineFeb 2, 2018
  32. Duy NguyenFeb 12, 2018
  33. 7/7 worktree remove: allow it when $GIT_WORK_TREE is already goneNguyễn Thái Ngọc Duy, Jan 24, 2018
  34. Eric SunshineFeb 2, 2018
  35. Junio C HamanoJan 24, 2018
  36. 0/7 nd/worktree-move rebootNguyễn Thái Ngọc Duy, Feb 12, 2018
  37. 1/7 worktree.c: add validate_worktree()Nguyễn Thái Ngọc Duy, Feb 12, 2018
  38. 2/7 worktree.c: add update_worktree_location()Nguyễn Thái Ngọc Duy, Feb 12, 2018
  39. 4/7 worktree move: accept destination as directoryNguyễn Thái Ngọc Duy, Feb 12, 2018
  40. 5/7 worktree move: refuse to move worktrees with submodulesNguyễn Thái Ngọc Duy, Feb 12, 2018
  41. 6/7 worktree remove: new commandNguyễn Thái Ngọc Duy, Feb 12, 2018
  42. 7/7 worktree remove: allow it when $GIT_WORK_TREE is already goneNguyễn Thái Ngọc Duy, Feb 12, 2018
  43. 3/7 worktree move: new commandNguyễn Thái Ngọc Duy, Feb 12, 2018
  44. t2028: fix minor error and issues in newly-added "worktree move" testsEric Sunshine, Mar 4, 2018
  45. Duy NguyenMar 5, 2018
  46. SZEDER GáborMar 5, 2018
  47. Junio C HamanoMar 5, 2018
  48. Eric SunshineMar 5, 2018
  49. Eric SunshineMar 4, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.