Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Nguyễn Thái Ngọc Duy authored and Junio C Hamano committed Feb 27, 2015
1 parent fdf96a2 commit d811c8e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Documentation/config.txt
Expand Up @@ -2523,6 +2523,13 @@ user.signingkey::
This option is passed unchanged to gpg's --local-user parameter,
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::
Specify a web browser that may be used by some commands.
Currently only linkgit:git-instaweb[1] and linkgit:git-help[1]
Expand Down
28 changes: 28 additions & 0 deletions t/t7004-tag.sh
Expand Up @@ -1459,6 +1459,34 @@ test_expect_success 'invalid sort parameter in configuratoin' '
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 () {
(ulimit -s 128 && "$@")
}
Expand Down
50 changes: 50 additions & 0 deletions versioncmp.c
@@ -1,4 +1,5 @@
#include "cache.h"
#include "string-list.h"

/*
* versioncmp(): copied from string/strverscmp.c in glibc commit
Expand All @@ -20,6 +21,48 @@
#define CMP 2
#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,
Expand Down Expand Up @@ -74,6 +117,13 @@ int versioncmp(const char *s1, const char *s2)
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)))];

switch (state) {
Expand Down

0 comments on commit d811c8e

Please sign in to comment.