diff options
| author | Phillip Wood <phillip.wood@dunelm.org.uk> | 2025-11-18 16:07:33 +0000 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2025-11-18 10:11:29 -0800 |
| commit | 08dfa5983572645ae7cc51b49cadfdf216ecfec6 (patch) | |
| tree | 9bc0e28b9ba3403a9facdadf1a209703adf33fd6 | |
| parent | a6238ee16371247517e39da36782614a229184ff (diff) | |
worktree list: quote paths
If a worktree path contains newlines or other control characters
it messes up the output of "git worktree list". Fix this by using
quote_path() to display the worktree path. The output of "git worktree
list" is designed for human consumption, scripts should be using the
"--porcelain" option so this change should not break them.
Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
| -rw-r--r-- | builtin/worktree.c | 10 | ||||
| -rwxr-xr-x | t/t2402-worktree-list.sh | 15 |
2 files changed, 22 insertions, 3 deletions
diff --git a/builtin/worktree.c b/builtin/worktree.c index 0643a22ee5..303cc3b2d6 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -980,6 +980,7 @@ static void show_worktree_porcelain(struct worktree *wt, int line_terminator) } struct worktree_display { + char *path; int width; }; @@ -989,7 +990,7 @@ static void show_worktree(struct worktree *wt, struct worktree_display *display, struct strbuf sb = STRBUF_INIT; const char *reason; - strbuf_addf(&sb, "%s%*s", wt->path, 1 + path_maxwidth - display->width, ""); + strbuf_addf(&sb, "%s%*s", display->path, 1 + path_maxwidth - display->width, ""); if (wt->is_bare) strbuf_addstr(&sb, "(bare)"); else { @@ -1028,11 +1029,14 @@ static void measure_widths(struct worktree **wt, int *abbrev, { int i, display_alloc = 0; struct worktree_display *display = NULL; + struct strbuf buf = STRBUF_INIT; for (i = 0; wt[i]; i++) { int sha1_len; ALLOC_GROW(display, i + 1, display_alloc); - display[i].width = utf8_strwidth(wt[i]->path); + quote_path(wt[i]->path, NULL, &buf, 0); + display[i].width = utf8_strwidth(buf.buf); + display[i].path = strbuf_detach(&buf, NULL); if (display[i].width > *maxwidth) *maxwidth = display[i].width; @@ -1104,6 +1108,8 @@ static int list(int ac, const char **av, const char *prefix, show_worktree(worktrees[i], &display[i], path_maxwidth, abbrev); } + for (i = 0; display && worktrees[i]; i++) + free(display[i].path); free(display); free_worktrees(worktrees); } diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh index a494df6d61..e0c6abd2f5 100755 --- a/t/t2402-worktree-list.sh +++ b/t/t2402-worktree-list.sh @@ -29,7 +29,8 @@ test_expect_success 'rev-parse --git-path objects linked worktree' ' test_cmp expect actual ' -test_expect_success '"list" all worktrees from main' ' +test_expect_success '"list" all worktrees from main core.quotepath=false' ' + test_config core.quotepath false && echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect && test_when_finished "rm -rf áááá out actual expect && git worktree prune" && git worktree add --detach áááá main && @@ -38,7 +39,19 @@ test_expect_success '"list" all worktrees from main' ' test_cmp expect actual ' +test_expect_success '"list" all worktrees from main core.quotepath=true' ' + test_config core.quotepath true && + echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect && + test_when_finished "rm -rf á out actual expect && git worktree prune" && + git worktree add --detach á main && + echo "\"$(git -C á rev-parse --show-toplevel)\" $(git rev-parse --short HEAD) (detached HEAD)" | + sed s/á/\\\\303\\\\241/g >>expect && + git worktree list >actual && + test_cmp expect actual +' + test_expect_success '"list" all worktrees from linked' ' + test_config core.quotepath false && echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect && test_when_finished "rm -rf áááá out actual expect && git worktree prune" && git worktree add --detach áááá main && |
