From: Jeff King <peff@peff.net>
To: nbelakovski@gmail.com
Cc: git@vger.kernel.org, rafa.almas@gmail.com, gitster@pobox.com,
avarab@gmail.com
Subject: Re: [PATCH v3 1/3] ref-filter: add worktreepath atom
Date: Tue, 18 Dec 2018 12:22:37 -0500 [thread overview]
Message-ID: <20181218172236.GA28455@sigill.intra.peff.net> (raw)
In-Reply-To: <20181216215759.24011-2-nbelakovski@gmail.com>
On Sun, Dec 16, 2018 at 01:57:57PM -0800, nbelakovski@gmail.com wrote:
> From: Nickolai Belakovski <nbelakovski@gmail.com>
>
> Add an atom proving the path of the linked worktree where this ref is
> checked out, if it is checked out in any linked worktrees, and empty
> string otherwise.
I stumbled over the word "proving" here. Maybe "showing" would be more
clear?
> diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
> index 901faef1bf..9590f7beab 100644
> --- a/Documentation/git-for-each-ref.txt
> +++ b/Documentation/git-for-each-ref.txt
> @@ -209,6 +209,10 @@ symref::
> `:lstrip` and `:rstrip` options in the same way as `refname`
> above.
>
> +worktreepath::
> + The absolute path to the worktree in which the ref is checked
> + out, if it is checked out in any linked worktree. ' ' otherwise.
> +
Normally single-quotes are used in asciidoc to emphasize text, and the
quotes aren't passed through. Asciidoc (and asciidoctor) do seem to
render the literal quotes here, which is good. I wonder if it would be
more clear to just write it out, though, like:
...any linked worktree. Otherwise, replaced with a single space.
Also, why are we replacing it with a single space? Wouldn't the empty
string be more customary (and work with the other "if empty, then do
this" formatting options)?
> @@ -34,6 +36,8 @@ static struct ref_msg {
> "ahead %d, behind %d"
> };
>
> +static struct worktree ** worktrees;
Minor style nit: we put the "*" in a pointer declaration next to the
variable name, without intervening whitespace. Like:
static struct worktree **worktrees;
> @@ -75,6 +79,12 @@ static struct expand_data {
> struct object_info info;
> } oi, oi_deref;
>
> +struct reftoworktreeinfo_entry {
> + struct hashmap_entry ent; // must be the first member!
> + char * ref; // key into map
> + struct worktree * wt;
> +};
A few style nits:
- the "*" space thing from above (it's in other places below, too, but
I won't point out each)
- we prefer "/* */" comments, even for single-liners
- since we do all-lowercase identifiers, use more underscores to break
things up. E.g., ref_to_worktree_entry.
Here we store the refname as a separate variable, but then point to the
worktree itself to access wt->path. Why do we treat these differently?
I.e., I'd expect to see either:
1. Each entry holding a single worktree object, and using its head_ref
and path fields, like:
struct ref_to_worktree_entry {
struct hashmap_entry ent; /* must be first */
struct worktree *wt;
};
....
entry = xmalloc(sizeof(*entry));
entry->wt = wt;
hashmap_entry_init(entry, strhash(wt->head_ref));
...
strbuf_addstr(&out, result->wt->path);
2. Each entry containing just the bits it needs, like:
struct ref_to_worktree_entry {
struct hashmap_entry ent; /* must be first */
char *ref;
char *path;
};
...
/*
* We could use FLEXPTR_ALLOC_STR() here, but it doesn't actually
* support holding _two_ strings. Separate allocations probably
* aren't a huge deal here, since there are only a handful of
* worktrees.
*/
entry = xmalloc(sizeof(*entry));
entry->ref = wt->head_ref;
entry->path = wt->path;
hashmap_entry_init(entry, strhash(entry->ref));
...
strbuf_addstr(&out, result->path);
I think the first one is strictly preferable unless we're worried about
the lifetime of the "struct worktree" going away. I don't think that's
an issue, though; they are ours until we call free_worktrees().
> @@ -114,6 +124,7 @@ static struct used_atom {
> } objectname;
> struct refname_atom refname;
> char *head;
> + struct hashmap reftoworktreeinfo_map;
> } u;
> } *used_atom;
This uses one map for each %(worktree) we use. But won't they all be the
same? It would ideally be associated with the ref-filter. There's no
ref-filter context struct to hold this kind of data, just static globals
in ref-filter.c (including this used_atom struct!). That's something
we'll probably need to fix in the long run, but I think it would be
reasonable to just have:
static struct hashmap ref_to_worktree_map;
next to the declaration of used_atom_cnt, need_symref, etc. And then
those can all eventually get moved into a struct together.
> @@ -461,6 +497,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, FIELD_STR, worktree_atom_parser },
> { "align", SOURCE_NONE, FIELD_STR, align_atom_parser },
> { "end", SOURCE_NONE },
> { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
Marking as SOURCE_NONE makes sense.
> +static const char * get_worktree_info(const struct used_atom *atom, const struct ref_array_item *ref)
> +{
> + struct strbuf val = STRBUF_INIT;
> + struct reftoworktreeinfo_entry * entry;
> + struct reftoworktreeinfo_entry * lookup_result;
> +
> + FLEXPTR_ALLOC_STR(entry, ref, ref->refname);
> + hashmap_entry_init(entry, strhash(entry->ref));
> + lookup_result = hashmap_get(&(atom->u.reftoworktreeinfo_map), entry, NULL);
> + free(entry);
We shouldn't need to do an allocation just for a lookup. That's what the
extra "keydata" parameter is for in the comparison function. And I guess
this is what led you to have "char *ref" in the struct, rather than
reusing wt->head_ref (because you don't have a "struct worktree" here).
You should be able to do it like this:
struct hashmap_entry entry;
struct ref_to_worktree_entry *result;
hashmap_entry_init(entry, strhash(ref->refname));
result = hashmap_get(&ref_to_worktree_map, &entry, ref->refname));
...
and then your comparison function would look like this:
int ref_to_worktree_hashcmp(const void *data,
const void *entry,
const void *entry_or_key,
const void *keydata)
{
const struct ref_to_worktree_entry *a = entry;
const struct ref_to_worktree_entry *b = entry;
if (keydata)
return strcmp(a->wt->head_ref, keydata);
else
return strcmp(a->wt->head_ref, b->wt->head_ref);
}
If you're thinking that this API is totally confusing and hard to figure
out, I agree. It's optimized to avoid extra allocations. I wish we had a
better one for simple cases (especially string->string mappings like
this).
Speaking of comparison functions, I didn't see one in your patch. Don't
you need to pass one to hashmap_init?
> + if (lookup_result)
> + {
> + if (!strncmp(atom->name, "worktreepath", strlen(atom->name)))
> + strbuf_addstr(&val, lookup_result->wt->path);
> + }
> + else
> + strbuf_addstr(&val, " ");
What's this extra strncmp about? If we're _not_ a worktreepath atom,
we'd still do the lookup only to put nothing in the string?
I think we'd only call this function when populate_value() sees a
worktreepath atom, though:
> @@ -1537,6 +1596,10 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
>
> if (starts_with(name, "refname"))
> refname = get_refname(atom, ref);
> + else if (starts_with(name, "worktreepath")) {
> + v->s = get_worktree_info(atom, ref);
> + continue;
> + }
So it would be OK to drop the check of atom->name again inside
get_worktree_info().
> @@ -2013,7 +2076,14 @@ void ref_array_clear(struct ref_array *array)
> int i;
>
> for (i = 0; i < used_atom_cnt; i++)
> + {
> + if (!strncmp(used_atom[i].name, "worktreepath", strlen("worktreepath")))
> + {
> + hashmap_free(&(used_atom[i].u.reftoworktreeinfo_map), 1);
> + free_worktrees(worktrees);
> + }
And if we move the mapping out to a static global, then this only has to
be done once, not once per atom. In fact, I think this could double-free
"worktrees" with your current patch if you have two "%(worktree)"
placeholders, since "worktrees" already is a global.
> diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
> index fc067ed672..add70a4c3e 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)%(worktreepath)%(then)checked out in a worktree%(else)not checked out in a worktree%(end)" refs/heads/ >actual &&
> + test_cmp expect actual
> +'
It's probably worth testing that the path we get is actually sane, too.
I.e., expect something more like:
cat >expect <<-\EOF
master: $PWD
master: $PWD/worktree
side: not checked out
EOF
git for-each-ref \
--format="%(refname:short): %(if)%(worktreepath)%(then)%(worktreepath)%(else)not checked %out%(end)
(I wish there was a way to avoid that really long line, but I don't
think there is).
-Peff
next prev parent reply other threads:[~2018-12-18 17:22 UTC|newest]
Thread overview: 125+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <"<CAC05386q2iGoiJ_fRgwoOTF23exEN2D1+oh4VjajEvYQ58O1TQ@mail.gmail.com>
2018-09-27 15:13 ` [PATCH] branch: colorize branches checked out in a linked working tree the same way as the current branch is colorized Nickolai Belakovski
2018-09-27 15:33 ` Ævar Arnfjörð Bjarmason
2018-09-27 17:46 ` Nickolai Belakovski
[not found] ` <CAC05387S9P+w8yqqcjkQDnURYSgQmqtukxS4KvqJu-kDA+_o0g@mail.gmail.com>
2018-09-27 17:59 ` Ævar Arnfjörð Bjarmason
2018-10-02 20:41 ` Johannes Schindelin
2018-09-27 17:58 ` Duy Nguyen
2018-09-27 18:17 ` Jeff King
2018-09-27 18:39 ` Nickolai Belakovski
2018-09-27 18:51 ` Jeff King
2018-09-27 19:28 ` Rafael Ascensão
2018-09-27 19:35 ` Jeff King
2018-09-27 19:41 ` Jeff King
2018-09-27 21:22 ` Junio C Hamano
2018-09-28 1:05 ` Jeff King
2018-09-28 1:28 ` Junio C Hamano
2018-09-27 21:35 ` Rafael Ascensão
2018-09-28 1:07 ` Jeff King
2018-09-27 20:02 ` Ævar Arnfjörð Bjarmason
2018-09-27 20:16 ` Nickolai Belakovski
2018-09-27 20:40 ` Rafael Ascensão
2018-11-11 23:58 ` [PATCH v2 0/2] refactoring branch colorization to ref-filter nbelakovski
2018-11-11 23:58 ` [PATCH v2 1/2] ref-filter: add worktree atom nbelakovski
2018-11-12 10:11 ` Junio C Hamano
2018-11-12 12:22 ` Jeff King
2018-11-13 1:38 ` Junio C Hamano
2018-11-21 14:05 ` Nickolai Belakovski
2018-11-21 14:08 ` Jeff King
2018-11-12 12:23 ` Jeff King
2018-11-11 23:58 ` [PATCH v2 2/2] branch: Mark and colorize a branch differently if it is checked out in a linked worktree nbelakovski
2018-11-12 10:20 ` Junio C Hamano
2018-11-12 12:14 ` Jeff King
2018-11-12 18:07 ` Rafael Ascensão
2018-11-13 1:45 ` Junio C Hamano
2018-11-13 14:49 ` Jeff King
2018-11-21 14:07 ` Nickolai Belakovski
2018-12-16 21:57 ` [PATCH v3 0/3] nbelakovski
2018-12-16 21:57 ` [PATCH v3 1/3] ref-filter: add worktreepath atom nbelakovski
2018-12-18 17:22 ` Jeff King [this message]
2018-12-20 7:09 ` Nickolai Belakovski
2018-12-20 14:59 ` Jeff King
2018-12-24 8:47 ` [PATCH v4 0/3] nbelakovski
2018-12-24 8:47 ` [PATCH v4 1/3] ref-filter: add worktreepath atom nbelakovski
2019-01-03 5:40 ` Jeff King
2019-01-03 9:31 ` Eric Sunshine
2018-12-24 8:47 ` [PATCH v4 2/3] branch: Mark and color a branch differently if it is checked out in a linked worktree nbelakovski
2018-12-24 8:47 ` [PATCH v4 3/3] branch: Add an extra verbose output displaying worktree path for refs " nbelakovski
2019-01-03 5:42 ` Jeff King
2019-01-03 5:22 ` [PATCH v4 0/3] Jeff King
2018-12-16 21:57 ` [PATCH v3 2/3] branch: Mark and color a branch differently if it is checked out in a linked worktree nbelakovski
2018-12-16 21:57 ` [PATCH v3 3/3] branch: Add an extra verbose output displaying worktree path for refs " nbelakovski
2018-12-18 17:25 ` [PATCH v3 0/3] Jeff King
2019-01-06 0:26 ` [PATCH v5 0/3] nbelakovski
2019-01-06 0:26 ` [PATCH v5 1/3] ref-filter: add worktreepath atom nbelakovski
2019-01-07 18:20 ` Junio C Hamano
2019-01-18 22:17 ` Nickolai Belakovski
2019-01-18 22:20 ` Nickolai Belakovski
2019-01-06 0:26 ` [PATCH v5 2/3] branch: Mark and color a branch differently if it is checked out in a linked worktree nbelakovski
2019-01-07 19:04 ` Junio C Hamano
2019-01-10 21:42 ` Philip Oakley
2019-01-13 1:41 ` Nickolai Belakovski
2019-01-14 18:18 ` Junio C Hamano
2019-01-18 22:18 ` Nickolai Belakovski
2019-01-06 0:26 ` [PATCH v5 3/3] branch: Add an extra verbose output displaying worktree path for refs " nbelakovski
2019-01-07 19:09 ` Junio C Hamano
2019-01-22 23:22 ` [PATCH v6 0/3] nbelakovski
2019-01-22 23:22 ` [PATCH v6 1/3] ref-filter: add worktreepath atom nbelakovski
2019-01-23 18:57 ` Junio C Hamano
2019-01-23 23:34 ` Nickolai Belakovski
2019-01-24 18:26 ` Junio C Hamano
2019-01-24 18:32 ` Jeff King
2019-01-24 19:27 ` Junio C Hamano
2019-01-24 19:34 ` Jeff King
2019-01-24 19:30 ` Junio C Hamano
2019-01-24 21:26 ` Jeff King
2019-01-31 20:53 ` Nickolai Belakovski
2019-01-31 23:21 ` Jeff King
2019-01-31 21:42 ` Junio C Hamano
2019-01-31 23:20 ` Jeff King
2019-01-22 23:23 ` [PATCH v6 2/3] branch: Mark and color a branch differently if it is checked out in a linked worktree nbelakovski
2019-01-22 23:23 ` [PATCH v6 3/3] branch: Add an extra verbose output displaying worktree path for refs " nbelakovski
2019-02-01 22:04 ` [PATCH v7 0/3] nbelakovski
2019-02-01 22:28 ` Junio C Hamano
2019-02-01 23:31 ` Nickolai Belakovski
2019-02-01 22:04 ` [PATCH v7 1/3] ref-filter: add worktreepath atom nbelakovski
2019-02-01 22:20 ` Eric Sunshine
2019-02-01 22:41 ` Nickolai Belakovski
2019-02-04 18:14 ` Junio C Hamano
2019-02-18 10:09 ` Nickolai Belakovski
2019-02-01 22:31 ` Junio C Hamano
2019-02-01 22:04 ` [PATCH v7 2/3] branch: Mark and color a branch differently if it is checked out in a linked worktree nbelakovski
2019-02-01 22:34 ` Junio C Hamano
2019-02-01 23:12 ` Nickolai Belakovski
2019-02-04 18:18 ` Junio C Hamano
2019-02-01 22:04 ` [PATCH v7 3/3] branch: Add an extra verbose output displaying worktree path for refs " nbelakovski
2019-02-01 22:27 ` Eric Sunshine
2019-02-01 22:45 ` Nickolai Belakovski
2019-02-01 22:53 ` Junio C Hamano
2019-02-01 23:06 ` Nickolai Belakovski
2019-02-02 1:22 ` [RFC] Sample of test for git branch -vv nbelakovski
2019-02-19 8:31 ` [PATCH v8 0/3] nbelakovski
2019-02-19 8:31 ` [PATCH v8 1/3] ref-filter: add worktreepath atom nbelakovski
2019-02-19 8:31 ` [PATCH v8 2/3] branch: update output to include worktree info nbelakovski
2019-02-21 12:44 ` Jeff King
2019-03-14 5:45 ` Nickolai Belakovski
2019-02-19 8:31 ` [PATCH v8 3/3] branch: add worktree info on verbose output nbelakovski
2019-02-21 12:59 ` Jeff King
2019-03-14 5:58 ` Nickolai Belakovski
2019-03-18 2:12 ` Junio C Hamano
2019-02-21 12:36 ` [PATCH v8 0/3] Jeff King
2019-03-14 6:10 ` Nickolai Belakovski
2019-03-16 1:38 ` [PATCH v9 0/3] nbelakovski
2019-03-16 1:38 ` [PATCH v9 1/3] ref-filter: add worktreepath atom nbelakovski
2019-03-16 1:38 ` [PATCH v9 2/3] branch: update output to include worktree info nbelakovski
2019-03-16 1:38 ` [PATCH v9 3/3] branch: add worktree info on verbose output nbelakovski
2019-03-18 12:10 ` SZEDER Gábor
2019-03-18 5:30 ` [PATCH v9 0/3] Junio C Hamano
2019-04-29 5:19 ` [PATCH v10 0/3] nbelakovski
2019-04-29 5:19 ` [PATCH v10 1/3] ref-filter: add worktreepath atom nbelakovski
2019-04-29 5:19 ` [PATCH v10 2/3] branch: update output to include worktree info nbelakovski
2019-04-29 5:19 ` [PATCH v10 3/3] branch: add worktree info on verbose output nbelakovski
2019-04-29 14:12 ` [PATCH v10 0/3] SZEDER Gábor
2019-04-29 19:27 ` Nickolai Belakovski
2019-04-29 20:57 ` Johannes Schindelin
2019-04-29 21:33 ` Nickolai Belakovski
[not found] ` <CAC05385Mc7pqiCd5mb+1c4WM+v7K=h=GMHuvkw9xizhRFJXXBA@mail.gmail.com>
2019-04-30 21:46 ` Johannes Schindelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181218172236.GA28455@sigill.intra.peff.net \
--to=peff@peff.net \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=nbelakovski@gmail.com \
--cc=rafa.almas@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).