|
20 | 20 | #include "commit-slab.h"
|
21 | 21 | #include "commit-graph.h"
|
22 | 22 | #include "commit-reach.h"
|
| 23 | +#include "worktree.h" |
| 24 | +#include "hashmap.h" |
23 | 25 |
|
24 | 26 | static struct ref_msg {
|
25 | 27 | const char *gone;
|
@@ -75,6 +77,27 @@ static struct expand_data {
|
75 | 77 | struct object_info info;
|
76 | 78 | } oi, oi_deref;
|
77 | 79 |
|
| 80 | +struct ref_to_worktree_entry { |
| 81 | + struct hashmap_entry ent; /* must be the first member! */ |
| 82 | + struct worktree *wt; /* key is wt->head_ref */ |
| 83 | +}; |
| 84 | + |
| 85 | +static int ref_to_worktree_map_cmpfnc(const void *unused_lookupdata, |
| 86 | + const void *existing_hashmap_entry_to_test, |
| 87 | + const void *key, |
| 88 | + const void *keydata_aka_refname) |
| 89 | +{ |
| 90 | + const struct ref_to_worktree_entry *e = existing_hashmap_entry_to_test; |
| 91 | + const struct ref_to_worktree_entry *k = key; |
| 92 | + return strcmp(e->wt->head_ref, |
| 93 | + keydata_aka_refname ? keydata_aka_refname : k->wt->head_ref); |
| 94 | +} |
| 95 | + |
| 96 | +static struct ref_to_worktree_map { |
| 97 | + struct hashmap map; |
| 98 | + struct worktree **worktrees; |
| 99 | +} ref_to_worktree_map; |
| 100 | + |
78 | 101 | /*
|
79 | 102 | * An atom is a valid field atom listed below, possibly prefixed with
|
80 | 103 | * a "*" to denote deref_tag().
|
@@ -480,6 +503,7 @@ static struct {
|
480 | 503 | { "flag", SOURCE_NONE },
|
481 | 504 | { "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
|
482 | 505 | { "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
|
| 506 | + { "worktreepath", SOURCE_NONE }, |
483 | 507 | { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
|
484 | 508 | { "end", SOURCE_NONE },
|
485 | 509 | { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
|
@@ -1529,6 +1553,48 @@ static int get_object(struct ref_array_item *ref, int deref, struct object **obj
|
1529 | 1553 | return 0;
|
1530 | 1554 | }
|
1531 | 1555 |
|
| 1556 | +static void populate_worktree_map(struct hashmap *map, struct worktree **worktrees) |
| 1557 | +{ |
| 1558 | + int i; |
| 1559 | + |
| 1560 | + for (i = 0; worktrees[i]; i++) { |
| 1561 | + if (worktrees[i]->head_ref) { |
| 1562 | + struct ref_to_worktree_entry *entry; |
| 1563 | + entry = xmalloc(sizeof(*entry)); |
| 1564 | + entry->wt = worktrees[i]; |
| 1565 | + hashmap_entry_init(entry, strhash(worktrees[i]->head_ref)); |
| 1566 | + |
| 1567 | + hashmap_add(map, entry); |
| 1568 | + } |
| 1569 | + } |
| 1570 | +} |
| 1571 | + |
| 1572 | +static void lazy_init_worktree_map(void) |
| 1573 | +{ |
| 1574 | + if (ref_to_worktree_map.worktrees) |
| 1575 | + return; |
| 1576 | + |
| 1577 | + ref_to_worktree_map.worktrees = get_worktrees(0); |
| 1578 | + hashmap_init(&(ref_to_worktree_map.map), ref_to_worktree_map_cmpfnc, NULL, 0); |
| 1579 | + populate_worktree_map(&(ref_to_worktree_map.map), ref_to_worktree_map.worktrees); |
| 1580 | +} |
| 1581 | + |
| 1582 | +static char *get_worktree_path(const struct used_atom *atom, const struct ref_array_item *ref) |
| 1583 | +{ |
| 1584 | + struct hashmap_entry entry; |
| 1585 | + struct ref_to_worktree_entry *lookup_result; |
| 1586 | + |
| 1587 | + lazy_init_worktree_map(); |
| 1588 | + |
| 1589 | + hashmap_entry_init(&entry, strhash(ref->refname)); |
| 1590 | + lookup_result = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname); |
| 1591 | + |
| 1592 | + if (lookup_result) |
| 1593 | + return xstrdup(lookup_result->wt->path); |
| 1594 | + else |
| 1595 | + return xstrdup(""); |
| 1596 | +} |
| 1597 | + |
1532 | 1598 | /*
|
1533 | 1599 | * Parse the object referred by ref, and grab needed value.
|
1534 | 1600 | */
|
@@ -1566,6 +1632,13 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
|
1566 | 1632 |
|
1567 | 1633 | if (starts_with(name, "refname"))
|
1568 | 1634 | refname = get_refname(atom, ref);
|
| 1635 | + else if (!strcmp(name, "worktreepath")) { |
| 1636 | + if (ref->kind == FILTER_REFS_BRANCHES) |
| 1637 | + v->s = get_worktree_path(atom, ref); |
| 1638 | + else |
| 1639 | + v->s = xstrdup(""); |
| 1640 | + continue; |
| 1641 | + } |
1569 | 1642 | else if (starts_with(name, "symref"))
|
1570 | 1643 | refname = get_symref(atom, ref);
|
1571 | 1644 | else if (starts_with(name, "upstream")) {
|
@@ -2049,6 +2122,11 @@ void ref_array_clear(struct ref_array *array)
|
2049 | 2122 | free_array_item(array->items[i]);
|
2050 | 2123 | FREE_AND_NULL(array->items);
|
2051 | 2124 | array->nr = array->alloc = 0;
|
| 2125 | + if (ref_to_worktree_map.worktrees) { |
| 2126 | + hashmap_free(&(ref_to_worktree_map.map), 1); |
| 2127 | + free_worktrees(ref_to_worktree_map.worktrees); |
| 2128 | + ref_to_worktree_map.worktrees = NULL; |
| 2129 | + } |
2052 | 2130 | }
|
2053 | 2131 |
|
2054 | 2132 | static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
|
|
0 commit comments