Browse Source
--sort=version:refname (or --sort=v:refname for short) sorts tags as if they are versions. --sort=-refname reverses the order (with or without ":version"). versioncmp() is copied from string/strverscmp.c in glibc commit ee9247c38a8def24a59eb5cfb7196a98bef8cfdc, reformatted to Git coding style. The implementation is under LGPL-2.1 and according to [1] I can relicense it to GPLv2. [1] http://www.gnu.org/licenses/gpl-faq.html#AllCompatibility Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
![pclouds@gmail.com](/assets/img/avatar_default.png)
![Junio C Hamano](/assets/img/avatar_default.png)
6 changed files with 211 additions and 5 deletions
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
#include "cache.h" |
||||
|
||||
/* |
||||
* versioncmp(): copied from string/strverscmp.c in glibc commit |
||||
* ee9247c38a8def24a59eb5cfb7196a98bef8cfdc, reformatted to Git coding |
||||
* style. The implementation is under LGPL-2.1 and Git relicenses it |
||||
* to GPLv2. |
||||
*/ |
||||
|
||||
/* |
||||
* states: S_N: normal, S_I: comparing integral part, S_F: comparing |
||||
* fractionnal parts, S_Z: idem but with leading Zeroes only |
||||
*/ |
||||
#define S_N 0x0 |
||||
#define S_I 0x3 |
||||
#define S_F 0x6 |
||||
#define S_Z 0x9 |
||||
|
||||
/* result_type: CMP: return diff; LEN: compare using len_diff/diff */ |
||||
#define CMP 2 |
||||
#define LEN 3 |
||||
|
||||
|
||||
/* |
||||
* Compare S1 and S2 as strings holding indices/version numbers, |
||||
* returning less than, equal to or greater than zero if S1 is less |
||||
* than, equal to or greater than S2 (for more info, see the texinfo |
||||
* doc). |
||||
*/ |
||||
|
||||
int versioncmp(const char *s1, const char *s2) |
||||
{ |
||||
const unsigned char *p1 = (const unsigned char *) s1; |
||||
const unsigned char *p2 = (const unsigned char *) s2; |
||||
unsigned char c1, c2; |
||||
int state, diff; |
||||
|
||||
/* |
||||
* Symbol(s) 0 [1-9] others |
||||
* Transition (10) 0 (01) d (00) x |
||||
*/ |
||||
static const uint8_t next_state[] = { |
||||
/* state x d 0 */ |
||||
/* S_N */ S_N, S_I, S_Z, |
||||
/* S_I */ S_N, S_I, S_I, |
||||
/* S_F */ S_N, S_F, S_F, |
||||
/* S_Z */ S_N, S_F, S_Z |
||||
}; |
||||
|
||||
static const int8_t result_type[] = { |
||||
/* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */ |
||||
|
||||
/* S_N */ CMP, CMP, CMP, CMP, LEN, CMP, CMP, CMP, CMP, |
||||
/* S_I */ CMP, -1, -1, +1, LEN, LEN, +1, LEN, LEN, |
||||
/* S_F */ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, |
||||
/* S_Z */ CMP, +1, +1, -1, CMP, CMP, -1, CMP, CMP |
||||
}; |
||||
|
||||
if (p1 == p2) |
||||
return 0; |
||||
|
||||
c1 = *p1++; |
||||
c2 = *p2++; |
||||
/* Hint: '0' is a digit too. */ |
||||
state = S_N + ((c1 == '0') + (isdigit (c1) != 0)); |
||||
|
||||
while ((diff = c1 - c2) == 0) { |
||||
if (c1 == '\0') |
||||
return diff; |
||||
|
||||
state = next_state[state]; |
||||
c1 = *p1++; |
||||
c2 = *p2++; |
||||
state += (c1 == '0') + (isdigit (c1) != 0); |
||||
} |
||||
|
||||
state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))]; |
||||
|
||||
switch (state) { |
||||
case CMP: |
||||
return diff; |
||||
|
||||
case LEN: |
||||
while (isdigit (*p1++)) |
||||
if (!isdigit (*p2++)) |
||||
return 1; |
||||
|
||||
return isdigit (*p2) ? -1 : diff; |
||||
|
||||
default: |
||||
return state; |
||||
} |
||||
} |
Loading…
Reference in new issue