Merge branch 'nb/branch-show-other-worktrees-head'
"git branch --list" learned to show branches that are checked out in other worktrees connected to the same repository prefixed with '+', similar to the way the currently checked out branch is shown with '*' in front. * nb/branch-show-other-worktrees-head: branch: add worktree info on verbose output branch: update output to include worktree info ref-filter: add worktreepath atom
This commit is contained in:
78
ref-filter.c
78
ref-filter.c
@ -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 {
|
||||
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 {
|
||||
{ "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 },
|
||||
@ -1531,6 +1555,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.
|
||||
*/
|
||||
@ -1568,6 +1634,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")) {
|
||||
@ -2051,6 +2124,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)
|
||||
|
||||
Reference in New Issue
Block a user