versionsort: support reorder prerelease suffixes
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									fdf96a20ac
								
							
						
					
					
						commit
						d811c8e17c
					
				|  | @ -2523,6 +2523,13 @@ user.signingkey:: | ||||||
| 	This option is passed unchanged to gpg's --local-user parameter, | 	This option is passed unchanged to gpg's --local-user parameter, | ||||||
| 	so you may specify a key using any method that gpg supports. | 	so you may specify a key using any method that gpg supports. | ||||||
|  |  | ||||||
|  | versionsort.prereleaseSuffix:: | ||||||
|  | 	When version sort is used in linkgit:git-tag[1], prerelease | ||||||
|  | 	tags (e.g. "1.0-rc1") may appear after the main release | ||||||
|  | 	"1.0". By specifying the suffix "-rc" in this variable, | ||||||
|  | 	"1.0-rc1" will appear before "1.0". One variable assignment | ||||||
|  | 	per suffix. | ||||||
|  |  | ||||||
| web.browser:: | web.browser:: | ||||||
| 	Specify a web browser that may be used by some commands. | 	Specify a web browser that may be used by some commands. | ||||||
| 	Currently only linkgit:git-instaweb[1] and linkgit:git-help[1] | 	Currently only linkgit:git-instaweb[1] and linkgit:git-help[1] | ||||||
|  |  | ||||||
|  | @ -1459,6 +1459,34 @@ test_expect_success 'invalid sort parameter in configuratoin' ' | ||||||
| 	test_cmp expect actual | 	test_cmp expect actual | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | test_expect_success 'version sort with prerelease reordering' ' | ||||||
|  | 	git config --unset tag.sort && | ||||||
|  | 	git config versionsort.prereleaseSuffix -rc && | ||||||
|  | 	git tag foo1.6-rc1 && | ||||||
|  | 	git tag foo1.6-rc2 && | ||||||
|  | 	git tag -l --sort=version:refname "foo*" >actual && | ||||||
|  | 	cat >expect <<-\EOF && | ||||||
|  | 	foo1.3 | ||||||
|  | 	foo1.6-rc1 | ||||||
|  | 	foo1.6-rc2 | ||||||
|  | 	foo1.6 | ||||||
|  | 	foo1.10 | ||||||
|  | 	EOF | ||||||
|  | 	test_cmp expect actual | ||||||
|  | ' | ||||||
|  |  | ||||||
|  | test_expect_success 'reverse version sort with prerelease reordering' ' | ||||||
|  | 	git tag -l --sort=-version:refname "foo*" >actual && | ||||||
|  | 	cat >expect <<-\EOF && | ||||||
|  | 	foo1.10 | ||||||
|  | 	foo1.6 | ||||||
|  | 	foo1.6-rc2 | ||||||
|  | 	foo1.6-rc1 | ||||||
|  | 	foo1.3 | ||||||
|  | 	EOF | ||||||
|  | 	test_cmp expect actual | ||||||
|  | ' | ||||||
|  |  | ||||||
| run_with_limited_stack () { | run_with_limited_stack () { | ||||||
| 	(ulimit -s 128 && "$@") | 	(ulimit -s 128 && "$@") | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								versioncmp.c
								
								
								
								
							
							
						
						
									
										50
									
								
								versioncmp.c
								
								
								
								
							|  | @ -1,4 +1,5 @@ | ||||||
| #include "cache.h" | #include "cache.h" | ||||||
|  | #include "string-list.h" | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * versioncmp(): copied from string/strverscmp.c in glibc commit |  * versioncmp(): copied from string/strverscmp.c in glibc commit | ||||||
|  | @ -20,6 +21,48 @@ | ||||||
| #define  CMP    2 | #define  CMP    2 | ||||||
| #define  LEN    3 | #define  LEN    3 | ||||||
|  |  | ||||||
|  | static const struct string_list *prereleases; | ||||||
|  | static int initialized; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * p1 and p2 point to the first different character in two strings. If | ||||||
|  |  * either p1 or p2 starts with a prerelease suffix, it will be forced | ||||||
|  |  * to be on top. | ||||||
|  |  * | ||||||
|  |  * If both p1 and p2 start with (different) suffix, the order is | ||||||
|  |  * determined by config file. | ||||||
|  |  * | ||||||
|  |  * Note that we don't have to deal with the situation when both p1 and | ||||||
|  |  * p2 start with the same suffix because the common part is already | ||||||
|  |  * consumed by the caller. | ||||||
|  |  * | ||||||
|  |  * Return non-zero if *diff contains the return value for versioncmp() | ||||||
|  |  */ | ||||||
|  | static int swap_prereleases(const void *p1_, | ||||||
|  | 			    const void *p2_, | ||||||
|  | 			    int *diff) | ||||||
|  | { | ||||||
|  | 	const char *p1 = p1_; | ||||||
|  | 	const char *p2 = p2_; | ||||||
|  | 	int i, i1 = -1, i2 = -1; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < prereleases->nr; i++) { | ||||||
|  | 		const char *suffix = prereleases->items[i].string; | ||||||
|  | 		if (i1 == -1 && starts_with(p1, suffix)) | ||||||
|  | 			i1 = i; | ||||||
|  | 		if (i2 == -1 && starts_with(p2, suffix)) | ||||||
|  | 			i2 = i; | ||||||
|  | 	} | ||||||
|  | 	if (i1 == -1 && i2 == -1) | ||||||
|  | 		return 0; | ||||||
|  | 	if (i1 >= 0 && i2 >= 0) | ||||||
|  | 		*diff = i1 - i2; | ||||||
|  | 	else if (i1 >= 0) | ||||||
|  | 		*diff = -1; | ||||||
|  | 	else /* if (i2 >= 0) */ | ||||||
|  | 		*diff = 1; | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Compare S1 and S2 as strings holding indices/version numbers, |  * Compare S1 and S2 as strings holding indices/version numbers, | ||||||
|  | @ -74,6 +117,13 @@ int versioncmp(const char *s1, const char *s2) | ||||||
| 		state += (c1 == '0') + (isdigit (c1) != 0); | 		state += (c1 == '0') + (isdigit (c1) != 0); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (!initialized) { | ||||||
|  | 		initialized = 1; | ||||||
|  | 		prereleases = git_config_get_value_multi("versionsort.prereleasesuffix"); | ||||||
|  | 	} | ||||||
|  | 	if (prereleases && swap_prereleases(p1 - 1, p2 - 1, &diff)) | ||||||
|  | 		return diff; | ||||||
|  |  | ||||||
| 	state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))]; | 	state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))]; | ||||||
|  |  | ||||||
| 	switch (state) { | 	switch (state) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy