Skip to content

Commit c026557

Browse files
szedergitster
authored andcommitted
versioncmp: generalize version sort suffix reordering
The 'versionsort.prereleaseSuffix' configuration variable, as its name suggests, is supposed to only deal with tagnames with prerelease suffixes, and allows sorting those prerelease tags in a user-defined order before the suffixless main release tag, instead of sorting them simply lexicographically. However, the previous changes in this series resulted in an interesting and useful property of version sort: - The empty string as a configured suffix matches all tagnames, including tagnames without any suffix, but - tagnames containing a "real" configured suffix are still ordered according to that real suffix, because any longer suffix takes precedence over the empty string. Exploiting this property we can easily generalize suffix reordering and specify the order of tags with given suffixes not only before but even after a main release tag by using the empty suffix to denote the position of the main release tag, without any algorithm changes: $ git -c versionsort.prereleaseSuffix=-alpha \ -c versionsort.prereleaseSuffix=-beta \ -c versionsort.prereleaseSuffix="" \ -c versionsort.prereleaseSuffix=-gamma \ -c versionsort.prereleaseSuffix=-delta \ tag -l --sort=version:refname 'v3.0*' v3.0-alpha1 v3.0-beta1 v3.0 v3.0-gamma1 v3.0-delta1 Since 'versionsort.prereleaseSuffix' is not a fitting name for a configuration variable to control this more general suffix reordering, introduce the new variable 'versionsort.suffix'. Still keep the old configuration variable name as a deprecated alias, though, to avoid suddenly breaking setups already using it. Ignore the old variable if both old and new configuration variables are set, but emit a warning so users will be aware of it and can fix their configuration. Extend the documentation to describe and add a test to check this more general behavior. Note: since the empty suffix matches all tagnames, tagnames with suffixes not included in the configuration are listed together with the suffixless main release tag, ordered lexicographically right after that, i.e. before tags with suffixes listed in the configuration following the empty suffix. Signed-off-by: SZEDER Gábor <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent b178464 commit c026557

File tree

4 files changed

+71
-13
lines changed

4 files changed

+71
-13
lines changed

Documentation/config.txt

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,16 +3038,32 @@ user.signingKey::
30383038
This option is passed unchanged to gpg's --local-user parameter,
30393039
so you may specify a key using any method that gpg supports.
30403040

3041-
versionsort.prereleaseSuffix::
3042-
When version sort is used in linkgit:git-tag[1], prerelease
3043-
tags (e.g. "1.0-rc1") may appear after the main release
3044-
"1.0". By specifying the suffix "-rc" in this variable,
3045-
"1.0-rc1" will appear before "1.0".
3046-
+
3047-
This variable can be specified multiple times, once per suffix. The
3048-
order of suffixes in the config file determines the sorting order
3049-
(e.g. if "-pre" appears before "-rc" in the config file then 1.0-preXX
3050-
is sorted before 1.0-rcXX).
3041+
versionsort.prereleaseSuffix (deprecated)::
3042+
Deprecated alias for `versionsort.suffix`. Ignored if
3043+
`versionsort.suffix` is set.
3044+
3045+
versionsort.suffix::
3046+
Even when version sort is used in linkgit:git-tag[1], tagnames
3047+
with the same base version but different suffixes are still sorted
3048+
lexicographically, resulting e.g. in prerelease tags appearing
3049+
after the main release (e.g. "1.0-rc1" after "1.0"). This
3050+
variable can be specified to determine the sorting order of tags
3051+
with different suffixes.
3052+
+
3053+
By specifying a single suffix in this variable, any tagname containing
3054+
that suffix will appear before the corresponding main release. E.g. if
3055+
the variable is set to "-rc", then all "1.0-rcX" tags will appear before
3056+
"1.0". If specified multiple times, once per suffix, then the order of
3057+
suffixes in the configuration will determine the sorting order of tagnames
3058+
with those suffixes. E.g. if "-pre" appears before "-rc" in the
3059+
configuration, then all "1.0-preX" tags will be listed before any
3060+
"1.0-rcX" tags. The placement of the main release tag relative to tags
3061+
with various suffixes can be determined by specifying the empty suffix
3062+
among those other suffixes. E.g. if the suffixes "-rc", "", "-ck" and
3063+
"-bfs" appear in the configuration in this order, then all "v4.8-rcX" tags
3064+
are listed first, followed by "v4.8", then "v4.8-ckX" and finally
3065+
"v4.8-bfsX".
3066+
+
30513067
If more than one suffixes match the same tagname, then that tagname will
30523068
be sorted according to the suffix which starts at the earliest position in
30533069
the tagname. If more than one different matching suffixes start at

Documentation/git-tag.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ OPTIONS
101101
multiple times, in which case the last key becomes the primary
102102
key. Also supports "version:refname" or "v:refname" (tag
103103
names are treated as versions). The "version:refname" sort
104-
order can also be affected by the
105-
"versionsort.prereleaseSuffix" configuration variable.
104+
order can also be affected by the "versionsort.suffix"
105+
configuration variable.
106106
The keys supported are the same as those in `git for-each-ref`.
107107
Sort order defaults to the value configured for the `tag.sort`
108108
variable if it exists, or lexicographic order otherwise. See

t/t7004-tag.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,41 @@ test_expect_success 'version sort with prerelease reordering, multiple suffixes
15951595
test_cmp expect actual
15961596
'
15971597

1598+
test_expect_success 'version sort with general suffix reordering' '
1599+
test_config versionsort.suffix -alpha &&
1600+
git config --add versionsort.suffix -beta &&
1601+
git config --add versionsort.suffix "" &&
1602+
git config --add versionsort.suffix -gamma &&
1603+
git config --add versionsort.suffix -delta &&
1604+
git tag foo1.10-alpha &&
1605+
git tag foo1.10-beta &&
1606+
git tag foo1.10-gamma &&
1607+
git tag foo1.10-delta &&
1608+
git tag foo1.10-unlisted-suffix &&
1609+
git tag -l --sort=version:refname "foo1.10*" >actual &&
1610+
cat >expect <<-\EOF &&
1611+
foo1.10-alpha
1612+
foo1.10-beta
1613+
foo1.10
1614+
foo1.10-unlisted-suffix
1615+
foo1.10-gamma
1616+
foo1.10-delta
1617+
EOF
1618+
test_cmp expect actual
1619+
'
1620+
1621+
test_expect_success 'versionsort.suffix overrides versionsort.prereleaseSuffix' '
1622+
test_config versionsort.suffix -before &&
1623+
test_config versionsort.prereleaseSuffix -after &&
1624+
git tag -l --sort=version:refname "foo1.7*" >actual &&
1625+
cat >expect <<-\EOF &&
1626+
foo1.7-before1
1627+
foo1.7
1628+
foo1.7-after1
1629+
EOF
1630+
test_cmp expect actual
1631+
'
1632+
15981633
test_expect_success 'version sort with very long prerelease suffix' '
15991634
test_config versionsort.prereleaseSuffix -very-looooooooooooooooooooooooong-prerelease-suffix &&
16001635
git tag -l --sort=version:refname

versioncmp.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,15 @@ int versioncmp(const char *s1, const char *s2)
159159
}
160160

161161
if (!initialized) {
162+
const struct string_list *deprecated_prereleases;
162163
initialized = 1;
163-
prereleases = git_config_get_value_multi("versionsort.prereleasesuffix");
164+
prereleases = git_config_get_value_multi("versionsort.suffix");
165+
deprecated_prereleases = git_config_get_value_multi("versionsort.prereleasesuffix");
166+
if (prereleases) {
167+
if (deprecated_prereleases)
168+
warning("ignoring versionsort.prereleasesuffix because versionsort.suffix is set");
169+
} else
170+
prereleases = deprecated_prereleases;
164171
}
165172
if (prereleases && swap_prereleases(s1, s2, (const char *) p1 - s1 - 1,
166173
&diff))

0 commit comments

Comments
 (0)