Skip to content

Commit 105df73

Browse files
pcloudsgitster
authored andcommitted
worktree add: be tolerant of corrupt worktrees
find_worktree() can die() unexpectedly because it uses real_path() instead of the gentler version. When it's used in 'git worktree add' [1] and there's a bad worktree, this die() could prevent people from adding new worktrees. The "bad" condition to trigger this is when a parent of the worktree's location is deleted. Then real_path() will complain. Use the other version so that bad worktrees won't affect 'worktree add'. The bad ones will eventually be pruned, we just have to tolerate them for a bit. [1] added in cb56f55 (worktree: disallow adding same path multiple times, 2018-08-28), or since v2.20.0. Though the real bug in find_worktree() is much older. Reported-by: Shaheed Haque <[email protected]> Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent aeb582a commit 105df73

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

t/t2025-worktree-add.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,4 +570,16 @@ test_expect_success '"add" an existing locked but missing worktree' '
570570
git worktree add --force --force --detach gnoo
571571
'
572572

573+
test_expect_success '"add" should not fail because of another bad worktree' '
574+
git init add-fail &&
575+
(
576+
cd add-fail &&
577+
test_commit first &&
578+
mkdir sub &&
579+
git worktree add sub/to-be-deleted &&
580+
rm -rf sub &&
581+
git worktree add second
582+
)
583+
'
584+
573585
test_done

worktree.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,12 @@ struct worktree *find_worktree(struct worktree **list,
222222
free(to_free);
223223
return NULL;
224224
}
225-
for (; *list; list++)
226-
if (!fspathcmp(path, real_path((*list)->path)))
225+
for (; *list; list++) {
226+
const char *wt_path = real_path_if_valid((*list)->path);
227+
228+
if (wt_path && !fspathcmp(path, wt_path))
227229
break;
230+
}
228231
free(path);
229232
free(to_free);
230233
return *list;

0 commit comments

Comments
 (0)