diff --git a/semver.py b/semver.py index d82718b..4d1c6eb 100644 --- a/semver.py +++ b/semver.py @@ -146,13 +146,29 @@ def compare(ver1, ver2): """ def nat_cmp(a, b): def convert(text): - return (2, int(text)) if re.match('[0-9]+', text) else (1, text) + return int(text) if re.match('[0-9]+', text) else text def split_key(key): return [convert(c) for c in key.split('.')] + def cmp_prerelease_tag(a, b): + if isinstance(a, int) and isinstance(b, int): + return cmp(a, b) + elif isinstance(a, int): + return -1 + elif isinstance(b, int): + return 1 + else: + return cmp(a, b) + a, b = a or '', b or '' - return cmp(split_key(a), split_key(b)) + a_parts, b_parts = split_key(a), split_key(b) + for sub_a, sub_b in zip(a_parts, b_parts): + cmp_result = cmp_prerelease_tag(sub_a, sub_b) + if cmp_result != 0: + return cmp_result + else: + return cmp(len(a), len(b)) def compare_by_keys(d1, d2): for key in ['major', 'minor', 'patch']: diff --git a/tests.py b/tests.py index 5681aef..1e724ef 100644 --- a/tests.py +++ b/tests.py @@ -70,10 +70,24 @@ def test_should_parse_zero_prerelease(): def test_should_get_less(): assert compare("1.0.0", "2.0.0") == -1 + assert compare('1.0.0-alpha', '1.0.0-alpha.1') == -1 + assert compare('1.0.0-alpha.1', '1.0.0-alpha.beta') == -1 + assert compare('1.0.0-alpha.beta', '1.0.0-beta') == -1 + assert compare('1.0.0-beta', '1.0.0-beta.2') == -1 + assert compare('1.0.0-beta.2', '1.0.0-beta.11') == -1 + assert compare('1.0.0-beta.11', '1.0.0-rc.1') == -1 + assert compare('1.0.0-rc.1', '1.0.0') == -1 def test_should_get_greater(): assert compare("2.0.0", "1.0.0") == 1 + assert compare('1.0.0-alpha.1', '1.0.0-alpha') == 1 + assert compare('1.0.0-alpha.beta', '1.0.0-alpha.1') == 1 + assert compare('1.0.0-beta', '1.0.0-alpha.beta') == 1 + assert compare('1.0.0-beta.2', '1.0.0-beta') == 1 + assert compare('1.0.0-beta.11', '1.0.0-beta.2') == 1 + assert compare('1.0.0-rc.1', '1.0.0-beta.11') == 1 + assert compare('1.0.0', '1.0.0-rc.1') == 1 def test_should_match_simple(): @@ -232,7 +246,7 @@ def test_prerelease_order(): assert min_ver('1.2.3-Rc10', '1.2.3-rc10') == '1.2.3-Rc10' # Numeric identifiers always have lower precedence than non-numeric # identifiers. - assert min_ver('1.2.3-2', '1.2.3-rc') == '1.2.3-rc' + assert min_ver('1.2.3-2', '1.2.3-rc') == '1.2.3-2' # A larger set of pre-release fields has a higher precedence than a # smaller set, if all of the preceding identifiers are equal. assert min_ver('1.2.3-rc.2.1', '1.2.3-rc.2') == '1.2.3-rc.2'