Rewrote version parser and added utility functions for comparing versions

parent e4cb85f0
Pipeline #63169877 passed with stages
in 2 minutes and 14 seconds
# Copyright 2019 Portmod Authors
# Distributed under the terms of the GNU General Public License v3
import re
from typing import Iterable
import hashlib
from collections import namedtuple
from portmod.repo.keywords import accepts, accepts_testing, get_keywords
from portmod.repo.metadata import has_eula, is_license_accepted
from portmod.globals import ARCH
BUF_SIZE = 65536
VersionMatch = namedtuple(
"VersionMatch", ["version", "numeric", "letter", "suffix", "revision"]
)
class KeywordDep:
def __init__(self, atom, keyword):
......@@ -61,22 +68,113 @@ def select_mod_by_use(modlist):
return (get_newest_mod(filtered), None)
def get_newest_mod(modlist):
def suffix_gt(a_suffix: str, b_suffix: str) -> bool:
__SUFFIXES = ["alpha", "beta", "pre", "rc", "p"]
return __SUFFIXES.index(a_suffix) < __SUFFIXES.index(b_suffix)
def get_max_version(versions: Iterable[str]) -> str:
"""
Returns the largest version in the given list
Version should be a valid version according to PMS section 3.2,
optionally follwed by a revision
"""
newest = None
for mod in modlist:
for version in versions:
match = re.match(
r"(?P<NUMERIC>[\d\.]+)"
r"(?P<LETTER>[a-z])?_?"
r"(?P<SUFFIX>([a-z]+\d*)*)"
r"(-r(?P<REV>\d+))?",
version,
)
v_match = VersionMatch(
version=version,
numeric=match.group("NUMERIC").split("."),
letter=match.group("LETTER") or "",
suffix=match.group("SUFFIX") or "",
revision=int(match.group("REV") or "0"),
)
if not newest:
newest = mod
newest_ver = mod.MV.split(".")
newest = v_match
else:
ver = mod.MV.split(".")
for index, val in enumerate(ver):
if val > newest_ver[index]:
newest = mod
newest_ver = ver
done = False
# Compare numeric components
for index, val in enumerate(v_match.numeric):
if index >= len(newest.numeric):
newest = v_match
done = True
break
if int(val) > int(newest.numeric[index]):
newest = v_match
done = True
break
elif val < newest_ver[index]:
elif int(val) < int(newest.numeric[index]):
done = True
break
return newest
# Compare letter components
if not done:
if v_match.letter > newest.letter:
newest = v_match
continue
elif v_match.letter < newest.letter:
continue
# Compare suffixes
if not done:
if newest.suffix and not v_match.suffix:
continue
elif v_match.suffix and not newest.suffix:
newest = v_match
continue
elif v_match.suffix and newest.suffix:
a_suffixes = newest.suffix.split("_")
b_suffixes = v_match.suffix.split("_")
for a_s, b_s in zip(a_suffixes, b_suffixes):
print(newest, v_match)
asm = re.match(r"(?P<S>[a-z]+)(?P<N>\d+)?", a_s)
bsm = re.match(r"(?P<S>[a-z]+)(?P<N>\d+)?", b_s)
a_suffix = asm.group("S")
b_suffix = bsm.group("S")
a_suffix_num = int(asm.group("N") or "0")
b_suffix_num = int(bsm.group("N") or "0")
if a_suffix == b_suffix:
if b_suffix_num > a_suffix_num:
newest = v_match
done = True
break
elif a_suffix_num > b_suffix_num:
done = True
break
elif suffix_gt(b_suffix, a_suffix):
newest = v_match
done = True
break
else:
done = True
break
# Compare revisions
if not done:
if v_match.revision > newest.revision:
newest = v_match
done = True
elif v_match.revision < newest.revision:
done = True
return newest.version
def get_newest_mod(modlist):
max_ver = get_max_version([mod.MVR for mod in modlist])
for mod in modlist:
if mod.MV == max_ver:
return mod
raise Exception(
f"Internal Error: get_max_version returned incorrect result {max_ver}"
)
def get_hash(filename):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment