2023-11-15 21:31:08 +01:00
|
|
|
# Copyright 2011 Corentin Chary <corentin.chary@gmail.com>
|
|
|
|
# Copyright 2020-2023 src_prepare group
|
|
|
|
# Distributed under the terms of the GNU General Public License v2
|
|
|
|
|
2012-07-02 11:20:52 +02:00
|
|
|
import re
|
|
|
|
|
2012-08-11 13:31:57 +02:00
|
|
|
gentoo_unstable = ("alpha", "beta", "pre", "rc")
|
|
|
|
gentoo_types = ("alpha", "beta", "pre", "rc", "p")
|
|
|
|
|
2012-08-07 09:39:49 +02:00
|
|
|
|
2012-07-20 09:04:15 +02:00
|
|
|
def is_version_type_stable(version_type):
|
2012-08-11 13:31:57 +02:00
|
|
|
return version_type not in gentoo_unstable
|
2012-07-20 09:04:15 +02:00
|
|
|
|
2012-08-07 09:39:49 +02:00
|
|
|
|
2012-07-20 09:04:15 +02:00
|
|
|
def is_version_stable(version):
|
|
|
|
return is_version_type_stable(get_version_type(version))
|
|
|
|
|
2012-08-07 09:39:49 +02:00
|
|
|
|
2012-07-20 09:04:15 +02:00
|
|
|
def get_version_type(version):
|
|
|
|
types = []
|
|
|
|
|
2013-03-09 12:07:47 +01:00
|
|
|
if "9999" in version or "99999999" in version:
|
|
|
|
return "live"
|
|
|
|
|
2012-07-20 09:04:15 +02:00
|
|
|
for token in re.findall("[\._-]([a-zA-Z]+)", version):
|
|
|
|
if token in gentoo_types:
|
|
|
|
types.append(token)
|
|
|
|
if types:
|
|
|
|
return types[0] # TODO: consider returning all types
|
|
|
|
return "release"
|
|
|
|
|
2023-11-14 22:03:53 +01:00
|
|
|
|
2012-07-02 11:20:52 +02:00
|
|
|
# Stolen from pkg_resources, but importing it is not a good idea
|
|
|
|
|
2023-11-14 22:03:53 +01:00
|
|
|
component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
|
|
|
|
replace = {"pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@"}.get
|
2012-08-07 09:39:49 +02:00
|
|
|
|
2012-07-02 11:20:52 +02:00
|
|
|
|
|
|
|
def _parse_version_parts(s):
|
|
|
|
for part in component_re.split(s):
|
2012-08-07 09:39:49 +02:00
|
|
|
part = replace(part, part)
|
2023-11-14 22:03:53 +01:00
|
|
|
if not part or part == ".":
|
2012-07-02 11:20:52 +02:00
|
|
|
continue
|
2023-11-14 22:03:53 +01:00
|
|
|
if part[:1] in "0123456789":
|
|
|
|
yield part.zfill(8) # pad for numeric comparison
|
2012-07-02 11:20:52 +02:00
|
|
|
else:
|
2023-11-14 22:03:53 +01:00
|
|
|
yield "*" + part
|
2012-07-02 11:20:52 +02:00
|
|
|
|
2023-11-14 22:03:53 +01:00
|
|
|
yield "*final" # ensure that alpha/beta/candidate are before final
|
2012-07-02 11:20:52 +02:00
|
|
|
|
2012-08-07 09:39:49 +02:00
|
|
|
|
2012-07-02 11:20:52 +02:00
|
|
|
def parse_version(s):
|
|
|
|
"""Convert a version string to a chronologically-sortable key
|
|
|
|
|
|
|
|
This is a rough cross between distutils' StrictVersion and LooseVersion;
|
|
|
|
if you give it versions that would work with StrictVersion, then it behaves
|
|
|
|
the same; otherwise it acts like a slightly-smarter LooseVersion. It is
|
|
|
|
*possible* to create pathological version coding schemes that will fool
|
|
|
|
this parser, but they should be very rare in practice.
|
|
|
|
|
|
|
|
The returned value will be a tuple of strings. Numeric portions of the
|
|
|
|
version are padded to 8 digits so they will compare numerically, but
|
|
|
|
without relying on how numbers compare relative to strings. Dots are
|
|
|
|
dropped, but dashes are retained. Trailing zeros between alpha segments
|
|
|
|
or dashes are suppressed, so that e.g. "2.4.0" is considered the same as
|
|
|
|
"2.4". Alphanumeric parts are lower-cased.
|
|
|
|
|
|
|
|
The algorithm assumes that strings like "-" and any alpha string that
|
|
|
|
alphabetically follows "final" represents a "patch level". So, "2.4-1"
|
|
|
|
is assumed to be a branch or patch of "2.4", and therefore "2.4.1" is
|
|
|
|
considered newer than "2.4-1", which in turn is newer than "2.4".
|
|
|
|
|
|
|
|
Strings like "a", "b", "c", "alpha", "beta", "candidate" and so on (that
|
|
|
|
come before "final" alphabetically) are assumed to be pre-release versions,
|
|
|
|
so that the version "2.4" is considered newer than "2.4a1".
|
|
|
|
|
|
|
|
Finally, to handle miscellaneous cases, the strings "pre", "preview", and
|
|
|
|
"rc" are treated as if they were "c", i.e. as though they were release
|
|
|
|
candidates, and therefore are not as new as a version string that does not
|
|
|
|
contain them, and "dev" is replaced with an '@' so that it sorts lower than
|
|
|
|
than any other pre-release tag.
|
|
|
|
"""
|
|
|
|
parts = []
|
|
|
|
for part in _parse_version_parts(s.lower()):
|
2023-11-14 22:03:53 +01:00
|
|
|
if part.startswith("*"):
|
|
|
|
if part < "*final": # remove '-' before a prerelease tag
|
|
|
|
while parts and parts[-1] == "*final-":
|
2012-08-07 09:39:49 +02:00
|
|
|
parts.pop()
|
2012-07-02 11:20:52 +02:00
|
|
|
# remove trailing zeros from each series of numeric parts
|
2023-11-14 22:03:53 +01:00
|
|
|
while parts and parts[-1] == "00000000":
|
2012-07-02 11:20:52 +02:00
|
|
|
parts.pop()
|
|
|
|
parts.append(part)
|
|
|
|
return tuple(parts)
|