aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--builtin/worktree.c25
-rwxr-xr-xt/t2025-worktree-add.sh7
2 files changed, 32 insertions, 0 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 46c93771e8..1122f27b5f 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -221,8 +221,33 @@ static const char *worktree_basename(const char *path, int *olen)
static void validate_worktree_add(const char *path, const struct add_opts *opts)
{
+ struct worktree **worktrees;
+ struct worktree *wt;
+ int locked;
+
if (file_exists(path) && !is_empty_dir(path))
die(_("'%s' already exists"), path);
+
+ worktrees = get_worktrees(0);
+ /*
+ * find_worktree()'s suffix matching may undesirably find the main
+ * rather than a linked worktree (for instance, when the basenames
+ * of the main worktree and the one being created are the same).
+ * We're only interested in linked worktrees, so skip the main
+ * worktree with +1.
+ */
+ wt = find_worktree(worktrees + 1, NULL, path);
+ if (!wt)
+ goto done;
+
+ locked = !!is_worktree_locked(wt);
+ if (locked)
+ die(_("'%s' is a missing but locked worktree;\nuse 'unlock' and 'prune' or 'remove' to clear"), path);
+ else
+ die(_("'%s' is a missing but already registered worktree;\nuse 'prune' or 'remove' to clear"), path);
+
+done:
+ free_worktrees(worktrees);
}
static int add_worktree(const char *path, const char *refname,
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 07d292317c..67fccc6591 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -552,4 +552,11 @@ test_expect_success '"add" in bare repo invokes post-checkout hook' '
test_cmp hook.expect goozy/hook.actual
'
+test_expect_success '"add" an existing but missing worktree' '
+ git worktree add --detach pneu &&
+ test_must_fail git worktree add --detach pneu &&
+ rm -fr pneu &&
+ test_must_fail git worktree add --detach pneu
+'
+
test_done