@ -20,6 +20,8 @@
@@ -20,6 +20,8 @@
#include "commit-slab.h"
#include "commit-graph.h"
#include "commit-reach.h"
#include "worktree.h"
#include "hashmap.h"
static struct ref_msg {
const char *gone;
@ -75,6 +77,27 @@ static struct expand_data {
@@ -75,6 +77,27 @@ static struct expand_data {
struct object_info info;
} oi, oi_deref;
struct ref_to_worktree_entry {
struct hashmap_entry ent; /* must be the first member! */
struct worktree *wt; /* key is wt->head_ref */
};
static int ref_to_worktree_map_cmpfnc(const void *unused_lookupdata,
const void *existing_hashmap_entry_to_test,
const void *key,
const void *keydata_aka_refname)
{
const struct ref_to_worktree_entry *e = existing_hashmap_entry_to_test;
const struct ref_to_worktree_entry *k = key;
return strcmp(e->wt->head_ref,
keydata_aka_refname ? keydata_aka_refname : k->wt->head_ref);
}
static struct ref_to_worktree_map {
struct hashmap map;
struct worktree **worktrees;
} ref_to_worktree_map;
/*
* An atom is a valid field atom listed below, possibly prefixed with
* a "*" to denote deref_tag().
@ -480,6 +503,7 @@ static struct {
@@ -480,6 +503,7 @@ static struct {
{ "flag", SOURCE_NONE },
{ "HEAD", SOURCE_NONE, FIELD_STR, head_atom_parser },
{ "color", SOURCE_NONE, FIELD_STR, color_atom_parser },
{ "worktreepath", SOURCE_NONE },
{ "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
{ "end", SOURCE_NONE },
{ "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,6 +1553,48 @@ static int get_object(struct ref_array_item *ref, int deref, struct object **obj
return 0;
}
static void populate_worktree_map(struct hashmap *map, struct worktree **worktrees)
{
int i;
for (i = 0; worktrees[i]; i++) {
if (worktrees[i]->head_ref) {
struct ref_to_worktree_entry *entry;
entry = xmalloc(sizeof(*entry));
entry->wt = worktrees[i];
hashmap_entry_init(entry, strhash(worktrees[i]->head_ref));
hashmap_add(map, entry);
}
}
}
static void lazy_init_worktree_map(void)
{
if (ref_to_worktree_map.worktrees)
return;
ref_to_worktree_map.worktrees = get_worktrees(0);
hashmap_init(&(ref_to_worktree_map.map), ref_to_worktree_map_cmpfnc, NULL, 0);
populate_worktree_map(&(ref_to_worktree_map.map), ref_to_worktree_map.worktrees);
}
static char *get_worktree_path(const struct used_atom *atom, const struct ref_array_item *ref)
{
struct hashmap_entry entry;
struct ref_to_worktree_entry *lookup_result;
lazy_init_worktree_map();
hashmap_entry_init(&entry, strhash(ref->refname));
lookup_result = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname);
if (lookup_result)
return xstrdup(lookup_result->wt->path);
else
return xstrdup("");
}
/*
* Parse the object referred by ref, and grab needed value.
*/
@ -1566,6 +1632,13 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
@@ -1566,6 +1632,13 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
if (starts_with(name, "refname"))
refname = get_refname(atom, ref);
else if (!strcmp(name, "worktreepath")) {
if (ref->kind == FILTER_REFS_BRANCHES)
v->s = get_worktree_path(atom, ref);
else
v->s = xstrdup("");
continue;
}
else if (starts_with(name, "symref"))
refname = get_symref(atom, ref);
else if (starts_with(name, "upstream")) {
@ -2049,6 +2122,11 @@ void ref_array_clear(struct ref_array *array)
@@ -2049,6 +2122,11 @@ void ref_array_clear(struct ref_array *array)
free_array_item(array->items[i]);
FREE_AND_NULL(array->items);
array->nr = array->alloc = 0;
if (ref_to_worktree_map.worktrees) {
hashmap_free(&(ref_to_worktree_map.map), 1);
free_worktrees(ref_to_worktree_map.worktrees);
ref_to_worktree_map.worktrees = NULL;
}
}
static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)