From: Nickolai Belakovski <nbelakov...@gmail.com>

Add an atom expressing whether the particular ref is checked out in a
linked worktree.

Signed-off-by: Nickolai Belakovski <nbelakov...@gmail.com>
---
 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

Reply via email to