From e19831c94f91fd410fe001c0372b9c88b40d335b Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Tue, 28 Aug 2018 17:20:23 -0400 Subject: worktree: teach 'add' to respect --force for registered but missing path For safety, "git worktree add " will refuse to add a new worktree at if is already associated with a worktree entry, even if is missing (for instance, has been deleted or resides on non-mounted removable media or network share). The typical way to re-create a worktree at in such a situation is either to prune all "broken" entries ("git worktree prune") or to selectively remove the worktree entry manually ("git worktree remove "). However, neither of these approaches ("prune" nor "remove") is especially convenient, and they may be unsuitable for scripting when a tool merely wants to re-use a worktree if it exists or create it from scratch if it doesn't (much as a tool might use "mkdir -p" to re-use or create a directory). Therefore, teach 'add' to respect --force as a convenient way to re-use a path already associated with a worktree entry if the path is non-existent. For a locked worktree, require --force to be specified twice. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 29a5b7e252..8537692f05 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -120,8 +120,12 @@ OPTIONS --force:: By default, `add` refuses to create a new working tree when `` is a branch name and is already checked out by - another working tree and `remove` refuses to remove an unclean - working tree. This option overrides these safeguards. + another working tree, or if `` is already assigned to some + working tree but is missing (for instance, if `` was deleted + manually). This option overrides these safeguards. To add a missing but + locked working tree path, specify `--force` twice. ++ +`remove` refuses to remove an unclean working tree unless `--force` is used. -b :: -B :: -- cgit v1.3-5-g9baa From 68a6b3a1bd45eb1814a0c1cedfe347692c3f2ff7 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Tue, 28 Aug 2018 17:20:24 -0400 Subject: worktree: teach 'move' to override lock when --force given twice For consistency with "add -f -f", which allows a missing but locked worktree path to be re-used, allow "move -f -f" to override a lock, as well, as a convenience. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 3 +++ builtin/worktree.c | 13 +++++++++---- t/t2028-worktree-move.sh | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 8537692f05..d08b8d8e4f 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -125,6 +125,9 @@ OPTIONS manually). This option overrides these safeguards. To add a missing but locked working tree path, specify `--force` twice. + +`move` refuses to move a locked working tree unless `--force` is specified +twice. ++ `remove` refuses to remove an unclean working tree unless `--force` is used. -b :: diff --git a/builtin/worktree.c b/builtin/worktree.c index 3eb2f89b0f..354a6c0eb5 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -740,13 +740,17 @@ static void validate_no_submodules(const struct worktree *wt) static int move_worktree(int ac, const char **av, const char *prefix) { + int force = 0; struct option options[] = { + OPT__FORCE(&force, + N_("force move even if worktree is dirty or locked"), + PARSE_OPT_NOCOMPLETE), OPT_END() }; struct worktree **worktrees, *wt; struct strbuf dst = STRBUF_INIT; struct strbuf errmsg = STRBUF_INIT; - const char *reason; + const char *reason = NULL; char *path; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); @@ -777,12 +781,13 @@ static int move_worktree(int ac, const char **av, const char *prefix) validate_no_submodules(wt); - reason = is_worktree_locked(wt); + if (force < 2) + reason = is_worktree_locked(wt); if (reason) { if (*reason) - die(_("cannot move a locked working tree, lock reason: %s"), + die(_("cannot move a locked working tree, lock reason: %s\nuse 'move -f -f' to override or unlock first"), reason); - die(_("cannot move a locked working tree")); + die(_("cannot move a locked working tree;\nuse 'move -f -f' to override or unlock first")); } if (validate_worktree(wt, &errmsg, 0)) die(_("validation failed, cannot move working tree: %s"), diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh index 60aba7c41a..9756ede8f1 100755 --- a/t/t2028-worktree-move.sh +++ b/t/t2028-worktree-move.sh @@ -98,6 +98,20 @@ test_expect_success 'move worktree to another dir' ' test_cmp expected2 actual2 ' +test_expect_success 'move locked worktree (force)' ' + test_when_finished " + git worktree unlock flump || : + git worktree remove flump || : + git worktree unlock ploof || : + git worktree remove ploof || : + " && + git worktree add --detach flump && + git worktree lock flump && + test_must_fail git worktree move flump ploof" && + test_must_fail git worktree move --force flump ploof" && + git worktree move --force --force flump ploof +' + test_expect_success 'remove main worktree' ' test_must_fail git worktree remove . ' -- cgit v1.3-5-g9baa From f4143101cbb26d189f63f2d29875f4acc07b2730 Mon Sep 17 00:00:00 2001 From: Eric Sunshine Date: Tue, 28 Aug 2018 17:20:25 -0400 Subject: worktree: teach 'remove' to override lock when --force given twice For consistency with "add -f -f" and "move -f -f" which override the lock on a worktree, allow "remove -f -f" to do so, as well, as a convenience. Signed-off-by: Eric Sunshine Signed-off-by: Junio C Hamano --- Documentation/git-worktree.txt | 1 + builtin/worktree.c | 11 ++++++----- t/t2028-worktree-move.sh | 10 ++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index d08b8d8e4f..e2ee9fc21b 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -129,6 +129,7 @@ OPTIONS twice. + `remove` refuses to remove an unclean working tree unless `--force` is used. +To remove a locked working tree, specify `--force` twice. -b :: -B :: diff --git a/builtin/worktree.c b/builtin/worktree.c index 354a6c0eb5..a95fe67da6 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -875,13 +875,13 @@ static int remove_worktree(int ac, const char **av, const char *prefix) int force = 0; struct option options[] = { OPT__FORCE(&force, - N_("force removing even if the worktree is dirty"), + N_("force removal even if worktree is dirty or locked"), PARSE_OPT_NOCOMPLETE), OPT_END() }; struct worktree **worktrees, *wt; struct strbuf errmsg = STRBUF_INIT; - const char *reason; + const char *reason = NULL; int ret = 0; ac = parse_options(ac, av, prefix, options, worktree_usage, 0); @@ -894,12 +894,13 @@ static int remove_worktree(int ac, const char **av, const char *prefix) die(_("'%s' is not a working tree"), av[0]); if (is_main_worktree(wt)) die(_("'%s' is a main working tree"), av[0]); - reason = is_worktree_locked(wt); + if (force < 2) + reason = is_worktree_locked(wt); if (reason) { if (*reason) - die(_("cannot remove a locked working tree, lock reason: %s"), + die(_("cannot remove a locked working tree, lock reason: %s\nuse 'remove -f -f' to override or unlock first"), reason); - die(_("cannot remove a locked working tree")); + die(_("cannot remove a locked working tree;\nuse 'remove -f -f' to override or unlock first")); } if (validate_worktree(wt, &errmsg, WT_VALIDATE_WORKTREE_MISSING_OK)) die(_("validation failed, cannot remove working tree: %s"), diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh index 9756ede8f1..1b5079e8fa 100755 --- a/t/t2028-worktree-move.sh +++ b/t/t2028-worktree-move.sh @@ -163,4 +163,14 @@ test_expect_success 'proper error when worktree not found' ' done ' +test_expect_success 'remove locked worktree (force)' ' + git worktree add --detach gumby && + test_when_finished "git worktree remove gumby || :" && + git worktree lock gumby && + test_when_finished "git worktree unlock gumby || :" && + test_must_fail git worktree remove gumby && + test_must_fail git worktree remove --force gumby && + git worktree remove --force --force gumby +' + test_done -- cgit v1.3-5-g9baa From 684e742249b48ec0c5491a98fa3b1427793738ce Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 30 Aug 2018 03:54:31 -0400 Subject: doc-diff: force worktree add We avoid re-creating our temporary worktree if it's already there. But we may run into a situation where the worktree has been deleted, but an entry still exists in $GIT_DIR/worktrees. Older versions of git-worktree would annoyingly create a series of duplicate entries. Recent versions now detect and prevent this, allowing you to override with "-f". Since we know that the worktree in question was just our temporary workspace, it's safe for us to always pass "-f". Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Documentation/doc-diff | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/doc-diff b/Documentation/doc-diff index f483fe427c..19d841ddeb 100755 --- a/Documentation/doc-diff +++ b/Documentation/doc-diff @@ -54,7 +54,7 @@ fi # results that don't differ between the two trees. if ! test -d "$tmp/worktree" then - git worktree add --detach "$tmp/worktree" "$from" && + git worktree add -f --detach "$tmp/worktree" "$from" && dots=$(echo "$tmp/worktree" | sed 's#[^/]*#..#g') && ln -s "$dots/config.mak" "$tmp/worktree/config.mak" fi -- cgit v1.3-5-g9baa