parent
4c4b770c27
commit
6fd3ba95ba
|
@ -3,9 +3,12 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
import asyncio
|
import asyncio
|
||||||
from io import StringIO
|
|
||||||
from typing import Dict, Tuple
|
from typing import Dict, Tuple
|
||||||
|
import itertools
|
||||||
|
import functools
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from nvchecker.api import (
|
from nvchecker.api import (
|
||||||
session, GetVersionError,
|
session, GetVersionError,
|
||||||
|
@ -17,6 +20,60 @@ APT_PACKAGES_PATH = "%s/binary-%s/Packages%s"
|
||||||
APT_PACKAGES_URL = "%s/dists/%s/%s"
|
APT_PACKAGES_URL = "%s/dists/%s/%s"
|
||||||
APT_PACKAGES_SUFFIX_PREFER = (".xz", ".gz", "")
|
APT_PACKAGES_SUFFIX_PREFER = (".xz", ".gz", "")
|
||||||
|
|
||||||
|
DpkgVersion = Tuple[int, str, str]
|
||||||
|
|
||||||
|
def parse_version(s: str) -> DpkgVersion:
|
||||||
|
try:
|
||||||
|
epoch_str, rest = s.split(':', 1)
|
||||||
|
except ValueError:
|
||||||
|
epoch = 0
|
||||||
|
rest = s
|
||||||
|
else:
|
||||||
|
epoch = int(epoch_str)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ver, rev = rest.split('-', 1)
|
||||||
|
except ValueError:
|
||||||
|
ver = rest
|
||||||
|
rev = ''
|
||||||
|
|
||||||
|
return epoch, ver, rev
|
||||||
|
|
||||||
|
def _compare_part(a: str, b: str) -> int:
|
||||||
|
sa = re.split(r'(\d+)', a)
|
||||||
|
sb = re.split(r'(\d+)', b)
|
||||||
|
for idx, (pa, pb) in enumerate(itertools.zip_longest(sa, sb)):
|
||||||
|
if pa is None:
|
||||||
|
return -1
|
||||||
|
elif pb is None:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
if idx % 2 == 1:
|
||||||
|
ret = int(pa) - int(pb)
|
||||||
|
if ret != 0:
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
if pa < pb:
|
||||||
|
return -1
|
||||||
|
elif pa > pb:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def compare_version_parsed(a: DpkgVersion, b: DpkgVersion) -> int:
|
||||||
|
ret = a[0] - b[0]
|
||||||
|
if ret != 0:
|
||||||
|
return ret
|
||||||
|
ret = _compare_part(a[1], b[1])
|
||||||
|
if ret != 0:
|
||||||
|
return ret
|
||||||
|
return _compare_part(a[2], b[2])
|
||||||
|
|
||||||
|
def compare_version(a: str, b: str) -> int:
|
||||||
|
va = parse_version(a)
|
||||||
|
vb = parse_version(b)
|
||||||
|
return compare_version_parsed(va, vb)
|
||||||
|
|
||||||
def _decompress_data(url: str, data: bytes) -> str:
|
def _decompress_data(url: str, data: bytes) -> str:
|
||||||
if url.endswith(".xz"):
|
if url.endswith(".xz"):
|
||||||
import lzma
|
import lzma
|
||||||
|
@ -39,8 +96,8 @@ async def parse_packages(key: Tuple[AsyncCache, str]) -> Tuple[Dict[str, str], D
|
||||||
cache, url = key
|
cache, url = key
|
||||||
apt_packages = await cache.get(url, get_url) # type: ignore
|
apt_packages = await cache.get(url, get_url) # type: ignore
|
||||||
|
|
||||||
pkg_map = {}
|
pkg_map = defaultdict(list)
|
||||||
srcpkg_map = {}
|
srcpkg_map = defaultdict(list)
|
||||||
|
|
||||||
pkg = None
|
pkg = None
|
||||||
srcpkg = None
|
srcpkg = None
|
||||||
|
@ -52,12 +109,17 @@ async def parse_packages(key: Tuple[AsyncCache, str]) -> Tuple[Dict[str, str], D
|
||||||
elif line.startswith("Version: "):
|
elif line.startswith("Version: "):
|
||||||
version = line[9:]
|
version = line[9:]
|
||||||
if pkg is not None:
|
if pkg is not None:
|
||||||
pkg_map[pkg] = version
|
pkg_map[pkg].append(version)
|
||||||
if srcpkg is not None:
|
if srcpkg is not None:
|
||||||
srcpkg_map[srcpkg] = version
|
srcpkg_map[srcpkg].append(version)
|
||||||
pkg = srcpkg = None
|
pkg = srcpkg = None
|
||||||
|
|
||||||
return pkg_map, srcpkg_map
|
pkg_map_max = {pkg: max(vs, key=functools.cmp_to_key(compare_version))
|
||||||
|
for pkg, vs in pkg_map.items()}
|
||||||
|
srcpkg_map_max = {pkg: max(vs, key=functools.cmp_to_key(compare_version))
|
||||||
|
for pkg, vs in srcpkg_map.items()}
|
||||||
|
|
||||||
|
return pkg_map_max, srcpkg_map_max
|
||||||
|
|
||||||
async def get_version(
|
async def get_version(
|
||||||
name: str, conf: Entry, *,
|
name: str, conf: Entry, *,
|
||||||
|
|
|
@ -39,3 +39,14 @@ async def test_apt_deepin(get_version):
|
||||||
"mirror": "https://community-packages.deepin.com/deepin",
|
"mirror": "https://community-packages.deepin.com/deepin",
|
||||||
"suite": "apricot",
|
"suite": "apricot",
|
||||||
}) == "0.1.6-1"
|
}) == "0.1.6-1"
|
||||||
|
|
||||||
|
@flaky(max_runs=10)
|
||||||
|
async def test_apt_multiversions(get_version):
|
||||||
|
assert await get_version("ms-teams", {
|
||||||
|
"source": "apt",
|
||||||
|
"mirror": "https://packages.microsoft.com/repos/ms-teams",
|
||||||
|
"pkg": "teams",
|
||||||
|
"suite": "stable",
|
||||||
|
"repo": "main",
|
||||||
|
"arch": "amd64",
|
||||||
|
}) == "1.4.00.13653"
|
||||||
|
|
Loading…
Reference in New Issue