{"thread":{"id":"62501","subject":"log --format existence of notes?","startedAt":"2024-11-15T22:01:07Z","lastAt":"2024-12-01T08:19:53Z","messageCount":7,"participants":["Bence Ferdinandy","Junio C Hamano","Kousik Sanagavarapu","Simon Richter"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"507378","messageId":"D5N39IJA0WDQ.2WH1MNIP77X2J@ferdinandy.com","threadId":"62501","inReplyTo":null,"subject":"log --format existence of notes?","fromName":"Bence Ferdinandy","fromEmail":"bence@ferdinandy.com","sentAt":"2024-11-15T22:00:30Z","receivedAt":"2024-11-15T22:01:07Z","isPatch":false,"sender":{"key":"bence@ferdinandy.com","avatar":"https://avatars.githubusercontent.com/u/6343487?v=4"},"body":"Hi,\n\nbased on the man pages it doesn't seem possible, but maybe I'm missing something.\n\nI would like to put together a \"log --format=\" which is similar to --oneline,\nbut where if there's a note for the commit it's marked with e.g. a notebook\nsymbol. There's %N, but that prints the entire note, so it doesn't work well\nwith one commit per line.\n\nE.g. something like this, where Taylor's commit does not have a note, but mine do:\n\neb12efd995 2024-10-08 Bence Ferdin.. remote set-head: refactor for readability 📓\na189f4e077 2024-09-28 Bence Ferdin.. refs: atomically record overwritten ref in update_symref 📓\nae0b28db8c 2024-10-19 Bence Ferdin.. t/t5505-remote: set default branch to main 📓\n15030f9556 2024-10-15 Taylor Blau    The second batch\n\nIs there a way to do this now? If not, maybe a \"%N?\" might be a nice addition?\n\nThanks,\nBence\n\n-- \nbence.ferdinandy.com\n\n"},{"id":"507386","messageId":"xmqqsersyrch.fsf@gitster.g","threadId":"62501","inReplyTo":"D5N39IJA0WDQ.2WH1MNIP77X2J@ferdinandy.com","subject":"Re: log --format existence of notes?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-11-16T00:06:38Z","receivedAt":"2024-11-16T00:06:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Bence Ferdinandy\" <bence@ferdinandy.com> writes:\n\n> based on the man pages it doesn't seem possible, but maybe I'm missing something.\n>\n> I would like to put together a \"log --format=\" which is similar to --oneline,\n> but where if there's a note for the commit it's marked with e.g. a notebook\n> symbol. There's %N, but that prints the entire note, so it doesn't work well\n> with one commit per line.\n\nI do not think it is doable.  Unlike the format language in the\nfor-each-ref/branch --list family of commands, the pretty-format\nlanguage in the log family of commands lack more involved\nconditional formatting features.\n\nUnifying these two formatting languages to port features from one to\nthe other would be needed, I guess.  If we had a note support in the\nlatter,  something like\n\n$ git branch -l --format='%(subject)%(if)%(note:amlog)%(then)📓%(end)'\n\nmay have worked.\n\n"},{"id":"507409","messageId":"D5NP6QUUBWBL.7OUG34RUIE2S@ferdinandy.com","threadId":"62501","inReplyTo":"xmqqsersyrch.fsf@gitster.g","subject":"Re: log --format existence of notes?","fromName":"Bence Ferdinandy","fromEmail":"bence@ferdinandy.com","sentAt":"2024-11-16T15:11:17Z","receivedAt":"2024-11-16T15:11:42Z","isPatch":false,"sender":{"key":"bence@ferdinandy.com","avatar":"https://avatars.githubusercontent.com/u/6343487?v=4"},"body":"\nOn Sat Nov 16, 2024 at 01:06, Junio C Hamano <gitster@pobox.com> wrote:\n> \"Bence Ferdinandy\" <bence@ferdinandy.com> writes:\n>\n>> based on the man pages it doesn't seem possible, but maybe I'm missing something.\n>>\n>> I would like to put together a \"log --format=\" which is similar to --oneline,\n>> but where if there's a note for the commit it's marked with e.g. a notebook\n>> symbol. There's %N, but that prints the entire note, so it doesn't work well\n>> with one commit per line.\n>\n> I do not think it is doable.  Unlike the format language in the\n> for-each-ref/branch --list family of commands, the pretty-format\n> language in the log family of commands lack more involved\n> conditional formatting features.\n>\n> Unifying these two formatting languages to port features from one to\n> the other would be needed, I guess.  \n\nIs this already on the roadmap with a plan on how to do it? It sounds like\nswitching log format to the same formatting as the other commands would make\nlife easier in the long run.\n\n> If we had a note support in the\n> latter,  something like\n>\n> $ git branch -l --format='%(subject)%(if)%(note:amlog)%(then)📓%(end)'\n>\n> may have worked.\n\nConditional formatting definitely would sound useful for logs as well :)\n\nOn the other hand: would a quick win in analogy to \"%G?\" be considered? A \"%N?\"\nthat either outputs a \"N\" for note and a \"-\" for no note? Or something like\nthat. A bit ugly, but gets the job done.\n\nThanks,\nBence\n"},{"id":"507767","messageId":"Zz4Wr1YY7HxRARoc@five231003","threadId":"62501","inReplyTo":"D5NP6QUUBWBL.7OUG34RUIE2S@ferdinandy.com","subject":"[PATCH] ref-filter: add \"notes\" atom","fromName":"Kousik Sanagavarapu","fromEmail":"five231003@gmail.com","sentAt":"2024-11-20T17:04:47Z","receivedAt":"2024-11-20T17:04:52Z","isPatch":true,"sender":{"key":"five231003@gmail.com","avatar":"https://avatars.githubusercontent.com/u/75560439?v=4"},"body":"On Sat, Nov 16, 2024 at 04:11:17PM +0100, Bence Ferdinandy wrote:\n> \n> On Sat Nov 16, 2024 at 01:06, Junio C Hamano <gitster@pobox.com> wrote:\n> > \"Bence Ferdinandy\" <bence@ferdinandy.com> writes:\n> >\n> >> based on the man pages it doesn't seem possible, but maybe I'm missing something.\n> >>\n> >> I would like to put together a \"log --format=\" which is similar to --oneline,\n> >> but where if there's a note for the commit it's marked with e.g. a notebook\n> >> symbol. There's %N, but that prints the entire note, so it doesn't work well\n> >> with one commit per line.\n> >\n> > I do not think it is doable.  Unlike the format language in the\n> > for-each-ref/branch --list family of commands, the pretty-format\n> > language in the log family of commands lack more involved\n> > conditional formatting features.\n> >\n> > Unifying these two formatting languages to port features from one to\n> > the other would be needed, I guess.  \n> \n> Is this already on the roadmap with a plan on how to do it? It sounds like\n> switching log format to the same formatting as the other commands would make\n> life easier in the long run.\n\nYes, but a fixed plan doesn't exist really.  There has been effort in\nthe past (and even now) to re-implement formats from pretty in ref-filter\nand when that is done, change everything to use ref-filter, but the parsing\nmechanism in ref-filter is a bit broken in some really really rare cases [1].\n\n> > If we had a note support in the\n> > latter,  something like\n> >\n> > $ git branch -l --format='%(subject)%(if)%(note:amlog)%(then)📓%(end)'\n> >\n> > may have worked.\n> \n> Conditional formatting definitely would sound useful for logs as well :)\n\nI agree that having the \"%(if)...\" would be good in pretty.\n\n[1] See thread\n\n\thttps://lore.kernel.org/git/20241105190235.13502-1-five231003@gmail.com/\n\n\n\nIn the meantime, here is an implementation of \"%(notes)\" atom in\nref-filter.  I know this doesn't really address the \"log\" family since\nwe are not adding this format in pretty, but we can now do\n\n\t$ git branch -l --format='%(subject)%(if)%(notes:amlog)%(then)📓%(end)'\n\n------------------------ >8 ------------------------\nSubject: [PATCH] ref-filter: add \"notes\" atom\n\nIntroduce new \"%(notes)\" format which is capable of showing the notes\nassociated with any particular ref.  This new atom may also be given an\nargument specifying where to look for the notes, for example\nrefs/notes/amlog, associated with the ref.\n\nThe behavior is the same as doing\n\n\t$ git notes show <refname>\n\nfor the bare \"%(notes)\" format and\n\n\t$ git notes --ref <notes-ref> show <refname>\n\nfor the \"%(notes:notes-ref)\" format.\n\nSigned-off-by: Kousik Sanagavarapu <five231003@gmail.com>\n---\n Documentation/git-for-each-ref.txt |  7 ++++\n ref-filter.c                       | 54 ++++++++++++++++++++++++++++++\n t/t6300-for-each-ref.sh            | 28 ++++++++++++++++\n 3 files changed, 89 insertions(+)\n\ndiff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\nindex d3764401a2..406e4a0390 100644\n--- a/Documentation/git-for-each-ref.txt\n+++ b/Documentation/git-for-each-ref.txt\n@@ -329,6 +329,13 @@ exclude=<pattern>;;\n \tin linkgit:git-describe[1] for details.\n --\n \n+notes:<notes-ref>::\n+\tShow notes associated with a ref.  Defaults to getting notes\n+\tfrom `refs/notes/commits`.  If `\"notes-ref\"` is given then notes\n+\tretrieved from that ref are shown; for the given ref.  For\n+\texample, `%(notes:amlog)` will retrieve the notes from\n+\t`refs/notes/amlog` for the given ref.  See linkgit:git-notes[1].\n+\n In addition to the above, for commit and tag objects, the header\n field names (`tree`, `parent`, `object`, `type`, and `tag`) can\n be used to specify the value in the header field.\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 84c6036107..76c06178f2 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -155,6 +155,7 @@ enum atom_type {\n \tATOM_TRAILERS,\n \tATOM_CONTENTS,\n \tATOM_SIGNATURE,\n+\tATOM_NOTES,\n \tATOM_RAW,\n \tATOM_UPSTREAM,\n \tATOM_PUSH,\n@@ -235,6 +236,7 @@ static struct used_atom {\n \t\t\t       S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;\n \t\t} signature;\n \t\tstruct strvec describe_args;\n+\t\tconst char *notes_refname;\n \t\tstruct refname_atom refname;\n \t\tchar *head;\n \t} u;\n@@ -712,6 +714,15 @@ static int describe_atom_parser(struct ref_format *format UNUSED,\n \treturn 0;\n }\n \n+static int notes_atom_parser(struct ref_format *format UNUSED,\n+\t\t\t     struct used_atom *atom,\n+\t\t\t     const char *arg, struct strbuf *err UNUSED)\n+{\n+\tif (arg)\n+\t\tatom->u.notes_refname = arg;\n+\treturn 0;\n+}\n+\n static int raw_atom_parser(struct ref_format *format UNUSED,\n \t\t\t   struct used_atom *atom,\n \t\t\t   const char *arg, struct strbuf *err)\n@@ -974,6 +985,7 @@ static struct {\n \t[ATOM_TRAILERS] = { \"trailers\", SOURCE_OBJ, FIELD_STR, trailers_atom_parser },\n \t[ATOM_CONTENTS] = { \"contents\", SOURCE_OBJ, FIELD_STR, contents_atom_parser },\n \t[ATOM_SIGNATURE] = { \"signature\", SOURCE_OBJ, FIELD_STR, signature_atom_parser },\n+\t[ATOM_NOTES] = { \"notes\", SOURCE_OBJ, FIELD_STR, notes_atom_parser },\n \t[ATOM_RAW] = { \"raw\", SOURCE_OBJ, FIELD_STR, raw_atom_parser },\n \t[ATOM_UPSTREAM] = { \"upstream\", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },\n \t[ATOM_PUSH] = { \"push\", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },\n@@ -1957,6 +1969,44 @@ static void grab_describe_values(struct atom_value *val, int deref,\n \t}\n }\n \n+static void grab_notes_values(struct atom_value *val, int deref,\n+\t\t\t      struct object *obj)\n+{\n+\tfor (int i = 0; i < used_atom_cnt; i++) {\n+\t\tstruct used_atom *atom = &used_atom[i];\n+\t\tconst char *name = atom->name;\n+\t\tstruct atom_value *v = &val[i];\n+\n+\t\tstruct child_process cmd = CHILD_PROCESS_INIT;\n+\t\tstruct strbuf out = STRBUF_INIT;\n+\t\tstruct strbuf err = STRBUF_INIT;\n+\n+\t\tif (atom->atom_type != ATOM_NOTES)\n+\t\t\tcontinue;\n+\n+\t\tif (!!deref != (*name == '*'))\n+\t\t\tcontinue;\n+\n+\t\tcmd.git_cmd = 1;\n+\t\tstrvec_push(&cmd.args, \"notes\");\n+\t\tif (atom->u.notes_refname) {\n+\t\t\tstrvec_push(&cmd.args, \"--ref\");\n+\t\t\tstrvec_push(&cmd.args, atom->u.notes_refname);\n+\t\t}\n+\t\tstrvec_push(&cmd.args, \"show\");\n+\t\tstrvec_push(&cmd.args, oid_to_hex(&obj->oid));\n+\t\tif (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {\n+\t\t\terror(_(\"failed to run 'notes'\"));\n+\t\t\tv->s = xstrdup(\"\");\n+\t\t\tcontinue;\n+\t\t}\n+\t\tstrbuf_rtrim(&out);\n+\t\tv->s = strbuf_detach(&out, NULL);\n+\n+\t\tstrbuf_release(&err);\n+\t}\n+}\n+\n /* See grab_values */\n static void grab_sub_body_contents(struct atom_value *val, int deref, struct expand_data *data)\n {\n@@ -2076,6 +2126,7 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, s\n \t\tgrab_sub_body_contents(val, deref, data);\n \t\tgrab_person(\"tagger\", val, deref, buf);\n \t\tgrab_describe_values(val, deref, obj);\n+\t\tgrab_notes_values(val, deref, obj);\n \t\tbreak;\n \tcase OBJ_COMMIT:\n \t\tgrab_commit_values(val, deref, obj);\n@@ -2084,14 +2135,17 @@ static void grab_values(struct atom_value *val, int deref, struct object *obj, s\n \t\tgrab_person(\"committer\", val, deref, buf);\n \t\tgrab_signature(val, deref, obj);\n \t\tgrab_describe_values(val, deref, obj);\n+\t\tgrab_notes_values(val, deref, obj);\n \t\tbreak;\n \tcase OBJ_TREE:\n \t\t/* grab_tree_values(val, deref, obj, buf, sz); */\n \t\tgrab_sub_body_contents(val, deref, data);\n+\t\tgrab_notes_values(val, deref, obj);\n \t\tbreak;\n \tcase OBJ_BLOB:\n \t\t/* grab_blob_values(val, deref, obj, buf, sz); */\n \t\tgrab_sub_body_contents(val, deref, data);\n+\t\tgrab_notes_values(val, deref, obj);\n \t\tbreak;\n \tdefault:\n \t\tdie(\"Eh?  Object of type %d?\", obj->type);\ndiff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh\nindex c39d4e7e9c..cf2ff26fd1 100755\n--- a/t/t6300-for-each-ref.sh\n+++ b/t/t6300-for-each-ref.sh\n@@ -847,6 +847,34 @@ test_expect_success 'err on bad describe atom arg' '\n \t)\n '\n \n+test_expect_success 'bare notes atom' '\n+\ttest_when_finished \"git checkout main && git branch -D notes-atom \" &&\n+\n+\tgit checkout -b notes-atom &&\n+\ttest_commit --no-tag \"commit on notes-atom\" &&\n+\n+\tgit notes add -m \"some msg\" refs/heads/notes-atom &&\n+\tgit notes show refs/heads/notes-atom >expect &&\n+\tgit for-each-ref --format=\"%(notes)\" refs/heads/notes-atom >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'notes atom with notes ref' '\n+\ttest_when_finished \\\n+\t\t\"git checkout main && git branch -D notes-atom-refname\" &&\n+\n+\tgit checkout -b notes-atom-refname &&\n+\ttest_commit --no-tag \"commit on notes-atom-refname\" &&\n+\n+\tgit notes --ref notes-ref add -m \"some msg\" \\\n+\t\t refs/heads/notes-atom-refname &&\n+\tgit notes --ref notes-ref show \\\n+\t\trefs/heads/notes-atom-refname >expect &&\n+\tgit for-each-ref --format=\"%(notes:notes-ref)\" \\\n+\t\trefs/heads/notes-atom-refname >actual &&\n+\ttest_cmp expect actual\n+'\n+\n cat >expected <<\\EOF\n heads/main\n tags/main\n-- \n2.47.0.289.g3d75e57c9c\n\n"},{"id":"507797","messageId":"xmqqserlh3ak.fsf@gitster.g","threadId":"62501","inReplyTo":"Zz4Wr1YY7HxRARoc@five231003","subject":"Re: [PATCH] ref-filter: add \"notes\" atom","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-11-20T23:51:47Z","receivedAt":"2024-11-20T23:51:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kousik Sanagavarapu <five231003@gmail.com> writes:\n\n> +static void grab_notes_values(struct atom_value *val, int deref,\n> +\t\t\t      struct object *obj)\n> +{\n> +\tfor (int i = 0; i < used_atom_cnt; i++) {\n> +\t\tstruct used_atom *atom = &used_atom[i];\n> +\t\tconst char *name = atom->name;\n> +\t\tstruct atom_value *v = &val[i];\n> +\n> +\t\tstruct child_process cmd = CHILD_PROCESS_INIT;\n> +\t\tstruct strbuf out = STRBUF_INIT;\n> +\t\tstruct strbuf err = STRBUF_INIT;\n> +\n> +\t\tif (atom->atom_type != ATOM_NOTES)\n> +\t\t\tcontinue;\n> +\n> +\t\tif (!!deref != (*name == '*'))\n> +\t\t\tcontinue;\n> +\n> +\t\tcmd.git_cmd = 1;\n> +\t\tstrvec_push(&cmd.args, \"notes\");\n> +\t\tif (atom->u.notes_refname) {\n> +\t\t\tstrvec_push(&cmd.args, \"--ref\");\n> +\t\t\tstrvec_push(&cmd.args, atom->u.notes_refname);\n> +\t\t}\n> +\t\tstrvec_push(&cmd.args, \"show\");\n> +\t\tstrvec_push(&cmd.args, oid_to_hex(&obj->oid));\n> +\t\tif (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {\n> +\t\t\terror(_(\"failed to run 'notes'\"));\n> +\t\t\tv->s = xstrdup(\"\");\n> +\t\t\tcontinue;\n> +\t\t}\n> +\t\tstrbuf_rtrim(&out);\n> +\t\tv->s = strbuf_detach(&out, NULL);\n> +\n> +\t\tstrbuf_release(&err);\n> +\t}\n> +}\n\nI suspect that this was written to mimick what is done for describe.\n\nThe describe codepath has a (semi-)valid reason to fork out to a\nsubprocess, as computation of describe smudges the object flags of\nin-core object database and it is not trivial to call into the\nhelper functions twice.\n\nBut showing notes for a single commit is merely an internal call to\nget_note() away, so unless the note object is not a blob (which\nshould be absolutely rare), spawning a subprocess for each and every\nref tip feels a bit heavier than acceptable.  We'd probably need to\nmaintain a table of notes_trees, one per <note-ref> used as\n%(notes:<note-ref>) in the format string, and init_notes() on them\nwhile parsing the atoms, and in this codepath it would be a look-up\nof notes_tree from the table based on the u.notes_refname by calling\nget_note() to learn the object name, plus reading the object\ncontents into the v->s member when the note object is a blob (and\nfallback the above code when it is not a blob, which is a rare-case,\nif we really want to handle them).\n"},{"id":"507805","messageId":"04783772-8606-4c85-8389-92e68ff50df2@hogyros.de","threadId":"62501","inReplyTo":"D5NP6QUUBWBL.7OUG34RUIE2S@ferdinandy.com","subject":"Re: log --format existence of notes?","fromName":"Simon Richter","fromEmail":"simon.richter@hogyros.de","sentAt":"2024-11-21T05:26:38Z","receivedAt":"2024-11-21T05:33:02Z","isPatch":false,"sender":{"key":"simon.richter@hogyros.de","avatar":"https://gravatar.com/avatar/1192aa9fa5dd19ce258b12b044cc27111dd7cdb58d920dc2123a02a24f55b5c5?d=mp&s=160"},"body":"Hi,\n\nOn 11/17/24 00:11, Bence Ferdinandy wrote:\n\n> On the other hand: would a quick win in analogy to \"%G?\" be considered? A \"%N?\"\n> that either outputs a \"N\" for note and a \"-\" for no note? Or something like\n> that. A bit ugly, but gets the job done.\n\nFWIW my main use case for notes is to record build/test results.\n\nHaving formats for \"first line of notes\" or \"last line of notes\" (with \nnewline removed) would be really useful for building a poor man's CI \nthat can display checkmarks next to commit messages.\n\n    Simon\n"},{"id":"508387","messageId":"Z0wcIgL8++gm4kt+@five231003","threadId":"62501","inReplyTo":"xmqqserlh3ak.fsf@gitster.g","subject":"Re: [PATCH] ref-filter: add \"notes\" atom","fromName":"Kousik Sanagavarapu","fromEmail":"five231003@gmail.com","sentAt":"2024-12-01T08:19:46Z","receivedAt":"2024-12-01T08:19:53Z","isPatch":true,"sender":{"key":"five231003@gmail.com","avatar":"https://avatars.githubusercontent.com/u/75560439?v=4"},"body":"On Thu, Nov 21, 2024 at 08:51:47AM +0900, Junio C Hamano wrote:\n> Kousik Sanagavarapu <five231003@gmail.com> writes:\n> \n> > +static void grab_notes_values(struct atom_value *val, int deref,\n> > +\t\t\t      struct object *obj)\n> > +{\n> > +\tfor (int i = 0; i < used_atom_cnt; i++) {\n> > +\t\tstruct used_atom *atom = &used_atom[i];\n> > +\t\tconst char *name = atom->name;\n> > +\t\tstruct atom_value *v = &val[i];\n> > +\n> > +\t\tstruct child_process cmd = CHILD_PROCESS_INIT;\n> > +\t\tstruct strbuf out = STRBUF_INIT;\n> > +\t\tstruct strbuf err = STRBUF_INIT;\n> > +\n> > +\t\tif (atom->atom_type != ATOM_NOTES)\n> > +\t\t\tcontinue;\n> > +\n> > +\t\tif (!!deref != (*name == '*'))\n> > +\t\t\tcontinue;\n> > +\n> > +\t\tcmd.git_cmd = 1;\n> > +\t\tstrvec_push(&cmd.args, \"notes\");\n> > +\t\tif (atom->u.notes_refname) {\n> > +\t\t\tstrvec_push(&cmd.args, \"--ref\");\n> > +\t\t\tstrvec_push(&cmd.args, atom->u.notes_refname);\n> > +\t\t}\n> > +\t\tstrvec_push(&cmd.args, \"show\");\n> > +\t\tstrvec_push(&cmd.args, oid_to_hex(&obj->oid));\n> > +\t\tif (pipe_command(&cmd, NULL, 0, &out, 0, &err, 0) < 0) {\n> > +\t\t\terror(_(\"failed to run 'notes'\"));\n> > +\t\t\tv->s = xstrdup(\"\");\n> > +\t\t\tcontinue;\n> > +\t\t}\n> > +\t\tstrbuf_rtrim(&out);\n> > +\t\tv->s = strbuf_detach(&out, NULL);\n> > +\n> > +\t\tstrbuf_release(&err);\n> > +\t}\n> > +}\n> \n> I suspect that this was written to mimick what is done for describe.\n> \n> The describe codepath has a (semi-)valid reason to fork out to a\n> subprocess, as computation of describe smudges the object flags of\n> in-core object database and it is not trivial to call into the\n> helper functions twice.\n> \n> But showing notes for a single commit is merely an internal call to\n> get_note() away, so unless the note object is not a blob (which\n> should be absolutely rare), spawning a subprocess for each and every\n> ref tip feels a bit heavier than acceptable.  We'd probably need to\n> maintain a table of notes_trees, one per <note-ref> used as\n> %(notes:<note-ref>) in the format string, and init_notes() on them\n> while parsing the atoms, and in this codepath it would be a look-up\n> of notes_tree from the table based on the u.notes_refname by calling\n> get_note() to learn the object name, plus reading the object\n> contents into the v->s member when the note object is a blob (and\n> fallback the above code when it is not a blob, which is a rare-case,\n> if we really want to handle them).\n\nHi,\nI was supposed to send a v2 a lot earlier but due to time constraints\n(my semester is ending and there's work related to that) I've not been\nable to work on this.  So if anyone is interested, they may work on this\nand submit v2.  I personally think this format would be a nice addition\nto the ref-filter framework and Junio's msg above gives a really nice\nexplanation on how to do things.\n\nI will work on it in the earliest when I find time but just in case\nsomeone else is interested, they may pick this up and work on it.\n\nThanks\n"}]}