worktree: don't die() in library function find_worktree()

Callers don't expect library function find_worktree() to die(); they expect it to return the named worktree if found, or NULL if not. Although find_worktree() itself never invokes die(), it calls real_pathdup() with 'die_on_error' incorrectly set to 'true', thus will die() indirectly if the user-provided path is not to real_pathdup()'s liking. This can be observed, for instance, with any git-worktree command which searches for an existing worktree: $ git worktree unlock foo fatal: 'foo' is not a working tree $ git worktree unlock foo/bar fatal: Invalid path '.../foo': No such file or directory The first error message is the expected one from "git worktree unlock" not finding the specified worktree; the second is from find_worktree() invoking real_pathdup() incorrectly and die()ing prematurely. Aside from the inconsistent error message between the two cases, this bug hasn't otherwise been a serious problem since existing callers all die() anyhow when the worktree can't be found. However, that may not be true of callers added in the future, so fix find_worktree() to avoid die()ing. Signed-off-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Eric Sunshine committed Aug 28, 2018 at 17:20 UTC 4c5fa9e6c4091eea9d8df3466b18ddb2812cd934
2 files changed +13 -1
t/t2028-worktree-move.sh
+8
@@ -141,4 +141,12 @@ test_expect_success 'NOT remove missing-but-locked worktree' '
141 test_path_is_dir .git/worktrees/gone-but-locked
142 '
143
144 +test_expect_success 'proper error when worktree not found' '
145 + for i in noodle noodle/bork
146 + do
147 + test_must_fail git worktree lock $i 2>err &&
148 + test_i18ngrep "not a working tree" err || return 1
149 + done
150 +'
151 +
152 test_done
worktree.c
+5 -1
@@ -217,7 +217,11 @@ struct worktree *find_worktree(struct worktree **list,
217
218 if (prefix)
219 arg = to_free = prefix_filename(prefix, arg);
220 - path = real_pathdup(arg, 1);
220 + path = real_pathdup(arg, 0);
221 + if (!path) {
222 + free(to_free);
223 + return NULL;
224 + }
225 for (; *list; list++)
226 if (!fspathcmp(path, real_path((*list)->path)))
227 break;