threads / patch / 51871

patchls-remote: create '--count' option

Subject: [PATCH] ls-remote: create '--count' option

## tl;dr

5 messages between Sep 18, 2019 and Sep 19, 2019. Diffs are folded; open one to read it.

replies: 4people: 3as markdown or json

Kamil Domański· Sep 18, 2019, 00:11 UTC · lore

Create a '--count' option for ls-remote, based on the one from for-each-ref. This allows e.g. to return only the first result from a sorted list of refs.

Signed-off-by: Kamil Domański <kamil@domanski.co>
---
 Documentation/git-ls-remote.txt | 11 ++++++++---
 builtin/ls-remote.c             | 16 ++++++++++++----
 t/t5512-ls-remote.sh            |  9 +++++++++
 3 files changed, 29 insertions(+), 7 deletions(-)
Show changes to 3 files +29 −7

Documentation/git-ls-remote.txt, builtin/ls-remote.c, t/t5512-ls-remote.sh

diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index 0b057cbb10..5adc1d676e 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -9,9 +9,9 @@ git-ls-remote - List references in a remote repository
 SYNOPSIS
 --------
 [verse]
-'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>]
-	      [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
-	      [--symref] [<repository> [<refs>...]]
+'git ls-remote' [--count=<count>] [--heads] [--tags] [--refs]
+	      [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url]
+	      [--sort=<key>] [--symref] [<repository> [<refs>...]]
 
 DESCRIPTION
 -----------
@@ -21,6 +21,11 @@ commit IDs.
 
 OPTIONS
 -------
+--count=<count>::
+	By default the command shows all refs that match
+	`<pattern>`.  This option makes it stop after showing
+	that many refs.
+
 -h::
 --heads::
 -t::
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 6ef519514b..482b8c5b3c 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -8,7 +8,7 @@
 static const char * const ls_remote_usage[] = {
 	N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
 	   "                     [-q | --quiet] [--exit-code] [--get-url]\n"
-	   "                     [--symref] [<repository> [<refs>...]]"),
+	   "                     [--symref] [--count=<n>] [<repository> [<refs>...]]"),
 	NULL
 };
 
@@ -43,6 +43,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 	int quiet = 0;
 	int status = 0;
 	int show_symref_target = 0;
+	int maxcount = 0;
 	const char *uploadpack = NULL;
 	const char **pattern = NULL;
 	struct argv_array ref_prefixes = ARGV_ARRAY_INIT;
@@ -55,7 +56,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 	struct ref_array ref_array;
 	static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
 
-	struct option options[] = {
+	struct option opts[] = {
 		OPT__QUIET(&quiet, N_("do not print remote URL")),
 		OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"),
 			   N_("path of git-upload-pack on the remote host")),
@@ -73,14 +74,19 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 			      2, PARSE_OPT_NOCOMPLETE),
 		OPT_BOOL(0, "symref", &show_symref_target,
 			 N_("show underlying ref in addition to the object pointed by it")),
+		OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
 		OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
 		OPT_END()
 	};
 
 	memset(&ref_array, 0, sizeof(ref_array));
 
-	argc = parse_options(argc, argv, prefix, options, ls_remote_usage,
+	argc = parse_options(argc, argv, prefix, opts, ls_remote_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (maxcount < 0) {
+		error("invalid --count argument: `%d'", maxcount);
+		usage_with_options(ls_remote_usage, opts);
+	}
 	dest = argv[0];
 
 	if (argc > 1) {
@@ -138,7 +144,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 	if (sorting)
 		ref_array_sort(sorting, &ref_array);
 
-	for (i = 0; i < ref_array.nr; i++) {
+	if (!maxcount || ref_array.nr < maxcount)
+		maxcount = ref_array.nr;
+	for (i = 0; i < maxcount; i++) {
 		const struct ref_array_item *ref = ref_array.items[i];
 		if (show_symref_target && ref->symref)
 			printf("ref: %s\t%s\n", ref->symref, ref->refname);
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 43e1d8d4d2..5c27a126bd 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -75,6 +75,15 @@ test_expect_success 'ls-remote --sort="-refname" --tags self' '
 	test_cmp expect actual
 '
 
+test_expect_success 'ls-remote --count=2 --sort="refname" --tags self' '
+	cat >expect <<-EOF &&
+	$(git rev-parse mark)	refs/tags/mark
+	$(git rev-parse mark1.1)	refs/tags/mark1.1
+	EOF
+	git ls-remote --count=2 --sort="refname" --tags self >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'dies when no remote specified and no default remotes found' '
 	test_must_fail git ls-remote
 '
-- 
2.23.0
Johannes Sixt· Sep 18, 2019, 06:28 UTC · re: Kamil Domański · lore

Re: [PATCH] ls-remote: create '--count' option

Am 18.09.19 um 02:11 schrieb Kamil Domański:
Show 25 quoted lines
> Create a '--count' option for ls-remote, based on the one from
> for-each-ref. This allows e.g. to return only the first result
> from a sorted list of refs.
> 
> Signed-off-by: Kamil Domański <kamil@domanski.co>
> ---
>  Documentation/git-ls-remote.txt | 11 ++++++++---
>  builtin/ls-remote.c             | 16 ++++++++++++----
>  t/t5512-ls-remote.sh            |  9 +++++++++
>  3 files changed, 29 insertions(+), 7 deletions(-)
> 
> diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
> index 0b057cbb10..5adc1d676e 100644
> --- a/Documentation/git-ls-remote.txt
> +++ b/Documentation/git-ls-remote.txt
> @@ -9,9 +9,9 @@ git-ls-remote - List references in a remote repository
>  SYNOPSIS
>  --------
>  [verse]
> -'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>]
> -	      [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
> -	      [--symref] [<repository> [<refs>...]]
> +'git ls-remote' [--count=<count>] [--heads] [--tags] [--refs]
> +	      [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url]
> +	      [--sort=<key>] [--symref] [<repository> [<refs>...]]

It is understandable that the new option is important to _you_, but it does not seem important enough that it must be the first in the list. Please add it between --symref and <repository>

Show 11 quoted lines
>  
>  DESCRIPTION
>  -----------
> @@ -21,6 +21,11 @@ commit IDs.
>  
>  OPTIONS
>  -------
> +--count=<count>::
> +	By default the command shows all refs that match
> +	`<pattern>`.  This option makes it stop after showing
> +	that many refs.
Is the meaning of this option perhaps:
    Stops after the specified count of refs have been listed.
    If `--sort=<key>` is specified as well, refs are counted
    after sorting; otherwise, it is unspecified which subset
    of is listed.

I do not know whether the "otherwise" part would be true (check it!), but I am pretty certain that the "If" part must be true, otherwise the option would be pointless.

The comment about the ordering of this paragraph at the very beginning of the option list applies here, too, because the list is not sorted alphabetically.

-- Hannes
Junio C Hamano· Sep 18, 2019, 17:28 UTC · re: Johannes Sixt · lore

Re: [PATCH] ls-remote: create '--count' option

Johannes Sixt <j6t@kdbg.org> writes:
Show 57 quoted lines
> Am 18.09.19 um 02:11 schrieb Kamil Domański:
>> Create a '--count' option for ls-remote, based on the one from
>> for-each-ref. This allows e.g. to return only the first result
>> from a sorted list of refs.
>> 
>> Signed-off-by: Kamil Domański <kamil@domanski.co>
>> ---
>>  Documentation/git-ls-remote.txt | 11 ++++++++---
>>  builtin/ls-remote.c             | 16 ++++++++++++----
>>  t/t5512-ls-remote.sh            |  9 +++++++++
>>  3 files changed, 29 insertions(+), 7 deletions(-)
>> 
>> diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
>> index 0b057cbb10..5adc1d676e 100644
>> --- a/Documentation/git-ls-remote.txt
>> +++ b/Documentation/git-ls-remote.txt
>> @@ -9,9 +9,9 @@ git-ls-remote - List references in a remote repository
>>  SYNOPSIS
>>  --------
>>  [verse]
>> -'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>]
>> -	      [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
>> -	      [--symref] [<repository> [<refs>...]]
>> +'git ls-remote' [--count=<count>] [--heads] [--tags] [--refs]
>> +	      [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url]
>> +	      [--sort=<key>] [--symref] [<repository> [<refs>...]]
>
> It is understandable that the new option is important to _you_, but it
> does not seem important enough that it must be the first in the list.
> Please add it between --symref and <repository>
>
>>  
>>  DESCRIPTION
>>  -----------
>> @@ -21,6 +21,11 @@ commit IDs.
>>  
>>  OPTIONS
>>  -------
>> +--count=<count>::
>> +	By default the command shows all refs that match
>> +	`<pattern>`.  This option makes it stop after showing
>> +	that many refs.
>
> Is the meaning of this option perhaps:
>
>     Stops after the specified count of refs have been listed.
>     If `--sort=<key>` is specified as well, refs are counted
>     after sorting; otherwise, it is unspecified which subset
>     of is listed.
>
> I do not know whether the "otherwise" part would be true (check it!),
> but I am pretty certain that the "If" part must be true, otherwise the
> option would be pointless.
>
> The comment about the ordering of this paragraph at the very beginning
> of the option list applies here, too, because the list is not sorted
> alphabetically.

All sensible comments and suggestions. I am not sure what's so hard to pipe the output to "head -n 20" or something like that, though.

Kamil Domański· Sep 18, 2019, 21:44 UTC · re: Johannes Sixt · lore

Re: [PATCH] ls-remote: create '--count' option

On 9/18/19 8:28 AM, Johannes Sixt wrote:
Show 29 quoted lines
> Am 18.09.19 um 02:11 schrieb Kamil Domański:
>> Create a '--count' option for ls-remote, based on the one from
>> for-each-ref. This allows e.g. to return only the first result
>> from a sorted list of refs.
>>
>> Signed-off-by: Kamil Domański <kamil@domanski.co>
>> ---
>>   Documentation/git-ls-remote.txt | 11 ++++++++---
>>   builtin/ls-remote.c             | 16 ++++++++++++----
>>   t/t5512-ls-remote.sh            |  9 +++++++++
>>   3 files changed, 29 insertions(+), 7 deletions(-)
>>
>> diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
>> index 0b057cbb10..5adc1d676e 100644
>> --- a/Documentation/git-ls-remote.txt
>> +++ b/Documentation/git-ls-remote.txt
>> @@ -9,9 +9,9 @@ git-ls-remote - List references in a remote repository
>>   SYNOPSIS
>>   --------
>>   [verse]
>> -'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>]
>> -	      [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
>> -	      [--symref] [<repository> [<refs>...]]
>> +'git ls-remote' [--count=<count>] [--heads] [--tags] [--refs]
>> +	      [--upload-pack=<exec>] [-q | --quiet] [--exit-code] [--get-url]
>> +	      [--sort=<key>] [--symref] [<repository> [<refs>...]]
> It is understandable that the new option is important to _you_, but it
> does not seem important enough that it must be the first in the list.
> Please add it between --symref and <repository>

The assumption is quite unnecessary. I merely tried to reflect the position of this parameter in the 'for-each-ref' command, on which I based the patch.

Show 17 quoted lines
>>   
>>   DESCRIPTION
>>   -----------
>> @@ -21,6 +21,11 @@ commit IDs.
>>   
>>   OPTIONS
>>   -------
>> +--count=<count>::
>> +	By default the command shows all refs that match
>> +	`<pattern>`.  This option makes it stop after showing
>> +	that many refs.
> Is the meaning of this option perhaps:
>
>      Stops after the specified count of refs have been listed.
>      If `--sort=<key>` is specified as well, refs are counted
>      after sorting; otherwise, it is unspecified which subset
>      of is listed.

Similarly, I merely copied the description used by 'for-each-ref'. I like your version as well, since it clarifies the relation to sorting. Should the description for 'for-each-ref' be changed as well then?

> I do not know whether the "otherwise" part would be true (check it!),
> but I am pretty certain that the "If" part must be true, otherwise the
> option would be pointless.

Yes, both in 'for-each-ref' as well as this patch, cutting off the results takes place after the whole set has been already sorted. As for the "otherwise" part, it appears that 'for-each-ref' defaults to sorting by 'refname' (through ref_default_sorting() ) if no alternative sorting is provided, while 'ls-remote' does no such defaulting. Do you figure it would be a good idea to add another patch which would introduce a similar default in 'ls-remote'?

Regards,
Kamil
Johannes Sixt· Sep 19, 2019, 18:40 UTC · re: Kamil Domański · lore

Re: [PATCH] ls-remote: create '--count' option

Am 18.09.19 um 23:44 schrieb Kamil Domański:
Show 21 quoted lines
> On 9/18/19 8:28 AM, Johannes Sixt wrote:
>> Am 18.09.19 um 02:11 schrieb Kamil Domański:
>>>     DESCRIPTION
>>>   -----------
>>> @@ -21,6 +21,11 @@ commit IDs.
>>>     OPTIONS
>>>   -------
>>> +--count=<count>::
>>> +    By default the command shows all refs that match
>>> +    `<pattern>`.  This option makes it stop after showing
>>> +    that many refs.
>> Is the meaning of this option perhaps:
>>
>>      Stops after the specified count of refs have been listed.
>>      If `--sort=<key>` is specified as well, refs are counted
>>      after sorting; otherwise, it is unspecified which subset
>>      of is listed.
> 
> Similarly, I merely copied the description used by 'for-each-ref'. I
> like your version as well, since it clarifies the relation to sorting.
> Should the description for 'for-each-ref' be changed as well then?

I am neutral. If you do it, then it should not happen in the same patch as this change.

Show 5 quoted lines
> ... it appears that 'for-each-ref' defaults to sorting
> by 'refname' (through ref_default_sorting() ) if no alternative sorting
> is provided, while 'ls-remote' does no such defaulting. Do you figure it
> would be a good idea to add another patch which would introduce a
> similar default in 'ls-remote'?

I don't think so. I would think that in the case of ls-remote it is preferable to stream refs to the output as soon as they are received from the remote. If refs must be sorted, it would have to wait until the remote has sent all refs before it can do anything.

That said, Junio's question remains open: why is piping though head -n not good enough?

-- Hannes

← back to recent threads