mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
Merge branch 'pw/worktree-list-display-width-fix'
"git worktree list" attempts to show paths to worktrees while aligning them, but miscounted display columns for the paths when non-ASCII characters were involved, which has been corrected. * pw/worktree-list-display-width-fix: worktree list: quote paths worktree list: fix column spacing
This commit is contained in:
@@ -975,14 +975,18 @@ static void show_worktree_porcelain(struct worktree *wt, int line_terminator)
|
|||||||
fputc(line_terminator, stdout);
|
fputc(line_terminator, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
|
struct worktree_display {
|
||||||
|
char *path;
|
||||||
|
int width;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void show_worktree(struct worktree *wt, struct worktree_display *display,
|
||||||
|
int path_maxwidth, int abbrev_len)
|
||||||
{
|
{
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
int cur_path_len = strlen(wt->path);
|
|
||||||
int path_adj = cur_path_len - utf8_strwidth(wt->path);
|
|
||||||
const char *reason;
|
const char *reason;
|
||||||
|
|
||||||
strbuf_addf(&sb, "%-*s ", 1 + path_maxlen + path_adj, wt->path);
|
strbuf_addf(&sb, "%s%*s", display->path, 1 + path_maxwidth - display->width, "");
|
||||||
if (wt->is_bare)
|
if (wt->is_bare)
|
||||||
strbuf_addstr(&sb, "(bare)");
|
strbuf_addstr(&sb, "(bare)");
|
||||||
else {
|
else {
|
||||||
@@ -1016,20 +1020,27 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
|
|||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void measure_widths(struct worktree **wt, int *abbrev, int *maxlen)
|
static void measure_widths(struct worktree **wt, int *abbrev,
|
||||||
|
struct worktree_display **d, int *maxwidth)
|
||||||
{
|
{
|
||||||
int i;
|
int i, display_alloc = 0;
|
||||||
|
struct worktree_display *display = NULL;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
for (i = 0; wt[i]; i++) {
|
for (i = 0; wt[i]; i++) {
|
||||||
int sha1_len;
|
int sha1_len;
|
||||||
int path_len = strlen(wt[i]->path);
|
ALLOC_GROW(display, i + 1, display_alloc);
|
||||||
|
quote_path(wt[i]->path, NULL, &buf, 0);
|
||||||
|
display[i].width = utf8_strwidth(buf.buf);
|
||||||
|
display[i].path = strbuf_detach(&buf, NULL);
|
||||||
|
|
||||||
if (path_len > *maxlen)
|
if (display[i].width > *maxwidth)
|
||||||
*maxlen = path_len;
|
*maxwidth = display[i].width;
|
||||||
sha1_len = strlen(repo_find_unique_abbrev(the_repository, &wt[i]->head_oid, *abbrev));
|
sha1_len = strlen(repo_find_unique_abbrev(the_repository, &wt[i]->head_oid, *abbrev));
|
||||||
if (sha1_len > *abbrev)
|
if (sha1_len > *abbrev)
|
||||||
*abbrev = sha1_len;
|
*abbrev = sha1_len;
|
||||||
}
|
}
|
||||||
|
*d = display;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pathcmp(const void *a_, const void *b_)
|
static int pathcmp(const void *a_, const void *b_)
|
||||||
@@ -1075,21 +1086,27 @@ static int list(int ac, const char **av, const char *prefix,
|
|||||||
die(_("the option '%s' requires '%s'"), "-z", "--porcelain");
|
die(_("the option '%s' requires '%s'"), "-z", "--porcelain");
|
||||||
else {
|
else {
|
||||||
struct worktree **worktrees = get_worktrees();
|
struct worktree **worktrees = get_worktrees();
|
||||||
int path_maxlen = 0, abbrev = DEFAULT_ABBREV, i;
|
int path_maxwidth = 0, abbrev = DEFAULT_ABBREV, i;
|
||||||
|
struct worktree_display *display = NULL;
|
||||||
|
|
||||||
/* sort worktrees by path but keep main worktree at top */
|
/* sort worktrees by path but keep main worktree at top */
|
||||||
pathsort(worktrees + 1);
|
pathsort(worktrees + 1);
|
||||||
|
|
||||||
if (!porcelain)
|
if (!porcelain)
|
||||||
measure_widths(worktrees, &abbrev, &path_maxlen);
|
measure_widths(worktrees, &abbrev,
|
||||||
|
&display, &path_maxwidth);
|
||||||
|
|
||||||
for (i = 0; worktrees[i]; i++) {
|
for (i = 0; worktrees[i]; i++) {
|
||||||
if (porcelain)
|
if (porcelain)
|
||||||
show_worktree_porcelain(worktrees[i],
|
show_worktree_porcelain(worktrees[i],
|
||||||
line_terminator);
|
line_terminator);
|
||||||
else
|
else
|
||||||
show_worktree(worktrees[i], path_maxlen, abbrev);
|
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);
|
free_worktrees(worktrees);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -29,23 +29,34 @@ test_expect_success 'rev-parse --git-path objects linked worktree' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '"list" all worktrees from main' '
|
test_expect_success '"list" all worktrees from main core.quotepath=false' '
|
||||||
echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
|
test_config core.quotepath false &&
|
||||||
test_when_finished "rm -rf here out actual expect && git worktree prune" &&
|
echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
|
||||||
git worktree add --detach here main &&
|
test_when_finished "rm -rf áááá out actual expect && git worktree prune" &&
|
||||||
echo "$(git -C here rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >>expect &&
|
git worktree add --detach áááá main &&
|
||||||
git worktree list >out &&
|
echo "$(git -C áááá rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >>expect &&
|
||||||
sed "s/ */ /g" <out >actual &&
|
git worktree list >actual &&
|
||||||
|
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_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '"list" all worktrees from linked' '
|
test_expect_success '"list" all worktrees from linked' '
|
||||||
echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
|
test_config core.quotepath false &&
|
||||||
test_when_finished "rm -rf here out actual expect && git worktree prune" &&
|
echo "$(git rev-parse --show-toplevel) $(git rev-parse --short HEAD) [$(git symbolic-ref --short HEAD)]" >expect &&
|
||||||
git worktree add --detach here main &&
|
test_when_finished "rm -rf áááá out actual expect && git worktree prune" &&
|
||||||
echo "$(git -C here rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >>expect &&
|
git worktree add --detach áááá main &&
|
||||||
git -C here worktree list >out &&
|
echo "$(git -C áááá rev-parse --show-toplevel) $(git rev-parse --short HEAD) (detached HEAD)" >>expect &&
|
||||||
sed "s/ */ /g" <out >actual &&
|
git -C áááá worktree list >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user