msys2-web/app/utils.py
Christoph Reiter c7ee6eb2bb Don't hide VCS packages
Treat them like all other packages. They used to cause various problems
by hitting edge cases, but this should all be fixed now.
2020-10-01 19:15:20 +02:00

156 lines
4.0 KiB
Python

# Copyright 2016-2020 Christoph Reiter
# SPDX-License-Identifier: MIT
import re
from itertools import zip_longest
from typing import List, Tuple, Optional, Dict, Set
def vercmp(v1: str, v2: str) -> int:
def cmp(a: int, b: int) -> int:
return (a > b) - (a < b)
def split(v: str) -> Tuple[str, str, Optional[str]]:
if "~" in v:
e, v = v.split("~", 1)
else:
e, v = ("0", v)
r: Optional[str] = None
if "-" in v:
v, r = v.rsplit("-", 1)
else:
v, r = (v, None)
return (e, v, r)
digit, alpha, other = range(3)
def get_type(c: str) -> int:
assert c
if c.isdigit():
return digit
elif c.isalpha():
return alpha
else:
return other
def parse(v: str) -> List[Tuple[int, Optional[str]]]:
parts: List[Tuple[int, Optional[str]]] = []
seps = 0
current = ""
for c in v:
if get_type(c) == other:
if current:
parts.append((seps, current))
current = ""
seps += 1
else:
if not current:
current += c
else:
if get_type(c) == get_type(current):
current += c
else:
parts.append((seps, current))
current = c
parts.append((seps, current or None))
return parts
def rpmvercmp(v1: str, v2: str) -> int:
for (s1, p1), (s2, p2) in zip_longest(parse(v1), parse(v2),
fillvalue=(None, None)):
if s1 is not None and s2 is not None:
ret = cmp(s1, s2)
if ret != 0:
return ret
if p1 is None and p2 is None:
return 0
if p1 is None:
if get_type(p2) == alpha:
return 1
return -1
elif p2 is None:
if get_type(p1) == alpha:
return -1
return 1
t1 = get_type(p1)
t2 = get_type(p2)
if t1 != t2:
if t1 == digit:
return 1
elif t2 == digit:
return -1
elif t1 == digit:
ret = cmp(int(p1), int(p2))
if ret != 0:
return ret
elif t1 == alpha:
ret = cmp(p1, p2)
if ret != 0:
return ret
return 0
e1, v1, r1 = split(v1)
e2, v2, r2 = split(v2)
ret = rpmvercmp(e1, e2)
if ret == 0:
ret = rpmvercmp(v1, v2)
if ret == 0 and r1 is not None and r2 is not None:
ret = rpmvercmp(r1, r2)
return ret
def extract_upstream_version(version: str) -> str:
return version.rsplit(
"-")[0].split("+", 1)[0].split("~", 1)[-1].split(":", 1)[-1]
def strip_vcs(package_name: str) -> str:
if package_name.endswith(
("-cvs", "-svn", "-hg", "-darcs", "-bzr", "-git")):
return package_name.rsplit("-", 1)[0]
return package_name
def arch_version_to_msys(v: str) -> str:
return v.replace(":", "~")
def version_is_newer_than(v1: str, v2: str) -> bool:
return vercmp(v1, v2) == 1
def split_depends(deps: List[str]) -> Dict[str, Set[str]]:
r: Dict[str, Set[str]] = {}
for d in deps:
parts = re.split("([<>=]+)", d, 1)
first = parts[0].strip()
second = "".join(parts[1:]).strip()
r.setdefault(first, set()).add(second)
return r
def split_optdepends(deps: List[str]) -> Dict[str, Set[str]]:
r: Dict[str, Set[str]] = {}
for d in deps:
if ":" in d:
a, b = d.split(":", 1)
a, b = a.strip(), b.strip()
else:
a, b = d.strip(), ""
e = r.setdefault(a, set())
if b:
e.add(b)
return r