From: Nickolai Belakovski <nbelakovski@xxxxxxxxx> Add an atom expressing whether the particular ref is checked out in a linked worktree. Signed-off-by: Nickolai Belakovski <nbelakovski@xxxxxxxxx> --- ref-filter.c | 31 +++++++++++++++++++++++++++++++ t/t6302-for-each-ref-filter.sh | 15 +++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/ref-filter.c b/ref-filter.c index 0c45ed9d94..53e2504f5d 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -20,6 +20,7 @@ #include "commit-slab.h" #include "commit-graph.h" #include "commit-reach.h" +#include "worktree.h" static struct ref_msg { const char *gone; @@ -114,6 +115,7 @@ static struct used_atom { } objectname; struct refname_atom refname; char *head; + struct string_list worktree_heads; } u; } *used_atom; static int used_atom_cnt, need_tagged, need_symref; @@ -420,6 +422,28 @@ static int head_atom_parser(const struct ref_format *format, struct used_atom *a return 0; } +static int worktree_head_atom_parser(const struct ref_format *format, + struct used_atom *atom, + const char *arg, + struct strbuf *unused_err) +{ + struct worktree **worktrees = get_worktrees(0); + int i; + + string_list_init(&atom->u.worktree_heads, 1); + + for (i = 0; worktrees[i]; i++) { + if (worktrees[i]->head_ref) + string_list_append(&atom->u.worktree_heads, + worktrees[i]->head_ref); + } + + string_list_sort(&atom->u.worktree_heads); + + free_worktrees(worktrees); + return 0; +} + static struct { const char *name; info_source source; @@ -461,6 +485,7 @@ static struct { { "flag", SOURCE_NONE }, { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser }, { "color", SOURCE_NONE, FIELD_STR, color_atom_parser }, + { "worktree", SOURCE_NONE, FIELD_STR, worktree_head_atom_parser }, { "align", SOURCE_NONE, FIELD_STR, align_atom_parser }, { "end", SOURCE_NONE }, { "if", SOURCE_NONE, FIELD_STR, if_atom_parser }, @@ -1594,6 +1619,12 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) else v->s = xstrdup(" "); continue; + } else if (!strcmp(name, "worktree")) { + if (string_list_has_string(&atom->u.worktree_heads, ref->refname)) + v->s = xstrdup("+"); + else + v->s = xstrdup(" "); + continue; } else if (starts_with(name, "align")) { v->handler = align_atom_handler; v->s = xstrdup(""); diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index fc067ed672..5e6d249d4c 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -441,4 +441,19 @@ test_expect_success '--merged is incompatible with --no-merged' ' test_must_fail git for-each-ref --merged HEAD --no-merged HEAD ' +test_expect_success '"add" a worktree' ' + mkdir worktree_dir && + git worktree add -b master_worktree worktree_dir master +' + +test_expect_success 'validate worktree atom' ' + cat >expect <<-\EOF && + master: checked out in a worktree + master_worktree: checked out in a worktree + side: not checked out in a worktree +EOF + git for-each-ref --format="%(refname:short): %(if)%(worktree)%(then)checked out in a worktree%(else)not checked out in a worktree%(end)" refs/heads/ >actual && + test_cmp expect actual +' + test_done -- 2.14.2