The new feature to 'remove' worktree was handy to remove specific worktrees. It didn't cover one particular case of removal. Specifically, if there is an "entry" (a directory in <main_worktree>/.git/worktrees) for a worktree but the worktree repository itself does not exist then it means that the "entry" is stale and it could just be removed. So, in case there's a "worktree entry" but not "worktree direectory" then just remove the 'stale' entry. Signed-off-by: Kaartic Sivaraam <kaartic.sivaraam@xxxxxxxxx> --- Hello Duy, I noticed that your remove command could be enhanced for a particular case. So, I made up an ad-hoc patch "illustrating" how it could be done. I may have broken something by quieting out 'validate_worktree()' function, so take note of it. You might add this as a separate commit or just incorporate it into one of your commits if you re-roll your 'nd/worktree-move' branch. Thanks, Kaartic builtin/worktree.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index b5afba164..f70bc0bd8 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -605,6 +605,22 @@ static int move_worktree(int ac, const char **av, const char *prefix) return update_worktree_location(wt, dst.buf); } +/* Removes the .git/worktrees/worktree_id directory for + the given worktree_id + + Returns 0 on success and non-zero value in case of failure */ +static int remove_worktree_entry(char *worktree_id) { + int ret = 0; + struct strbuf we_path = STRBUF_INIT; + strbuf_addstr(&we_path, git_common_path("worktrees/%s", worktree_id)); + if (remove_dir_recursively(&we_path, 0)) { + error_errno(_("failed to delete '%s'"), we_path.buf); + ret = -1; + } + strbuf_release(&we_path); + return ret; +} + static int remove_worktree(int ac, const char **av, const char *prefix) { int force = 0; @@ -634,9 +650,17 @@ static int remove_worktree(int ac, const char **av, const char *prefix) die(_("already locked, reason: %s"), reason); die(_("already locked, no reason")); } - if (validate_worktree(wt, 0)) - return -1; - + if (validate_worktree(wt, 1)) { + if (!file_exists(wt->path)) { + /* There's a worktree entry but the worktree directory + doesn't exist. So, just remove the worktree entry. */ + ret = remove_worktree_entry(wt->id); + free_worktrees(worktrees); + return ret; + } else { + return -1; + } + } if (!force) { struct argv_array child_env = ARGV_ARRAY_INIT; struct child_process cp; @@ -670,13 +694,7 @@ static int remove_worktree(int ac, const char **av, const char *prefix) error_errno(_("failed to delete '%s'"), sb.buf); ret = -1; } - strbuf_reset(&sb); - strbuf_addstr(&sb, git_common_path("worktrees/%s", wt->id)); - if (remove_dir_recursively(&sb, 0)) { - error_errno(_("failed to delete '%s'"), sb.buf); - ret = -1; - } - strbuf_release(&sb); + ret = remove_worktree_entry(wt->id); free_worktrees(worktrees); return ret; } -- 2.15.0.345.gf926f18f3