ls-remote: create '--sort' option
Create a '--sort' option for ls-remote, based on the one from for-each-ref. This e.g. allows ref names to be sorted by version semantics, so that v1.2 is sorted before v1.10. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									427cbc9dbf
								
							
						
					
					
						commit
						1fb20dfd8e
					
				|  | @ -10,7 +10,7 @@ SYNOPSIS | |||
| -------- | ||||
| [verse] | ||||
| 'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>] | ||||
| 	      [-q | --quiet] [--exit-code] [--get-url] | ||||
| 	      [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>] | ||||
| 	      [--symref] [<repository> [<refs>...]] | ||||
|  | ||||
| DESCRIPTION | ||||
|  | @ -60,6 +60,16 @@ OPTIONS | |||
| 	upload-pack only shows the symref HEAD, so it will be the only | ||||
| 	one shown by ls-remote. | ||||
|  | ||||
| --sort=<key>:: | ||||
| 	Sort based on the key given. Prefix `-` to sort in descending order | ||||
| 	of the value. Supports "version:refname" or "v:refname" (tag names | ||||
| 	are treated as versions). The "version:refname" sort order can also | ||||
| 	be affected by the "versionsort.suffix" configuration variable. | ||||
| 	See linkgit:git-for-each-ref[1] for more sort options, but be aware | ||||
| 	keys like `committerdate` that require access to the objects | ||||
| 	themselves will not work for refs whose objects have not yet been | ||||
| 	fetched from the remote, and will give a `missing object` error. | ||||
|  | ||||
| <repository>:: | ||||
| 	The "remote" repository to query.  This parameter can be | ||||
| 	either a URL or the name of a remote (see the GIT URLS and | ||||
|  | @ -90,6 +100,10 @@ EXAMPLES | |||
| 	c5db5456ae3b0873fc659c19fafdde22313cc441	refs/tags/v0.99.2 | ||||
| 	7ceca275d047c90c0c7d5afb13ab97efdf51bd6e	refs/tags/v0.99.3 | ||||
|  | ||||
| SEE ALSO | ||||
| -------- | ||||
| linkgit:git-check-ref-format[1]. | ||||
|  | ||||
| GIT | ||||
| --- | ||||
| Part of the linkgit:git[1] suite | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| #include "builtin.h" | ||||
| #include "cache.h" | ||||
| #include "transport.h" | ||||
| #include "ref-filter.h" | ||||
| #include "remote.h" | ||||
|  | ||||
| static const char * const ls_remote_usage[] = { | ||||
|  | @ -43,10 +44,13 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) | |||
| 	int show_symref_target = 0; | ||||
| 	const char *uploadpack = NULL; | ||||
| 	const char **pattern = NULL; | ||||
| 	int i; | ||||
|  | ||||
| 	struct remote *remote; | ||||
| 	struct transport *transport; | ||||
| 	const struct ref *ref; | ||||
| 	struct ref_array ref_array; | ||||
| 	static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; | ||||
|  | ||||
| 	struct option options[] = { | ||||
| 		OPT__QUIET(&quiet, N_("do not print remote URL")), | ||||
|  | @ -60,6 +64,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) | |||
| 		OPT_BIT(0, "refs", &flags, N_("do not show peeled tags"), REF_NORMAL), | ||||
| 		OPT_BOOL(0, "get-url", &get_url, | ||||
| 			 N_("take url.<base>.insteadOf into account")), | ||||
| 		OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"), | ||||
| 			     N_("field name to sort on"), &parse_opt_ref_sorting), | ||||
| 		OPT_SET_INT_F(0, "exit-code", &status, | ||||
| 			      N_("exit with exit code 2 if no matching refs are found"), | ||||
| 			      2, PARSE_OPT_NOCOMPLETE), | ||||
|  | @ -68,6 +74,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) | |||
| 		OPT_END() | ||||
| 	}; | ||||
|  | ||||
| 	memset(&ref_array, 0, sizeof(ref_array)); | ||||
|  | ||||
| 	argc = parse_options(argc, argv, prefix, options, ls_remote_usage, | ||||
| 			     PARSE_OPT_STOP_AT_NON_OPTION); | ||||
| 	dest = argv[0]; | ||||
|  | @ -90,6 +98,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) | |||
|  | ||||
| 	if (get_url) { | ||||
| 		printf("%s\n", *remote->url); | ||||
| 		UNLEAK(sorting); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
|  | @ -98,20 +107,35 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix) | |||
| 		transport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack); | ||||
|  | ||||
| 	ref = transport_get_remote_refs(transport); | ||||
| 	if (transport_disconnect(transport)) | ||||
| 	if (transport_disconnect(transport)) { | ||||
| 		UNLEAK(sorting); | ||||
| 		return 1; | ||||
| 	} | ||||
|  | ||||
| 	if (!dest && !quiet) | ||||
| 		fprintf(stderr, "From %s\n", *remote->url); | ||||
| 	for ( ; ref; ref = ref->next) { | ||||
| 		struct ref_array_item *item; | ||||
| 		if (!check_ref_type(ref, flags)) | ||||
| 			continue; | ||||
| 		if (!tail_match(pattern, ref->name)) | ||||
| 			continue; | ||||
| 		item = ref_array_push(&ref_array, ref->name, &ref->old_oid); | ||||
| 		item->symref = xstrdup_or_null(ref->symref); | ||||
| 	} | ||||
|  | ||||
| 	if (sorting) | ||||
| 		ref_array_sort(sorting, &ref_array); | ||||
|  | ||||
| 	for (i = 0; i < ref_array.nr; 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->name); | ||||
| 		printf("%s\t%s\n", oid_to_hex(&ref->old_oid), ref->name); | ||||
| 			printf("ref: %s\t%s\n", ref->symref, ref->refname); | ||||
| 		printf("%s\t%s\n", oid_to_hex(&ref->objectname), ref->refname); | ||||
| 		status = 0; /* we found something */ | ||||
| 	} | ||||
|  | ||||
| 	UNLEAK(sorting); | ||||
| 	UNLEAK(ref_array); | ||||
| 	return status; | ||||
| } | ||||
|  |  | |||
|  | @ -10,6 +10,9 @@ test_expect_success setup ' | |||
| 	test_tick && | ||||
| 	git commit -m initial && | ||||
| 	git tag mark && | ||||
| 	git tag mark1.1 && | ||||
| 	git tag mark1.2 && | ||||
| 	git tag mark1.10 && | ||||
| 	git show-ref --tags -d | sed -e "s/ /	/" >expected.tag && | ||||
| 	( | ||||
| 		echo "$(git rev-parse HEAD)	HEAD" | ||||
|  | @ -39,6 +42,39 @@ test_expect_success 'ls-remote self' ' | |||
| 	test_cmp expected.all actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'ls-remote --sort="version:refname" --tags self' ' | ||||
| 	cat >expect <<-EOF && | ||||
| 	$(git rev-parse mark)	refs/tags/mark | ||||
| 	$(git rev-parse mark1.1)	refs/tags/mark1.1 | ||||
| 	$(git rev-parse mark1.2)	refs/tags/mark1.2 | ||||
| 	$(git rev-parse mark1.10)	refs/tags/mark1.10 | ||||
| 	EOF | ||||
| 	git ls-remote --sort="version:refname" --tags self >actual && | ||||
| 	test_cmp expect actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'ls-remote --sort="-version:refname" --tags self' ' | ||||
| 	cat >expect <<-EOF && | ||||
| 	$(git rev-parse mark1.10)	refs/tags/mark1.10 | ||||
| 	$(git rev-parse mark1.2)	refs/tags/mark1.2 | ||||
| 	$(git rev-parse mark1.1)	refs/tags/mark1.1 | ||||
| 	$(git rev-parse mark)	refs/tags/mark | ||||
| 	EOF | ||||
| 	git ls-remote --sort="-version:refname" --tags self >actual && | ||||
| 	test_cmp expect actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'ls-remote --sort="-refname" --tags self' ' | ||||
| 	cat >expect <<-EOF && | ||||
| 	$(git rev-parse mark1.2)	refs/tags/mark1.2 | ||||
| 	$(git rev-parse mark1.10)	refs/tags/mark1.10 | ||||
| 	$(git rev-parse mark1.1)	refs/tags/mark1.1 | ||||
| 	$(git rev-parse mark)	refs/tags/mark | ||||
| 	EOF | ||||
| 	git ls-remote --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 | ||||
| ' | ||||
|  | @ -131,7 +167,7 @@ test_expect_success 'Report no-match with --exit-code' ' | |||
|  | ||||
| test_expect_success 'Report match with --exit-code' ' | ||||
| 	git ls-remote --exit-code other.git "refs/tags/*" >actual && | ||||
| 	git ls-remote . tags/mark >expect && | ||||
| 	git ls-remote . tags/mark* >expect && | ||||
| 	test_cmp expect actual | ||||
| ' | ||||
|  | ||||
|  | @ -170,14 +206,18 @@ test_expect_success 'overrides work between mixed transfer/upload-pack hideRefs' | |||
| 	grep refs/tags/magic actual | ||||
| ' | ||||
|  | ||||
| git fetch origin | ||||
| test_expect_success 'ls-remote --symref' ' | ||||
| 	cat >expect <<-\EOF && | ||||
| 	cat >expect <<-EOF && | ||||
| 	ref: refs/heads/master	HEAD | ||||
| 	1bd44cb9d13204b0fe1958db0082f5028a16eb3a	HEAD | ||||
| 	1bd44cb9d13204b0fe1958db0082f5028a16eb3a	refs/heads/master | ||||
| 	1bd44cb9d13204b0fe1958db0082f5028a16eb3a	refs/remotes/origin/HEAD | ||||
| 	1bd44cb9d13204b0fe1958db0082f5028a16eb3a	refs/remotes/origin/master | ||||
| 	1bd44cb9d13204b0fe1958db0082f5028a16eb3a	refs/tags/mark | ||||
| 	$(git rev-parse HEAD)	HEAD | ||||
| 	$(git rev-parse refs/heads/master)	refs/heads/master | ||||
| 	$(git rev-parse HEAD)	refs/remotes/origin/HEAD | ||||
| 	$(git rev-parse refs/remotes/origin/master)	refs/remotes/origin/master | ||||
| 	$(git rev-parse refs/tags/mark)	refs/tags/mark | ||||
| 	$(git rev-parse refs/tags/mark1.1)	refs/tags/mark1.1 | ||||
| 	$(git rev-parse refs/tags/mark1.10)	refs/tags/mark1.10 | ||||
| 	$(git rev-parse refs/tags/mark1.2)	refs/tags/mark1.2 | ||||
| 	EOF | ||||
| 	git ls-remote --symref >actual && | ||||
| 	test_cmp expect actual | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Harald Nordgren
						Harald Nordgren