Add an APT source

This source follows the same flow apt itself uses to check for a
package's version, so it can be used to check for any APT repository
(not necessarily Debian or Ubuntu).
This commit is contained in:
Felix Yan 2020-09-16 17:20:17 +08:00
parent e744a27572
commit ae563d007f
No known key found for this signature in database
GPG Key ID: 786C63F330D7CB92
3 changed files with 106 additions and 0 deletions

View File

@ -610,6 +610,32 @@ host
This source returns tags and supports :ref:`list options`.
Check APT repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
source = "apt"
This enables you to track the update of an arbitary APT repository, without needing of apt and an updated local APT database.
apt
Name of the APT package.
mirror
URL of the repository (defaults to http://ftp.debian.org/debian/)
suite
Name of the APT repository release (jessie, wheezy, etc, defaults to sid)
repo
Name of the APT repository (main, contrib, etc, defaults to main)
arch
Architecture of the repository (i386, amd64, etc, defaults to amd64)
strip_release
Strip the release part.
Manually updating
~~~~~~~~~~~~~~~~~
::

52
nvchecker_source/apt.py Normal file
View File

@ -0,0 +1,52 @@
# MIT licensed
# Copyright (c) 2020 Felix Yan <felixonmars@archlinux.org>, et al.
from nvchecker.api import session, GetVersionError
APT_RELEASE_URL = "%s/dists/%s/Release"
APT_PACKAGES_PATH = "%s/binary-%s/Packages%s"
APT_PACKAGES_URL = "%s/dists/%s/%s"
APT_PACKAGES_SUFFIX_PREFER = (".xz", ".gz", "")
async def get_url(url):
res = await session.get(url)
data = res.body
if url.endswith(".xz"):
import lzma
data = lzma.decompress(data)
elif url.endswith(".gz"):
import gzip
data = gzip.decompress(data)
return data.decode('utf-8')
async def get_version(name, conf, *, cache, **kwargs):
pkg = conf.get('apt') or name
mirror = conf.get('mirror', "http://ftp.debian.org/debian/")
suite = conf.get('suite', 'sid')
repo = conf.get('repo', 'main')
arch = conf.get('arch', 'amd64')
strip_release = conf.get('strip_release', False)
apt_release = await cache.get(APT_RELEASE_URL % (mirror, suite), get_url)
for suffix in APT_PACKAGES_SUFFIX_PREFER:
packages_path = APT_PACKAGES_PATH % (repo, arch, suffix)
if " " + packages_path in apt_release:
break
else:
raise GetVersionError('Packages file not found in APT repository')
apt_packages = await cache.get(APT_PACKAGES_URL % (mirror, suite, packages_path), get_url)
pkg_found = False
for line in apt_packages.split("\n"):
if line == "Package: " + pkg:
pkg_found = True
if pkg_found and line.startswith("Version: "):
version = line[9:]
if strip_release:
version = version.split("-")[0]
return version
raise GetVersionError('package not found in APT repository')

28
tests/test_apt.py Normal file
View File

@ -0,0 +1,28 @@
# MIT licensed
# Copyright (c) 2020 lilydjwg <lilydjwg@gmail.com>, et al.
# Copyright (c) 2017 Felix Yan <felixonmars@archlinux.org>, et al.
from flaky import flaky
import pytest
pytestmark = [pytest.mark.asyncio, pytest.mark.needs_net]
@flaky(max_runs=10)
async def test_apt(get_version):
assert await get_version("sigrok-firmware-fx2lafw", {
"source": "apt",
}) == "0.1.7-1"
@flaky(max_runs=10)
async def test_apt_strip_release(get_version):
assert await get_version("sigrok-firmware-fx2lafw", {
"source": "apt",
"strip_release": 1,
}) == "0.1.7"
@flaky(max_runs=10)
async def test_apt_deepin(get_version):
assert await get_version("sigrok-firmware-fx2lafw", {
"source": "apt",
"mirror": "https://community-packages.deepin.com/deepin",
"suite": "apricot",
}) == "0.1.6-1"