git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [GSoC][RFC PATCH v3 1/3] builtin/refs: add list subcommand

From
Junio C Hamano <gitster@pobox.com>
Date
Jul 24, 2025, 16:01 UTC
Message-ID
<xmqq4iv1k26x.fsf@gitster.g>
In-Reply-To
<aIHLdkhdVNy72Yf-@pks.im>
Patrick Steinhardt <ps@pks.im> writes:
Show 9 quoted lines
> On Wed, Jul 23, 2025 at 12:13:11PM +0530, Meet Soni wrote:
>> diff --git a/Documentation/git-for-each-ref.adoc b/Documentation/git-for-each-ref.adoc
>> index 5ef89fc0fe..f7bbc1902a 100644
>> --- a/Documentation/git-for-each-ref.adoc
>> +++ b/Documentation/git-for-each-ref.adoc
>
> Tiny nit, not worth a reroll by itself: it would have been nice to move
> the extraction of the common options from our docs into a separate,
> preparatory commit.
True.
Show 24 quoted lines
>> diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
>> index 3d2207ec77..d7d8279049 100644
>> --- a/builtin/for-each-ref.c
>> +++ b/builtin/for-each-ref.c
>> @@ -16,11 +16,27 @@ static char const * const for_each_ref_usage[] = {
>>  	NULL
>>  };
>>  
>> +#define REFS_LIST_USAGE \
>> +	N_("git refs list [--count=<count>] [--shell|--perl|--python|--tcl]\n" \
>> +	   "              [(--sort=<key>)...] [--format=<format>]\n" \
>> +	   "              [--include-root-refs] [ --stdin | <pattern>... ]\n" \
>> +	   "              [--points-at=<object>]\n" \
>> +	   "              [--merged[=<object>]] [--no-merged[=<object>]]\n" \
>> +	   "              [--contains[=<object>]] [--no-contains[=<object>]]\n" \
>> +	   "              [--exclude=<pattern> ...]")
>> +
>> +static char const * const refs_list_usage[] = {
>> +	REFS_LIST_USAGE,
>> +	NULL
>> +};
>
> Shouldn't the usage strings for git-for-each-ref(1) and git-refs-list(1)
> be the same, except for the command name?
A great observation, but where would it lead us?  Something like
        #define COMMON_USAGE_FOR_EACH_REF \
                   " [--count=<count>] [--shell|--perl|--python|--tcl]\n" \
		   "              [(--sort=<key>)...] [--format=<format>]\n" \
                   ... \
                   "              [--exclude=<pattern> ...]"
        #define REFS_LIST_USAGE \
                N_("git refs list" COMMON_USAGE_FOR_EACH_REF);
        #define FOR_EACH_REF_USAGE \
                N_("git for-each-ref" COMMON_USAGE_FOR_EACH_REF);

is very much desirable because we do not want the options of these two commands drift apart, but it does not quite work with the current usage_with_options() infrastructure, as it leaves the indentation of second and subsequent lines up to the caller, and the display widths of "refs list" and "for-each-ref" are different.

Show 14 quoted lines
>>  int cmd_for_each_ref(int argc,
>>  		     const char **argv,
>>  		     const char *prefix,
>>  		     struct repository *repo)
>>  {
>> +	int cmd_is_refs_list = !strcmp(argv[0], "refs list");
>> +	const char *const *opt_usage = cmd_is_refs_list ? refs_list_usage : for_each_ref_usage;
>>  	struct ref_sorting *sorting;
>>  	struct string_list sorting_options = STRING_LIST_INIT_DUP;
>>  	int icase = 0, include_root_refs = 0, from_stdin = 0;
>
> This follows the same pattern we have in "builtin/blame.c". It's not
> exactly pretty that git-for-each-ref(1) is aware of git-refs(1) now, but
> I think it's the pragmatic thing to do.

Although it is yucky. argv[0] can never be "refs list" unless you are calling this as if it were a subroutine by hand, which is in general a no-no.

cf. https://lore.kernel.org/git/20171010040604.26029-1-gitster@pobox.com/

In this particular case, it is not like calling cmd_merge() from within a loop in cmd_rebase(), so many reasons against such program structure would not apply, but it would be prudent to leave an in-code comment to warn others not to mimic this pattern in general case.

Show 24 quoted lines
>> diff --git a/builtin/refs.c b/builtin/refs.c
>> index 998d2a2c1c..41e29d1b5f 100644
>> --- a/builtin/refs.c
>> +++ b/builtin/refs.c
>> @@ -13,6 +14,15 @@
>>  #define REFS_VERIFY_USAGE \
>>  	N_("git refs verify [--strict] [--verbose]")
>>  
>> +#define REFS_LIST_USAGE \
>> +	N_("git refs list [--count=<count>] [--shell|--perl|--python|--tcl]\n" \
>> +	   "              [(--sort=<key>)...] [--format=<format>]\n" \
>> +	   "              [--include-root-refs] [ --stdin | <pattern>... ]\n" \
>> +	   "              [--points-at=<object>]\n" \
>> +	   "              [--merged[=<object>]] [--no-merged[=<object>]]\n" \
>> +	   "              [--contains[=<object>]] [--no-contains[=<object>]]\n" \
>> +	   "              [--exclude=<pattern> ...]")
>> +
>>  static int cmd_refs_migrate(int argc, const char **argv, const char *prefix,
>>  			    struct repository *repo UNUSED)
>>  {
>
> Hm, this one is a bit unfortunate though, as it feels like it's just a
> matter of time before the two `REFS_LIST_USAGE` defines drift apart.
> Might be worth it to move them to a shared place.
Yes, but see above.
> Alternatively, we could pull out the logic of `cmd_for_each_ref()` into
> a separate function that also receives the usage array. Not sure whether
> that is worth the hassle though.

I was also wondering about such restructuring of the existing program. Before adding a single line to support "refs list", can we move much of what cmd_for_each_ref() does that is common between it and upcoming "refs list" into a helper function, and make cmd_for_each_ref() to call it, as a preparatory step? Then a new "refs list" implementation does not have to touch the implementation of cmd_for_each_ref(), or call cmd_for_each_ref(). Which would give us much cleaner implementation, and we do not have to leave an ugly comment "we are doing this because we want to introduce 'refs list' synonym that behaves identically and calling cmd_for_each_ref() is the easiest way, but do not mimick it! It is an unacceptable pattern you should not follow in more general cases".

Thanks.
Previous: Patrick SteinhardtNext: Meet Soni
Message 28 of 65 in “Add refs list subcommand”
  1. Meet SoniJun 27, 2025
  2. [GSoC][RFC PATCH 1/2] builtin/refs: add list subcommandMeet Soni, Jun 27, 2025
  3. Jean-Noël AvilaJun 27, 2025
  4. Junio C HamanoJun 27, 2025
  5. Meet SoniJun 30, 2025
  6. doc:git-for-each-ref: fix styling and typosJean-Noël Avila, Jun 29, 2025
  7. Junio C HamanoJun 30, 2025
  8. Jean-Noël AVILAJun 30, 2025
  9. [GSoC][RFC PATCH 2/2] t: add test for git refs list subcommandMeet Soni, Jun 27, 2025
  10. Junio C HamanoJun 27, 2025
  11. shejialuoJun 28, 2025
  12. Junio C HamanoJun 30, 2025
  13. shejialuoJul 6, 2025
  14. Meet SoniJun 30, 2025
  15. Junio C HamanoJun 30, 2025
  16. Patrick SteinhardtJul 9, 2025
  17. [GSoC][RFC PATCH v2 0/2] Add refs list subcommandMeet Soni, Jul 17, 2025
  18. [GSoC][RFC PATCH v2 1/2] builtin/refs: add list subcommandMeet Soni, Jul 17, 2025
  19. Eric SunshineJul 17, 2025
  20. Meet SoniJul 23, 2025
  21. [GSoC][RFC PATCH v2 2/2] t: add test for git refs list subcommandMeet Soni, Jul 17, 2025
  22. Junio C HamanoJul 17, 2025
  23. Meet SoniJul 23, 2025
  24. Junio C HamanoJul 23, 2025
  25. [GSoC][RFC PATCH v3 0/3] Add refs list subcommandMeet Soni, Jul 23, 2025
  26. [GSoC][RFC PATCH v3 1/3] builtin/refs: add list subcommandMeet Soni, Jul 23, 2025
  27. Patrick SteinhardtJul 24, 2025
  28. Junio C HamanoJul 24, 2025
  29. Meet SoniJul 25, 2025
  30. [GSoC][RFC PATCH v3 2/3] t6300: refactor tests to be shareableMeet Soni, Jul 23, 2025
  31. [GSoC][RFC PATCH v3 3/3] t: add test for git refs list subcommandMeet Soni, Jul 23, 2025
  32. [GSoC][RFC PATCH v4 0/5] Add refs list subcommandMeet Soni, Jul 31, 2025
  33. [GSoC][RFC PATCH v4 1/5] doc: factor out common optionMeet Soni, Jul 31, 2025
  34. [GSoC][RFC PATCH v4 2/5] builtin/for-each-ref: factor out core logic into a helperMeet Soni, Jul 31, 2025
  35. Patrick SteinhardtAug 1, 2025
  36. Meet SoniAug 4, 2025
  37. [GSoC][RFC PATCH v4 3/5] builtin/refs: add list subcommandMeet Soni, Jul 31, 2025
  38. Phillip WoodAug 1, 2025
  39. Junio C HamanoAug 1, 2025
  40. Phillip WoodAug 1, 2025
  41. Junio C HamanoAug 1, 2025
  42. Phillip WoodAug 4, 2025
  43. Meet SoniAug 4, 2025
  44. Phillip WoodAug 4, 2025
  45. Junio C HamanoAug 4, 2025
  46. [GSoC][RFC PATCH v4 4/5] t6300: refactor tests to be shareableMeet Soni, Jul 31, 2025
  47. [GSoC][RFC PATCH v4 5/5] t: add test for git refs list subcommandMeet Soni, Jul 31, 2025
  48. Patrick SteinhardtAug 1, 2025
  49. [GSoC][RFC PATCH v5 0/6] Add refs list subcommandMeet Soni, Aug 4, 2025
  50. [GSoC][RFC PATCH v5 1/6] doc: factor out common optionMeet Soni, Aug 4, 2025
  51. Junio C HamanoAug 4, 2025
  52. [GSoC][RFC PATCH v5 2/6] builtin/for-each-ref: align usage string with the man pageMeet Soni, Aug 4, 2025
  53. [GSoC][RFC PATCH v5 3/6] builtin/for-each-ref: factor out core logic into a helperMeet Soni, Aug 4, 2025
  54. [GSoC][RFC PATCH v5 4/6] builtin/refs: add list subcommandMeet Soni, Aug 4, 2025
  55. [GSoC][RFC PATCH v5 5/6] t6300: refactor tests to be shareableMeet Soni, Aug 4, 2025
  56. [GSoC][RFC PATCH v5 6/6] t: add test for git refs list subcommandMeet Soni, Aug 4, 2025
  57. [GSoC][PATCH v6 0/6] Add refs list subcommandMeet Soni, Aug 5, 2025
  58. [GSoC][PATCH v6 1/6] doc: factor out common optionMeet Soni, Aug 5, 2025
  59. [GSoC][PATCH v6 2/6] builtin/for-each-ref: align usage string with the man pageMeet Soni, Aug 5, 2025
  60. [GSoC][PATCH v6 3/6] builtin/for-each-ref: factor out core logic into a helperMeet Soni, Aug 5, 2025
  61. [GSoC][PATCH v6 4/6] builtin/refs: add list subcommandMeet Soni, Aug 5, 2025
  62. [GSoC][PATCH v6 5/6] t6300: refactor tests to be shareableMeet Soni, Aug 5, 2025
  63. [GSoC][PATCH v6 6/6] t: add test for git refs list subcommandMeet Soni, Aug 5, 2025
  64. Patrick SteinhardtAug 5, 2025
  65. Junio C HamanoAug 5, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.