Skip to content

Commit d811c8e

Browse files
pcloudsgitster
authored andcommitted
versionsort: support reorder prerelease suffixes
Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent fdf96a2 commit d811c8e

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

Documentation/config.txt

+7
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,13 @@ user.signingkey::
25232523
This option is passed unchanged to gpg's --local-user parameter,
25242524
so you may specify a key using any method that gpg supports.
25252525

2526+
versionsort.prereleaseSuffix::
2527+
When version sort is used in linkgit:git-tag[1], prerelease
2528+
tags (e.g. "1.0-rc1") may appear after the main release
2529+
"1.0". By specifying the suffix "-rc" in this variable,
2530+
"1.0-rc1" will appear before "1.0". One variable assignment
2531+
per suffix.
2532+
25262533
web.browser::
25272534
Specify a web browser that may be used by some commands.
25282535
Currently only linkgit:git-instaweb[1] and linkgit:git-help[1]

t/t7004-tag.sh

+28
Original file line numberDiff line numberDiff line change
@@ -1459,6 +1459,34 @@ test_expect_success 'invalid sort parameter in configuratoin' '
14591459
test_cmp expect actual
14601460
'
14611461
1462+
test_expect_success 'version sort with prerelease reordering' '
1463+
git config --unset tag.sort &&
1464+
git config versionsort.prereleaseSuffix -rc &&
1465+
git tag foo1.6-rc1 &&
1466+
git tag foo1.6-rc2 &&
1467+
git tag -l --sort=version:refname "foo*" >actual &&
1468+
cat >expect <<-\EOF &&
1469+
foo1.3
1470+
foo1.6-rc1
1471+
foo1.6-rc2
1472+
foo1.6
1473+
foo1.10
1474+
EOF
1475+
test_cmp expect actual
1476+
'
1477+
1478+
test_expect_success 'reverse version sort with prerelease reordering' '
1479+
git tag -l --sort=-version:refname "foo*" >actual &&
1480+
cat >expect <<-\EOF &&
1481+
foo1.10
1482+
foo1.6
1483+
foo1.6-rc2
1484+
foo1.6-rc1
1485+
foo1.3
1486+
EOF
1487+
test_cmp expect actual
1488+
'
1489+
14621490
run_with_limited_stack () {
14631491
(ulimit -s 128 && "$@")
14641492
}

versioncmp.c

+50
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "cache.h"
2+
#include "string-list.h"
23

34
/*
45
* versioncmp(): copied from string/strverscmp.c in glibc commit
@@ -20,6 +21,48 @@
2021
#define CMP 2
2122
#define LEN 3
2223

24+
static const struct string_list *prereleases;
25+
static int initialized;
26+
27+
/*
28+
* p1 and p2 point to the first different character in two strings. If
29+
* either p1 or p2 starts with a prerelease suffix, it will be forced
30+
* to be on top.
31+
*
32+
* If both p1 and p2 start with (different) suffix, the order is
33+
* determined by config file.
34+
*
35+
* Note that we don't have to deal with the situation when both p1 and
36+
* p2 start with the same suffix because the common part is already
37+
* consumed by the caller.
38+
*
39+
* Return non-zero if *diff contains the return value for versioncmp()
40+
*/
41+
static int swap_prereleases(const void *p1_,
42+
const void *p2_,
43+
int *diff)
44+
{
45+
const char *p1 = p1_;
46+
const char *p2 = p2_;
47+
int i, i1 = -1, i2 = -1;
48+
49+
for (i = 0; i < prereleases->nr; i++) {
50+
const char *suffix = prereleases->items[i].string;
51+
if (i1 == -1 && starts_with(p1, suffix))
52+
i1 = i;
53+
if (i2 == -1 && starts_with(p2, suffix))
54+
i2 = i;
55+
}
56+
if (i1 == -1 && i2 == -1)
57+
return 0;
58+
if (i1 >= 0 && i2 >= 0)
59+
*diff = i1 - i2;
60+
else if (i1 >= 0)
61+
*diff = -1;
62+
else /* if (i2 >= 0) */
63+
*diff = 1;
64+
return 1;
65+
}
2366

2467
/*
2568
* Compare S1 and S2 as strings holding indices/version numbers,
@@ -74,6 +117,13 @@ int versioncmp(const char *s1, const char *s2)
74117
state += (c1 == '0') + (isdigit (c1) != 0);
75118
}
76119

120+
if (!initialized) {
121+
initialized = 1;
122+
prereleases = git_config_get_value_multi("versionsort.prereleasesuffix");
123+
}
124+
if (prereleases && swap_prereleases(p1 - 1, p2 - 1, &diff))
125+
return diff;
126+
77127
state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
78128

79129
switch (state) {

0 commit comments

Comments
 (0)