diff --git a/swh/lister/arch/lister.py b/swh/lister/arch/lister.py index af66d7f..563fa18 100644 --- a/swh/lister/arch/lister.py +++ b/swh/lister/arch/lister.py @@ -1,474 +1,482 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information import datetime import logging from pathlib import Path import re import tarfile import tempfile from typing import Any, Dict, Iterator, List, Optional from urllib.parse import unquote, urljoin from bs4 import BeautifulSoup from swh.model.hashutil import hash_to_hex from swh.scheduler.interface import SchedulerInterface from swh.scheduler.model import ListedOrigin from ..pattern import CredentialsType, StatelessLister logger = logging.getLogger(__name__) # Aliasing the page results returned by `get_pages` method from the lister. ArchListerPage = List[Dict[str, Any]] def size_to_bytes(size: str) -> int: """Convert human readable file size to bytes. Resulting value is an approximation as input value is in most case rounded. Args: size: A string representing a human readable file size (eg: '500K') Returns: A decimal representation of file size Examples:: >>> size_to_bytes("500") 500 >>> size_to_bytes("1K") 1000 """ units = { "K": 1000, "M": 1000**2, "G": 1000**3, "T": 1000**4, "P": 1000**5, "E": 1000**6, "Z": 1000**7, "Y": 1000**8, } if size.endswith(tuple(units)): v, u = (size[:-1], size[-1]) return int(v) * units[u] else: return int(size) class ArchLister(StatelessLister[ArchListerPage]): """List Arch linux origins from 'core', 'extra', and 'community' repositories For 'official' Arch Linux it downloads core.tar.gz, extra.tar.gz and community.tar.gz from https://archive.archlinux.org/repos/last/ extract to a temp directory and then walks through each 'desc' files. Each 'desc' file describe the latest released version of a package and helps to build an origin url from where scrapping artifacts metadata. For 'arm' Arch Linux it follow the same discovery process parsing 'desc' files. The main difference is that we can't get existing versions of an arm package because https://archlinuxarm.org does not have an 'archive' website or api. """ LISTER_NAME = "arch" VISIT_TYPE = "arch" INSTANCE = "arch" ARCH_PACKAGE_URL_PATTERN = "{base_url}/packages/{repo}/{arch}/{pkgname}" ARCH_PACKAGE_VERSIONS_URL_PATTERN = "{base_url}/packages/{pkgname[0]}/{pkgname}" ARCH_PACKAGE_DOWNLOAD_URL_PATTERN = ( "{base_url}/packages/{pkgname[0]}/{pkgname}/{filename}" ) ARCH_API_URL_PATTERN = "{base_url}/packages/{repo}/{arch}/{pkgname}/json" ARM_PACKAGE_URL_PATTERN = "{base_url}/packages/{arch}/{pkgname}" ARM_PACKAGE_DOWNLOAD_URL_PATTERN = "{base_url}/{arch}/{repo}/{filename}" def __init__( self, scheduler: SchedulerInterface, credentials: Optional[CredentialsType] = None, flavours: Dict[str, Any] = { "official": { "archs": ["x86_64"], "repos": ["core", "extra", "community"], "base_info_url": "https://archlinux.org", "base_archive_url": "https://archive.archlinux.org", "base_mirror_url": "", "base_api_url": "https://archlinux.org", }, "arm": { "archs": ["armv7h", "aarch64"], "repos": ["core", "extra", "community"], "base_info_url": "https://archlinuxarm.org", "base_archive_url": "", "base_mirror_url": "https://uk.mirror.archlinuxarm.org", "base_api_url": "", }, }, ): super().__init__( scheduler=scheduler, credentials=credentials, url=flavours["official"]["base_info_url"], instance=self.INSTANCE, ) self.flavours = flavours def scrap_package_versions( self, name: str, repo: str, base_url: str ) -> List[Dict[str, Any]]: """Given a package 'name' and 'repo', make an http call to origin url and parse its content to get package versions artifacts data. That method is suitable only for 'official' Arch Linux, not 'arm'. Args: name: Package name repo: The repository the package belongs to (one of self.repos) Returns: A list of dict of version Example:: [ {"url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190211-1-x86_64.pkg.tar.xz", # noqa: B950 "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20190211-1", "length": 180000, "filename": "dialog-1:1.3_20190211-1-x86_64.pkg.tar.xz", "last_modified": "2019-02-13T08:36:00"}, ] """ url = self.ARCH_PACKAGE_VERSIONS_URL_PATTERN.format( pkgname=name, base_url=base_url ) response = self.http_request(url) soup = BeautifulSoup(response.text, "html.parser") links = soup.find_all("a", href=True) # drop the first line (used to go to up directory) if links[0].attrs["href"] == "../": links.pop(0) versions = [] for link in links: # filename displayed can be cropped if name is too long, get it from href instead filename = unquote(link.attrs["href"]) if filename.endswith((".tar.xz", ".tar.zst")): # Extract arch from filename arch_rex = re.compile( rf"^{re.escape(name)}-(?P.*)-(?Pany|i686|x86_64)" rf"(.pkg.tar.(?:zst|xz))$" ) m = arch_rex.match(filename) if m is None: logger.error( "Can not find a match for architecture in %(filename)s", dict(filename=filename), ) else: arch = m.group("arch") version = m.group("version") # Extract last_modified and an approximate file size raw_text = link.next_sibling raw_text_rex = re.compile( r"^(?P\d+-\w+-\d+ \d\d:\d\d)\s+(?P\w+)$" ) s = raw_text_rex.search(raw_text.strip()) if s is None: logger.error( "Can not find a match for 'last_modified' and/or " "'size' in '%(raw_text)s'", dict(raw_text=raw_text), ) else: assert s.groups() assert len(s.groups()) == 2 last_modified_str, size = s.groups() # format as expected last_modified = datetime.datetime.strptime( last_modified_str, "%d-%b-%Y %H:%M" ).isoformat() length = size_to_bytes(size) # we want bytes # link url is relative, format a canonical one url = self.ARCH_PACKAGE_DOWNLOAD_URL_PATTERN.format( base_url=base_url, pkgname=name, filename=filename ) versions.append( dict( name=name, version=version, repo=repo, arch=arch, filename=filename, url=url, last_modified=last_modified, length=length, ) ) return versions def get_repo_archive(self, url: str, destination_path: Path) -> Path: """Given an url and a destination path, retrieve and extract .tar.gz archive which contains 'desc' file for each package. Each .tar.gz archive corresponds to an Arch Linux repo ('core', 'extra', 'community'). Args: url: url of the .tar.gz archive to download destination_path: the path on disk where to extract archive Returns: a directory Path where the archive has been extracted to. """ res = self.http_request(url) destination_path.parent.mkdir(parents=True, exist_ok=True) destination_path.write_bytes(res.content) extract_to = Path(str(destination_path).split(".tar.gz")[0]) tar = tarfile.open(destination_path) tar.extractall(path=extract_to) tar.close() return extract_to def parse_desc_file( self, path: Path, repo: str, base_url: str, dl_url_fmt: str, ) -> Dict[str, Any]: """Extract package information from a 'desc' file. There are subtle differences between parsing 'official' and 'arm' des files Args: path: A path to a 'desc' file on disk repo: The repo the package belongs to Returns: A dict of metadata Example:: {'api_url': 'https://archlinux.org/packages/core/x86_64/dialog/json', 'arch': 'x86_64', 'base': 'dialog', 'builddate': '1650081535', 'csize': '203028', 'desc': 'A tool to display dialog boxes from shell scripts', 'filename': 'dialog-1:1.3_20220414-1-x86_64.pkg.tar.zst', 'isize': '483988', 'license': 'LGPL2.1', 'md5sum': '06407c0cb11c50d7bf83d600f2e8107c', 'name': 'dialog', 'packager': 'Evangelos Foutras ', 'pgpsig': 'pgpsig content xxx', 'project_url': 'https://invisible-island.net/dialog/', 'provides': 'libdialog.so=15-64', 'repo': 'core', 'sha256sum': 'ef8c8971f591de7db0f455970ef5d81d5aced1ddf139f963f16f6730b1851fa7', 'url': 'https://archive.archlinux.org/packages/.all/dialog-1:1.3_20220414-1-x86_64.pkg.tar.zst', # noqa: B950 'version': '1:1.3_20220414-1'} """ rex = re.compile(r"^\%(?P\w+)\%\n(?P.*)\n$", re.M) with path.open("rb") as content: parsed = rex.findall(content.read().decode()) data = {entry[0].lower(): entry[1] for entry in parsed} if "url" in data.keys(): data["project_url"] = data["url"] assert data["name"] assert data["filename"] assert data["arch"] data["repo"] = repo data["url"] = urljoin( base_url, dl_url_fmt.format( base_url=base_url, pkgname=data["name"], filename=data["filename"], arch=data["arch"], repo=repo, ), ) assert data["md5sum"] assert data["sha256sum"] data["checksums"] = { "md5sum": hash_to_hex(data["md5sum"]), "sha256sum": hash_to_hex(data["sha256sum"]), } return data def get_pages(self) -> Iterator[ArchListerPage]: """Yield an iterator sorted by name in ascending order of pages. Each page is a list of package belonging to a flavour ('official', 'arm'), and a repo ('core', 'extra', 'community') """ for name, flavour in self.flavours.items(): for arch in flavour["archs"]: for repo in flavour["repos"]: yield self._get_repo_page(name, flavour, arch, repo) def _get_repo_page( self, name: str, flavour: Dict[str, Any], arch: str, repo: str ) -> ArchListerPage: with tempfile.TemporaryDirectory() as tmpdir: page = [] if name == "official": prefix = urljoin(flavour["base_archive_url"], "/repos/last/") filename = f"{repo}.files.tar.gz" archive_url = urljoin(prefix, f"{repo}/os/{arch}/{filename}") destination_path = Path(tmpdir, arch, filename) base_url = flavour["base_archive_url"] dl_url_fmt = self.ARCH_PACKAGE_DOWNLOAD_URL_PATTERN base_info_url = flavour["base_info_url"] info_url_fmt = self.ARCH_PACKAGE_URL_PATTERN elif name == "arm": filename = f"{repo}.files.tar.gz" archive_url = urljoin( flavour["base_mirror_url"], f"{arch}/{repo}/{filename}" ) destination_path = Path(tmpdir, arch, filename) base_url = flavour["base_mirror_url"] dl_url_fmt = self.ARM_PACKAGE_DOWNLOAD_URL_PATTERN base_info_url = flavour["base_info_url"] info_url_fmt = self.ARM_PACKAGE_URL_PATTERN archive = self.get_repo_archive( url=archive_url, destination_path=destination_path ) assert archive packages_desc = list(archive.glob("**/desc")) logger.debug( "Processing %(instance)s source packages info from " "%(flavour)s %(arch)s %(repo)s repository, " "(%(qty)s packages).", dict( instance=self.instance, flavour=name, arch=arch, repo=repo, qty=len(packages_desc), ), ) for package_desc in packages_desc: data = self.parse_desc_file( path=package_desc, repo=repo, base_url=base_url, dl_url_fmt=dl_url_fmt, ) assert data["builddate"] last_modified = datetime.datetime.fromtimestamp( float(data["builddate"]), tz=datetime.timezone.utc ) assert data["name"] assert data["filename"] assert data["arch"] url = info_url_fmt.format( base_url=base_info_url, pkgname=data["name"], filename=data["filename"], repo=repo, arch=data["arch"], ) assert data["version"] if name == "official": # find all versions of a package scrapping archive versions = self.scrap_package_versions( name=data["name"], repo=repo, base_url=base_url ) elif name == "arm": # There is no way to get related versions of a package, # but 'data' represents the latest released version, # use it in this case assert data["builddate"] assert data["csize"] assert data["url"] versions = [ dict( name=data["name"], version=data["version"], repo=repo, arch=data["arch"], filename=data["filename"], url=data["url"], last_modified=last_modified.replace(tzinfo=None).isoformat( timespec="seconds" ), length=int(data["csize"]), ) ] package = { "name": data["name"], "version": data["version"], "last_modified": last_modified, "url": url, "versions": versions, "data": data, } page.append(package) return page def get_origins_from_page(self, page: ArchListerPage) -> Iterator[ListedOrigin]: """Iterate on all arch pages and yield ListedOrigin instances.""" assert self.lister_obj.id is not None for origin in page: artifacts = [] arch_metadata = [] for version in origin["versions"]: artifacts.append( { "version": version["version"], "filename": version["filename"], "url": version["url"], "length": version["length"], } ) + if version["version"] == origin["version"]: + artifacts[-1]["checksums"] = { + "md5": origin["data"]["md5sum"], + "sha256": origin["data"]["sha256sum"], + } + else: + artifacts[-1]["checksums"] = {"length": version["length"]} + arch_metadata.append( { "version": version["version"], "name": version["name"], "arch": version["arch"], "repo": version["repo"], "last_modified": version["last_modified"], } ) yield ListedOrigin( lister_id=self.lister_obj.id, visit_type=self.VISIT_TYPE, url=origin["url"], last_update=origin["last_modified"], extra_loader_arguments={ "artifacts": artifacts, "arch_metadata": arch_metadata, }, ) diff --git a/swh/lister/arch/tests/test_lister.py b/swh/lister/arch/tests/test_lister.py index fa644d3..3167c4d 100644 --- a/swh/lister/arch/tests/test_lister.py +++ b/swh/lister/arch/tests/test_lister.py @@ -1,1395 +1,1696 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information +# flake8: noqa: B950 + from swh.lister.arch.lister import ArchLister expected_origins = [ { "url": "https://archlinux.org/packages/core/x86_64/dialog", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190211-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190211-1-x86_64.pkg.tar.xz", "version": "1:1.3_20190211-1", "length": 180000, "filename": "dialog-1:1.3_20190211-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 180000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190724-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190724-1-x86_64.pkg.tar.xz", "version": "1:1.3_20190724-1", "length": 180000, "filename": "dialog-1:1.3_20190724-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 180000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190728-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190728-1-x86_64.pkg.tar.xz", "version": "1:1.3_20190728-1", "length": 180000, "filename": "dialog-1:1.3_20190728-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 180000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190806-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190806-1-x86_64.pkg.tar.xz", "version": "1:1.3_20190806-1", "length": 182000, "filename": "dialog-1:1.3_20190806-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 182000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190808-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20190808-1-x86_64.pkg.tar.xz", "version": "1:1.3_20190808-1", "length": 182000, "filename": "dialog-1:1.3_20190808-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 182000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191110-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191110-1-x86_64.pkg.tar.xz", "version": "1:1.3_20191110-1", "length": 183000, "filename": "dialog-1:1.3_20191110-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 183000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191110-2-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191110-2-x86_64.pkg.tar.xz", "version": "1:1.3_20191110-2", "length": 183000, "filename": "dialog-1:1.3_20191110-2-x86_64.pkg.tar.xz", + "checksums": { + "length": 183000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191209-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191209-1-x86_64.pkg.tar.xz", "version": "1:1.3_20191209-1", "length": 183000, "filename": "dialog-1:1.3_20191209-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 183000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191210-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20191210-1-x86_64.pkg.tar.xz", "version": "1:1.3_20191210-1", "length": 184000, "filename": "dialog-1:1.3_20191210-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 184000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20200228-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20200228-1-x86_64.pkg.tar.zst", "version": "1:1.3_20200228-1", "length": 196000, "filename": "dialog-1:1.3_20200228-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 196000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20200327-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20200327-1-x86_64.pkg.tar.zst", "version": "1:1.3_20200327-1", "length": 196000, "filename": "dialog-1:1.3_20200327-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 196000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20201126-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20201126-1-x86_64.pkg.tar.zst", "version": "1:1.3_20201126-1", "length": 199000, "filename": "dialog-1:1.3_20201126-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 199000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210117-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210117-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210117-1", "length": 200000, "filename": "dialog-1:1.3_20210117-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 200000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210306-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210306-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210306-1", "length": 201000, "filename": "dialog-1:1.3_20210306-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 201000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210319-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210319-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210319-1", "length": 201000, "filename": "dialog-1:1.3_20210319-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 201000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210324-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210324-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210324-1", "length": 201000, "filename": "dialog-1:1.3_20210324-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 201000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210509-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210509-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210509-1", "length": 198000, "filename": "dialog-1:1.3_20210509-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 198000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210530-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210530-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210530-1", "length": 198000, "filename": "dialog-1:1.3_20210530-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 198000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210621-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20210621-1-x86_64.pkg.tar.zst", "version": "1:1.3_20210621-1", "length": 199000, "filename": "dialog-1:1.3_20210621-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 199000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20211107-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20211107-1-x86_64.pkg.tar.zst", "version": "1:1.3_20211107-1", "length": 197000, "filename": "dialog-1:1.3_20211107-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 197000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20211214-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20211214-1-x86_64.pkg.tar.zst", "version": "1:1.3_20211214-1", "length": 197000, "filename": "dialog-1:1.3_20211214-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 197000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20220117-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20220117-1-x86_64.pkg.tar.zst", "version": "1:1.3_20220117-1", "length": 199000, "filename": "dialog-1:1.3_20220117-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 199000, + }, }, { - "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20220414-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/d/dialog/dialog-1:1.3_20220414-1-x86_64.pkg.tar.zst", "version": "1:1.3_20220414-1", "length": 198000, "filename": "dialog-1:1.3_20220414-1-x86_64.pkg.tar.zst", + "checksums": { + "md5": "06407c0cb11c50d7bf83d600f2e8107c", + "sha256": "ef8c8971f591de7db0f455970ef5d81d5aced1ddf139f963f16f6730b1851fa7", + }, }, ], "arch_metadata": [ { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20190211-1", "last_modified": "2019-02-13T08:36:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20190724-1", "last_modified": "2019-07-26T21:39:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20190728-1", "last_modified": "2019-07-29T12:10:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20190806-1", "last_modified": "2019-08-07T04:19:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20190808-1", "last_modified": "2019-08-09T22:49:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20191110-1", "last_modified": "2019-11-11T11:15:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20191110-2", "last_modified": "2019-11-13T17:40:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20191209-1", "last_modified": "2019-12-10T09:56:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20191210-1", "last_modified": "2019-12-12T15:55:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20200228-1", "last_modified": "2020-03-06T02:21:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20200327-1", "last_modified": "2020-03-29T17:08:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20201126-1", "last_modified": "2020-11-27T12:19:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210117-1", "last_modified": "2021-01-18T18:05:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210306-1", "last_modified": "2021-03-07T11:40:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210319-1", "last_modified": "2021-03-20T00:12:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210324-1", "last_modified": "2021-03-26T17:53:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210509-1", "last_modified": "2021-05-16T02:04:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210530-1", "last_modified": "2021-05-31T14:59:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20210621-1", "last_modified": "2021-06-23T02:59:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20211107-1", "last_modified": "2021-11-09T14:06:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20211214-1", "last_modified": "2021-12-14T09:26:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20220117-1", "last_modified": "2022-01-19T09:56:00", }, { "arch": "x86_64", "repo": "core", "name": "dialog", "version": "1:1.3_20220414-1", "last_modified": "2022-04-16T03:59:00", }, ], }, }, { "url": "https://archlinux.org/packages/community/x86_64/gnome-code-assistance", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-1-x86_64.pkg.tar.xz", "version": "1:3.16.1+15+g0fd8b5f-1", "length": 2000000, - "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-1-x86_64.pkg.tar.xz", # noqa: B950 + "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-2-x86_64.pkg.tar.zst", "version": "1:3.16.1+15+g0fd8b5f-2", "length": 2000000, - "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-2-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-3-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-3-x86_64.pkg.tar.zst", "version": "1:3.16.1+15+g0fd8b5f-3", "length": 2000000, - "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-3-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-3-x86_64.pkg.tar.zst", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-4-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-1:3.16.1+15+g0fd8b5f-4-x86_64.pkg.tar.zst", "version": "1:3.16.1+15+g0fd8b5f-4", "length": 2000000, - "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-4-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "gnome-code-assistance-1:3.16.1+15+g0fd8b5f-4-x86_64.pkg.tar.zst", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-2:3.16.1+14+gaad6437-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-2:3.16.1+14+gaad6437-1-x86_64.pkg.tar.zst", "version": "2:3.16.1+14+gaad6437-1", "length": 2000000, - "filename": "gnome-code-assistance-2:3.16.1+14+gaad6437-1-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "gnome-code-assistance-2:3.16.1+14+gaad6437-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-2:3.16.1+14+gaad6437-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-2:3.16.1+14+gaad6437-2-x86_64.pkg.tar.zst", "version": "2:3.16.1+14+gaad6437-2", "length": 2000000, - "filename": "gnome-code-assistance-2:3.16.1+14+gaad6437-2-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "gnome-code-assistance-2:3.16.1+14+gaad6437-2-x86_64.pkg.tar.zst", + "checksums": { + "md5": "eadcf1a6bb70a3e564f260b7fc58135a", + "sha256": "6fd0c80b63d205a1edf5c39c7a62d16499e802566f2451c2b85cd28c9bc30ec7", + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3.16.1+14+gaad6437-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3.16.1+14+gaad6437-1-x86_64.pkg.tar.xz", "version": "3.16.1+14+gaad6437-1", "length": 2000000, - "filename": "gnome-code-assistance-3.16.1+14+gaad6437-1-x86_64.pkg.tar.xz", # noqa: B950 + "filename": "gnome-code-assistance-3.16.1+14+gaad6437-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3.16.1+14+gaad6437-2-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3.16.1+14+gaad6437-2-x86_64.pkg.tar.xz", "version": "3.16.1+14+gaad6437-2", "length": 2000000, - "filename": "gnome-code-assistance-3.16.1+14+gaad6437-2-x86_64.pkg.tar.xz", # noqa: B950 + "filename": "gnome-code-assistance-3.16.1+14+gaad6437-2-x86_64.pkg.tar.xz", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3.16.1+15+gb9ffc4d-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3.16.1+15+gb9ffc4d-1-x86_64.pkg.tar.xz", "version": "3.16.1+15+gb9ffc4d-1", "length": 2000000, - "filename": "gnome-code-assistance-3.16.1+15+gb9ffc4d-1-x86_64.pkg.tar.xz", # noqa: B950 + "filename": "gnome-code-assistance-3.16.1+15+gb9ffc4d-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 2000000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3:3.16.1+r14+gaad6437-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gnome-code-assistance/gnome-code-assistance-3:3.16.1+r14+gaad6437-1-x86_64.pkg.tar.zst", "version": "3:3.16.1+r14+gaad6437-1", "length": 2000000, - "filename": "gnome-code-assistance-3:3.16.1+r14+gaad6437-1-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "gnome-code-assistance-3:3.16.1+r14+gaad6437-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 2000000, + }, }, ], "arch_metadata": [ { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "1:3.16.1+15+g0fd8b5f-1", "last_modified": "2019-11-10T20:55:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "1:3.16.1+15+g0fd8b5f-2", "last_modified": "2020-03-28T15:58:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "1:3.16.1+15+g0fd8b5f-3", "last_modified": "2020-07-05T15:28:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "1:3.16.1+15+g0fd8b5f-4", "last_modified": "2020-11-12T17:28:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "2:3.16.1+14+gaad6437-1", "last_modified": "2021-02-24T16:30:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "2:3.16.1+14+gaad6437-2", "last_modified": "2021-12-02T23:36:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "3.16.1+14+gaad6437-1", "last_modified": "2019-03-15T19:23:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "3.16.1+14+gaad6437-2", "last_modified": "2019-08-24T20:05:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "3.16.1+15+gb9ffc4d-1", "last_modified": "2019-08-25T20:55:00", }, { "arch": "x86_64", "repo": "community", "name": "gnome-code-assistance", "version": "3:3.16.1+r14+gaad6437-1", "last_modified": "2022-05-18T17:23:00", }, ], }, }, { "url": "https://archlinux.org/packages/core/x86_64/gzip", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.10-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.10-1-x86_64.pkg.tar.xz", "version": "1.10-1", "length": 78000, "filename": "gzip-1.10-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 78000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.10-2-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.10-2-x86_64.pkg.tar.xz", "version": "1.10-2", "length": 78000, "filename": "gzip-1.10-2-x86_64.pkg.tar.xz", + "checksums": { + "length": 78000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.10-3-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.10-3-x86_64.pkg.tar.xz", "version": "1.10-3", "length": 78000, "filename": "gzip-1.10-3-x86_64.pkg.tar.xz", + "checksums": { + "length": 78000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.11-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.11-1-x86_64.pkg.tar.zst", "version": "1.11-1", "length": 82000, "filename": "gzip-1.11-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 82000, + }, }, { - "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.12-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/g/gzip/gzip-1.12-1-x86_64.pkg.tar.zst", "version": "1.12-1", "length": 80000, "filename": "gzip-1.12-1-x86_64.pkg.tar.zst", + "checksums": { + "md5": "3e72c94305917d00d9e361a687cf0a3e", + "sha256": "0ee561edfbc1c7c6a204f7cfa43437c3362311b4fd09ea0541134aaea3a8cc07", + }, }, ], "arch_metadata": [ { "arch": "x86_64", "repo": "core", "name": "gzip", "version": "1.10-1", "last_modified": "2018-12-30T18:38:00", }, { "arch": "x86_64", "repo": "core", "name": "gzip", "version": "1.10-2", "last_modified": "2019-10-06T16:02:00", }, { "arch": "x86_64", "repo": "core", "name": "gzip", "version": "1.10-3", "last_modified": "2019-11-13T15:55:00", }, { "arch": "x86_64", "repo": "core", "name": "gzip", "version": "1.11-1", "last_modified": "2021-09-04T02:02:00", }, { "arch": "x86_64", "repo": "core", "name": "gzip", "version": "1.12-1", "last_modified": "2022-04-07T17:35:00", }, ], }, }, { "url": "https://archlinux.org/packages/extra/x86_64/libasyncns", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://archive.archlinux.org/packages/l/libasyncns/libasyncns-0.8+3+g68cd5af-2-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/l/libasyncns/libasyncns-0.8+3+g68cd5af-2-x86_64.pkg.tar.xz", "version": "0.8+3+g68cd5af-2", "length": 16000, "filename": "libasyncns-0.8+3+g68cd5af-2-x86_64.pkg.tar.xz", + "checksums": { + "length": 16000, + }, }, { - "url": "https://archive.archlinux.org/packages/l/libasyncns/libasyncns-0.8+3+g68cd5af-3-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/l/libasyncns/libasyncns-0.8+3+g68cd5af-3-x86_64.pkg.tar.zst", "version": "0.8+3+g68cd5af-3", "length": 17000, "filename": "libasyncns-0.8+3+g68cd5af-3-x86_64.pkg.tar.zst", + "checksums": { + "md5": "0aad62f00eab3d0ec7798cb5b4a6eddd", + "sha256": "a0262e191dd3b00343e79e3521159c963e26b7a438d4cc44137c64cf0da90516", + }, }, { - "url": "https://archive.archlinux.org/packages/l/libasyncns/libasyncns-1:0.8+r3+g68cd5af-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/l/libasyncns/libasyncns-1:0.8+r3+g68cd5af-1-x86_64.pkg.tar.zst", "version": "1:0.8+r3+g68cd5af-1", "length": 17000, - "filename": "libasyncns-1:0.8+r3+g68cd5af-1-x86_64.pkg.tar.zst", # noqa: B950 + "filename": "libasyncns-1:0.8+r3+g68cd5af-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 17000, + }, }, ], "arch_metadata": [ { "arch": "x86_64", "repo": "extra", "name": "libasyncns", "version": "0.8+3+g68cd5af-2", "last_modified": "2018-11-09T23:39:00", }, { "arch": "x86_64", "repo": "extra", "name": "libasyncns", "version": "0.8+3+g68cd5af-3", "last_modified": "2020-05-19T08:28:00", }, { "arch": "x86_64", "repo": "extra", "name": "libasyncns", "version": "1:0.8+r3+g68cd5af-1", "last_modified": "2022-05-18T17:23:00", }, ], }, }, { "url": "https://archlinux.org/packages/extra/x86_64/mercurial", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-4.8.2-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-4.8.2-1-x86_64.pkg.tar.xz", "version": "4.8.2-1", "length": 4000000, "filename": "mercurial-4.8.2-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-4.9-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-4.9-1-x86_64.pkg.tar.xz", "version": "4.9-1", "length": 4000000, "filename": "mercurial-4.9-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-4.9.1-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-4.9.1-1-x86_64.pkg.tar.xz", "version": "4.9.1-1", "length": 4000000, "filename": "mercurial-4.9.1-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.0-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.0-1-x86_64.pkg.tar.xz", "version": "5.0-1", "length": 4000000, "filename": "mercurial-5.0-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.0.1-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.0.1-1-x86_64.pkg.tar.xz", "version": "5.0.1-1", "length": 4000000, "filename": "mercurial-5.0.1-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.0.2-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.0.2-1-x86_64.pkg.tar.xz", "version": "5.0.2-1", "length": 4000000, "filename": "mercurial-5.0.2-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.1-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.1-1-x86_64.pkg.tar.xz", "version": "5.1-1", "length": 4000000, "filename": "mercurial-5.1-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.1.2-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.1.2-1-x86_64.pkg.tar.xz", "version": "5.1.2-1", "length": 4000000, "filename": "mercurial-5.1.2-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2-1-x86_64.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2-1-x86_64.pkg.tar.xz", "version": "5.2-1", "length": 4000000, "filename": "mercurial-5.2-1-x86_64.pkg.tar.xz", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2.1-1-x86_64.pkg.tar.zst", "version": "5.2.1-1", "length": 4000000, "filename": "mercurial-5.2.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2.2-1-x86_64.pkg.tar.zst", "version": "5.2.2-1", "length": 5000000, "filename": "mercurial-5.2.2-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2.2-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.2.2-2-x86_64.pkg.tar.zst", "version": "5.2.2-2", "length": 4000000, "filename": "mercurial-5.2.2-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.3-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.3-1-x86_64.pkg.tar.zst", "version": "5.3-1", "length": 5000000, "filename": "mercurial-5.3-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.3.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.3.1-1-x86_64.pkg.tar.zst", "version": "5.3.1-1", "length": 4000000, "filename": "mercurial-5.3.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.3.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.3.2-1-x86_64.pkg.tar.zst", "version": "5.3.2-1", "length": 4000000, "filename": "mercurial-5.3.2-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 4000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4-1-x86_64.pkg.tar.zst", "version": "5.4-1", "length": 5000000, "filename": "mercurial-5.4-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4-2-x86_64.pkg.tar.zst", "version": "5.4-2", "length": 5000000, "filename": "mercurial-5.4-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4.1-1-x86_64.pkg.tar.zst", "version": "5.4.1-1", "length": 5000000, "filename": "mercurial-5.4.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.4.2-1-x86_64.pkg.tar.zst", "version": "5.4.2-1", "length": 5000000, "filename": "mercurial-5.4.2-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.5-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.5-1-x86_64.pkg.tar.zst", "version": "5.5-1", "length": 5000000, "filename": "mercurial-5.5-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.5.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.5.1-1-x86_64.pkg.tar.zst", "version": "5.5.1-1", "length": 5000000, "filename": "mercurial-5.5.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.5.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.5.2-1-x86_64.pkg.tar.zst", "version": "5.5.2-1", "length": 5000000, "filename": "mercurial-5.5.2-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6-1-x86_64.pkg.tar.zst", "version": "5.6-1", "length": 5000000, "filename": "mercurial-5.6-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6-2-x86_64.pkg.tar.zst", "version": "5.6-2", "length": 5000000, "filename": "mercurial-5.6-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6-3-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6-3-x86_64.pkg.tar.zst", "version": "5.6-3", "length": 5000000, "filename": "mercurial-5.6-3-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.6.1-1-x86_64.pkg.tar.zst", "version": "5.6.1-1", "length": 5000000, "filename": "mercurial-5.6.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.7-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.7-1-x86_64.pkg.tar.zst", "version": "5.7-1", "length": 5000000, "filename": "mercurial-5.7-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.7.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.7.1-1-x86_64.pkg.tar.zst", "version": "5.7.1-1", "length": 5000000, "filename": "mercurial-5.7.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.8-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.8-1-x86_64.pkg.tar.zst", "version": "5.8-1", "length": 5000000, "filename": "mercurial-5.8-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.8-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.8-2-x86_64.pkg.tar.zst", "version": "5.8-2", "length": 5000000, "filename": "mercurial-5.8-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.8.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.8.1-1-x86_64.pkg.tar.zst", "version": "5.8.1-1", "length": 5000000, "filename": "mercurial-5.8.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.1-1-x86_64.pkg.tar.zst", "version": "5.9.1-1", "length": 5000000, "filename": "mercurial-5.9.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.1-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.1-2-x86_64.pkg.tar.zst", "version": "5.9.1-2", "length": 5000000, "filename": "mercurial-5.9.1-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.2-1-x86_64.pkg.tar.zst", "version": "5.9.2-1", "length": 5000000, "filename": "mercurial-5.9.2-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.3-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-5.9.3-1-x86_64.pkg.tar.zst", "version": "5.9.3-1", "length": 5000000, "filename": "mercurial-5.9.3-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0-1-x86_64.pkg.tar.zst", "version": "6.0-1", "length": 5000000, "filename": "mercurial-6.0-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0-2-x86_64.pkg.tar.zst", "version": "6.0-2", "length": 5000000, "filename": "mercurial-6.0-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0-3-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0-3-x86_64.pkg.tar.zst", "version": "6.0-3", "length": 5000000, "filename": "mercurial-6.0-3-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0.1-1-x86_64.pkg.tar.zst", "version": "6.0.1-1", "length": 5000000, "filename": "mercurial-6.0.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0.2-1-x86_64.pkg.tar.zst", "version": "6.0.2-1", "length": 5000000, "filename": "mercurial-6.0.2-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0.3-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.0.3-1-x86_64.pkg.tar.zst", "version": "6.0.3-1", "length": 5000000, "filename": "mercurial-6.0.3-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1-1-x86_64.pkg.tar.zst", "version": "6.1-1", "length": 5000000, "filename": "mercurial-6.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1-2-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1-2-x86_64.pkg.tar.zst", "version": "6.1-2", "length": 5000000, "filename": "mercurial-6.1-2-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1.1-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1.1-1-x86_64.pkg.tar.zst", "version": "6.1.1-1", "length": 5000000, "filename": "mercurial-6.1.1-1-x86_64.pkg.tar.zst", + "checksums": { + "length": 5000000, + }, }, { - "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1.2-1-x86_64.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/m/mercurial/mercurial-6.1.2-1-x86_64.pkg.tar.zst", "version": "6.1.2-1", "length": 5000000, "filename": "mercurial-6.1.2-1-x86_64.pkg.tar.zst", + "checksums": { + "md5": "037ff48bf6127e9d37ad7da7026a6dc0", + "sha256": "be33e7bf800d1e84714cd40029d103873e65f5a72dea19d6ad935f3439512cf8", + }, }, ], "arch_metadata": [ { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "4.8.2-1", "last_modified": "2019-01-15T20:31:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "4.9-1", "last_modified": "2019-02-12T06:15:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "4.9.1-1", "last_modified": "2019-03-30T17:40:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.0-1", "last_modified": "2019-05-10T08:44:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.0.1-1", "last_modified": "2019-06-10T18:05:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.0.2-1", "last_modified": "2019-07-10T04:58:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.1-1", "last_modified": "2019-08-17T19:58:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.1.2-1", "last_modified": "2019-10-08T08:38:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.2-1", "last_modified": "2019-11-28T06:41:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.2.1-1", "last_modified": "2020-01-06T12:35:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.2.2-1", "last_modified": "2020-01-15T14:07:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.2.2-2", "last_modified": "2020-01-30T20:05:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.3-1", "last_modified": "2020-02-13T21:40:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.3.1-1", "last_modified": "2020-03-07T23:58:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.3.2-1", "last_modified": "2020-04-05T17:48:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.4-1", "last_modified": "2020-05-10T17:19:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.4-2", "last_modified": "2020-06-04T13:38:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.4.1-1", "last_modified": "2020-06-06T12:28:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.4.2-1", "last_modified": "2020-07-02T21:35:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.5-1", "last_modified": "2020-08-05T10:39:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.5.1-1", "last_modified": "2020-09-03T19:05:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.5.2-1", "last_modified": "2020-10-07T20:05:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.6-1", "last_modified": "2020-11-03T17:26:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.6-2", "last_modified": "2020-11-09T16:54:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.6-3", "last_modified": "2020-11-11T15:20:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.6.1-1", "last_modified": "2020-12-05T12:29:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.7-1", "last_modified": "2021-02-04T08:41:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.7.1-1", "last_modified": "2021-03-11T07:51:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.8-1", "last_modified": "2021-05-04T17:55:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.8-2", "last_modified": "2021-05-08T22:08:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.8.1-1", "last_modified": "2021-07-13T07:04:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.9.1-1", "last_modified": "2021-09-01T12:48:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.9.1-2", "last_modified": "2021-09-24T17:39:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.9.2-1", "last_modified": "2021-10-07T21:52:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "5.9.3-1", "last_modified": "2021-10-27T07:20:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.0-1", "last_modified": "2021-11-25T17:10:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.0-2", "last_modified": "2021-11-30T20:53:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.0-3", "last_modified": "2021-12-02T12:06:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.0.1-1", "last_modified": "2022-01-08T10:07:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.0.2-1", "last_modified": "2022-02-03T13:28:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.0.3-1", "last_modified": "2022-02-23T20:50:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.1-1", "last_modified": "2022-03-03T18:06:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.1-2", "last_modified": "2022-03-04T08:37:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.1.1-1", "last_modified": "2022-04-07T18:26:00", }, { "arch": "x86_64", "repo": "extra", "name": "mercurial", "version": "6.1.2-1", "last_modified": "2022-05-07T11:03:00", }, ], }, }, { "url": "https://archlinux.org/packages/community/any/python-hglib", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.1-3-any.pkg.tar.xz", # noqa: B950 + "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.1-3-any.pkg.tar.xz", "version": "2.6.1-3", "length": 40000, "filename": "python-hglib-2.6.1-3-any.pkg.tar.xz", + "checksums": { + "length": 40000, + }, }, { - "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-1-any.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-1-any.pkg.tar.zst", "version": "2.6.2-1", "length": 43000, "filename": "python-hglib-2.6.2-1-any.pkg.tar.zst", + "checksums": { + "length": 43000, + }, }, { - "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-2-any.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-2-any.pkg.tar.zst", "version": "2.6.2-2", "length": 43000, "filename": "python-hglib-2.6.2-2-any.pkg.tar.zst", + "checksums": { + "length": 43000, + }, }, { - "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-3-any.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-3-any.pkg.tar.zst", "version": "2.6.2-3", "length": 43000, "filename": "python-hglib-2.6.2-3-any.pkg.tar.zst", + "checksums": { + "length": 43000, + }, }, { - "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-4-any.pkg.tar.zst", # noqa: B950 + "url": "https://archive.archlinux.org/packages/p/python-hglib/python-hglib-2.6.2-4-any.pkg.tar.zst", "version": "2.6.2-4", "length": 43000, "filename": "python-hglib-2.6.2-4-any.pkg.tar.zst", + "checksums": { + "md5": "ecc6598834dc216efd938466a2425eae", + "sha256": "fd273811023e8c58090d65118d27f5c10ad10ea5d1fbdbcf88c730327cea0952", + }, }, ], "arch_metadata": [ { "arch": "any", "repo": "community", "name": "python-hglib", "version": "2.6.1-3", "last_modified": "2019-11-06T14:08:00", }, { "arch": "any", "repo": "community", "name": "python-hglib", "version": "2.6.2-1", "last_modified": "2020-11-19T22:29:00", }, { "arch": "any", "repo": "community", "name": "python-hglib", "version": "2.6.2-2", "last_modified": "2020-11-19T22:31:00", }, { "arch": "any", "repo": "community", "name": "python-hglib", "version": "2.6.2-3", "last_modified": "2020-11-19T22:35:00", }, { "arch": "any", "repo": "community", "name": "python-hglib", "version": "2.6.2-4", "last_modified": "2021-12-03T00:44:00", }, ], }, }, { "url": "https://archlinuxarm.org/packages/aarch64/gzip", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://uk.mirror.archlinuxarm.org/aarch64/core/gzip-1.12-1-aarch64.pkg.tar.xz", # noqa: B950 + "url": "https://uk.mirror.archlinuxarm.org/aarch64/core/gzip-1.12-1-aarch64.pkg.tar.xz", "length": 79640, "version": "1.12-1", "filename": "gzip-1.12-1-aarch64.pkg.tar.xz", + "checksums": { + "md5": "97d1e76302213f0499f45aa4a4d329cc", + "sha256": "9065fdaf21dfcac231b0e5977599b37596a0d964f48ec0a6bff628084d636d4c", + }, } ], "arch_metadata": [ { "arch": "aarch64", "name": "gzip", "repo": "core", "version": "1.12-1", "last_modified": "2022-04-07T21:08:14", } ], }, }, { "url": "https://archlinuxarm.org/packages/aarch64/mercurial", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://uk.mirror.archlinuxarm.org/aarch64/extra/mercurial-6.1.3-1-aarch64.pkg.tar.xz", # noqa: B950 + "url": "https://uk.mirror.archlinuxarm.org/aarch64/extra/mercurial-6.1.3-1-aarch64.pkg.tar.xz", "length": 4931228, "version": "6.1.3-1", "filename": "mercurial-6.1.3-1-aarch64.pkg.tar.xz", + "checksums": { + "md5": "0464390744f42faba80c323ee7c72406", + "sha256": "635edb47117e7bda0b821d86e61906c802bd880d4a30a64185d9feec1bd25db6", + }, } ], "arch_metadata": [ { "arch": "aarch64", "name": "mercurial", "repo": "extra", "version": "6.1.3-1", "last_modified": "2022-06-02T22:15:18", } ], }, }, { "url": "https://archlinuxarm.org/packages/any/python-hglib", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://uk.mirror.archlinuxarm.org/any/community/python-hglib-2.6.2-4-any.pkg.tar.xz", # noqa: B950 + "url": "https://uk.mirror.archlinuxarm.org/any/community/python-hglib-2.6.2-4-any.pkg.tar.xz", "length": 41432, "version": "2.6.2-4", "filename": "python-hglib-2.6.2-4-any.pkg.tar.xz", + "checksums": { + "md5": "0f763d5e85c4ffe728153f2836838674", + "sha256": "7a873e20d1822403c8ecf0c790de02439368000e9b1b74881788a9faea8c81b6", + }, } ], "arch_metadata": [ { "arch": "any", "name": "python-hglib", "repo": "community", "version": "2.6.2-4", "last_modified": "2021-12-14T16:22:20", } ], }, }, { "url": "https://archlinuxarm.org/packages/armv7h/gzip", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://uk.mirror.archlinuxarm.org/armv7h/core/gzip-1.12-1-armv7h.pkg.tar.xz", # noqa: B950 + "url": "https://uk.mirror.archlinuxarm.org/armv7h/core/gzip-1.12-1-armv7h.pkg.tar.xz", "length": 78468, "version": "1.12-1", "filename": "gzip-1.12-1-armv7h.pkg.tar.xz", + "checksums": { + "md5": "490c9e28db91740f1adcea64cb6ec1aa", + "sha256": "4ffc8bbede3bbdd9dd6ad6f85bb689b3f4b985655e56285691db2a1346eaf0e7", + }, } ], "arch_metadata": [ { "arch": "armv7h", "name": "gzip", "repo": "core", "version": "1.12-1", "last_modified": "2022-04-07T21:08:35", } ], }, }, { "url": "https://archlinuxarm.org/packages/armv7h/mercurial", "visit_type": "arch", "extra_loader_arguments": { "artifacts": [ { - "url": "https://uk.mirror.archlinuxarm.org/armv7h/extra/mercurial-6.1.3-1-armv7h.pkg.tar.xz", # noqa: B950 + "url": "https://uk.mirror.archlinuxarm.org/armv7h/extra/mercurial-6.1.3-1-armv7h.pkg.tar.xz", "length": 4897816, "version": "6.1.3-1", "filename": "mercurial-6.1.3-1-armv7h.pkg.tar.xz", + "checksums": { + "md5": "453effa55e32be3ef9de5a58f322b9c4", + "sha256": "c1321de5890a6f53d41c1a5e339733be145221828703f13bccf3e7fc22612396", + }, } ], "arch_metadata": [ { "arch": "armv7h", "name": "mercurial", "repo": "extra", "version": "6.1.3-1", "last_modified": "2022-06-02T22:13:08", } ], }, }, ] def test_arch_lister(datadir, requests_mock_datadir, swh_scheduler): lister = ArchLister(scheduler=swh_scheduler) res = lister.run() assert res.pages == 9 assert res.origins == 11 scheduler_origins = swh_scheduler.get_listed_origins(lister.lister_obj.id).results assert [ ( scheduled.visit_type, scheduled.url, scheduled.extra_loader_arguments["artifacts"], scheduled.extra_loader_arguments["arch_metadata"], ) for scheduled in sorted(scheduler_origins, key=lambda scheduled: scheduled.url) ] == [ ( "arch", expected["url"], expected["extra_loader_arguments"]["artifacts"], expected["extra_loader_arguments"]["arch_metadata"], ) for expected in sorted(expected_origins, key=lambda expected: expected["url"]) ] diff --git a/swh/lister/cpan/tests/test_lister.py b/swh/lister/cpan/tests/test_lister.py index 4554cbb..716feca 100644 --- a/swh/lister/cpan/tests/test_lister.py +++ b/swh/lister/cpan/tests/test_lister.py @@ -1,31 +1,32 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information + from swh.lister.cpan.lister import CpanLister expected_origins = [ "https://metacpan.org/dist/App-Booklist", "https://metacpan.org/dist/EuclideanRhythm", "https://metacpan.org/dist/EventSource-Server", "https://metacpan.org/dist/Getopt_Auto", "https://metacpan.org/dist/Interchange6", "https://metacpan.org/dist/Internals-CountObjects", "https://metacpan.org/dist/openerserver_perl-master", ] def test_cpan_lister(datadir, requests_mock_datadir_visits, swh_scheduler): lister = CpanLister(scheduler=swh_scheduler) res = lister.run() assert res.pages == 3 assert res.origins == 4 + 3 + 0 scheduler_origins = swh_scheduler.get_listed_origins(lister.lister_obj.id).results assert len(scheduler_origins) == len(expected_origins) for origin in scheduler_origins: assert origin.visit_type == "cpan" assert origin.url in expected_origins diff --git a/swh/lister/cran/list_all_packages.R b/swh/lister/cran/list_all_packages.R index 5747bb4..67d9c6d 100755 --- a/swh/lister/cran/list_all_packages.R +++ b/swh/lister/cran/list_all_packages.R @@ -1,9 +1,9 @@ #!/usr/bin/Rscript # This R script calls the buildin API to get list of # all the packages of R and their description, then convert the API # response to JSON string and print it -db <- tools::CRAN_package_db()[, c("Package", "Version", "Packaged")] +db <- tools::CRAN_package_db()[, c("Package", "Version", "Packaged", "MD5sum")] dbjson <- jsonlite::toJSON(db) print(dbjson) \ No newline at end of file diff --git a/swh/lister/cran/lister.py b/swh/lister/cran/lister.py index e9f937a..35e3d2b 100644 --- a/swh/lister/cran/lister.py +++ b/swh/lister/cran/lister.py @@ -1,149 +1,150 @@ # Copyright (C) 2019-2021 the Software Heritage developers # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from datetime import datetime, timezone import json import logging import subprocess from typing import Dict, Iterator, List, Optional, Tuple import pkg_resources from swh.lister.pattern import CredentialsType, StatelessLister from swh.scheduler.interface import SchedulerInterface from swh.scheduler.model import ListedOrigin logger = logging.getLogger(__name__) CRAN_MIRROR = "https://cran.r-project.org" PageType = List[Dict[str, str]] class CRANLister(StatelessLister[PageType]): """ List all packages hosted on The Comprehensive R Archive Network. """ LISTER_NAME = "CRAN" def __init__( self, scheduler: SchedulerInterface, credentials: Optional[CredentialsType] = None, ): super().__init__( scheduler, url=CRAN_MIRROR, instance="cran", credentials=credentials ) def get_pages(self) -> Iterator[PageType]: """ Yields a single page containing all CRAN packages info. """ yield read_cran_data() def get_origins_from_page(self, page: PageType) -> Iterator[ListedOrigin]: assert self.lister_obj.id is not None seen_urls = set() for package_info in page: origin_url, artifact_url = compute_origin_urls(package_info) if origin_url in seen_urls: # prevent multiple listing of an origin, # most recent version will be listed first continue seen_urls.add(origin_url) yield ListedOrigin( lister_id=self.lister_obj.id, url=origin_url, visit_type="cran", last_update=parse_packaged_date(package_info), extra_loader_arguments={ "artifacts": [ { "url": artifact_url, "version": package_info["Version"], "package": package_info["Package"], + "checksums": {"md5": package_info["MD5sum"]}, } ] }, ) def read_cran_data() -> List[Dict[str, str]]: """ Runs R script which uses inbuilt API to return a json response containing data about the R packages. Returns: List of Dict about R packages. For example:: [ { 'Package': 'A3', 'Version': '1.0.0' }, { 'Package': 'abbyyR', 'Version': '0.5.4' }, ... ] """ filepath = pkg_resources.resource_filename("swh.lister.cran", "list_all_packages.R") logger.debug("Executing R script %s", filepath) response = subprocess.run(filepath, stdout=subprocess.PIPE, shell=False) return json.loads(response.stdout.decode("utf-8")) def compute_origin_urls(package_info: Dict[str, str]) -> Tuple[str, str]: """Compute the package url from the repo dict. Args: repo: dict with key 'Package', 'Version' Returns: the tuple project url, artifact url """ package = package_info["Package"] version = package_info["Version"] origin_url = f"{CRAN_MIRROR}/package={package}" artifact_url = f"{CRAN_MIRROR}/src/contrib/{package}_{version}.tar.gz" return origin_url, artifact_url def parse_packaged_date(package_info: Dict[str, str]) -> Optional[datetime]: packaged_at_str = package_info.get("Packaged", "") packaged_at = None if packaged_at_str: packaged_at_str = packaged_at_str.replace(" UTC", "") # Packaged field possible formats: # - "%Y-%m-%d %H:%M:%S[.%f] UTC; ", # - "%a %b %d %H:%M:%S %Y; " for date_format in ( "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", "%a %b %d %H:%M:%S %Y", ): try: packaged_at = datetime.strptime( packaged_at_str.split(";")[0], date_format, ).replace(tzinfo=timezone.utc) break except Exception: continue if packaged_at is None: logger.debug( "Could not parse %s package release date: %s", package_info["Package"], packaged_at_str, ) return packaged_at diff --git a/swh/lister/cran/tests/data/list-r-packages.json b/swh/lister/cran/tests/data/list-r-packages.json index 70ef69c..7357cd5 100644 --- a/swh/lister/cran/tests/data/list-r-packages.json +++ b/swh/lister/cran/tests/data/list-r-packages.json @@ -1,40 +1,32 @@ [ - { - "Package": "SeleMix", - "Version": "1.0.2", - "Packaged": "2020-11-28 22:16:43 UTC; Teresa" + "Package": "cNORM", + "Version": "3.0.2", + "Packaged": "2022-06-12 08:46:39 UTC; gbpa005", + "MD5sum": "d878686afc17b990e500dc88afb3a990" }, { - "Package": "plink", - "Version": "1.5-1", - "Packaged": "2017-04-26 11:36:15 UTC; Jonathan" + "Package": "CNprep", + "Version": "2.2", + "Packaged": "2022-05-23 23:58:37 UTC; Astrid", + "MD5sum": "4b6ddc37df607c79b7fb50a96a57197f" }, { - "Package": "jsonlite", - "Version": "1.7.2", - "Packaged": "2020-12-09 13:54:18 UTC; jeroen" - + "Package": "CNPS", + "Version": "1.0.0", + "Packaged": "2021-05-21 16:55:04 UTC; Surface", + "MD5sum": "deac071a9387e3a296481d041e6d09ee" }, { - "Package": "Records", - "Version": "1.0", - "Packaged": "2012-10-29 08:57:37 UTC; ripley" + "Package": "cns", + "Version": "0.1.0", + "Packaged": "2021-07-16 19:30:51 UTC; nfultz", + "MD5sum": "3ad5a474260dbacb889be461b826a73b" }, { - "Package": "scRNAtools", - "Version": "1.0", - "Packaged": "2018-07-04 00:49:45 UTC; dell" - }, - { - "Package": "Deriv", - "Version": "4.1.2", - "Packaged": "2020-12-10 11:12:28 UTC; sokol" - }, - { - "Package": "BayesValidate", - "Version": "0.0", - "Packaged": "Thu Mar 30 10:48:35 2006; hornik" + "Package": "cnum", + "Version": "0.1.3", + "Packaged": "2021-01-11 13:24:52 UTC; Elgar", + "MD5sum": "3cb5ab3fdaf4277d1ebfbe147e8990e1" } - ] \ No newline at end of file diff --git a/swh/lister/cran/tests/test_lister.py b/swh/lister/cran/tests/test_lister.py index a0bebfc..6501a77 100644 --- a/swh/lister/cran/tests/test_lister.py +++ b/swh/lister/cran/tests/test_lister.py @@ -1,163 +1,164 @@ # Copyright (C) 2019-2021 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from datetime import datetime, timezone import json from os import path import pytest from swh.lister.cran.lister import ( CRAN_MIRROR, CRANLister, compute_origin_urls, parse_packaged_date, ) def test_cran_compute_origin_urls(): pack = "something" vers = "0.0.1" origin_url, artifact_url = compute_origin_urls( { "Package": pack, "Version": vers, } ) assert origin_url == f"{CRAN_MIRROR}/package={pack}" assert artifact_url == f"{CRAN_MIRROR}/src/contrib/{pack}_{vers}.tar.gz" def test_cran_compute_origin_urls_failure(): for incomplete_repo in [{"Version": "0.0.1"}, {"Package": "package"}, {}]: with pytest.raises(KeyError): compute_origin_urls(incomplete_repo) def test_parse_packaged_date(): common_date_format = { "Package": "test", "Packaged": "2017-04-26 11:36:15 UTC; Jonathan", } assert parse_packaged_date(common_date_format) == datetime( year=2017, month=4, day=26, hour=11, minute=36, second=15, tzinfo=timezone.utc ) common_date_format = { "Package": "test", "Packaged": "2017-04-26 11:36:15.123456 UTC; Jonathan", } assert parse_packaged_date(common_date_format) == datetime( year=2017, month=4, day=26, hour=11, minute=36, second=15, microsecond=123456, tzinfo=timezone.utc, ) old_date_format = { "Package": "test", "Packaged": "Thu Mar 30 10:48:35 2006; hornik", } assert parse_packaged_date(old_date_format) == datetime( year=2006, month=3, day=30, hour=10, minute=48, second=35, tzinfo=timezone.utc ) invalid_date_format = { "Package": "test", "Packaged": "foo", } assert parse_packaged_date(invalid_date_format) is None missing_date = { "Package": "test", } assert parse_packaged_date(missing_date) is None def test_cran_lister_cran(datadir, swh_scheduler, mocker): with open(path.join(datadir, "list-r-packages.json")) as f: cran_data = json.loads(f.read()) lister = CRANLister(swh_scheduler) mock_cran = mocker.patch("swh.lister.cran.lister.read_cran_data") mock_cran.return_value = cran_data stats = lister.run() assert stats.pages == 1 assert stats.origins == len(cran_data) scheduler_origins = swh_scheduler.get_listed_origins(lister.lister_obj.id).results assert len(scheduler_origins) == len(cran_data) for package_info in cran_data: origin_url, artifact_url = compute_origin_urls(package_info) filtered_origins = [o for o in scheduler_origins if o.url == origin_url] assert len(filtered_origins) == 1 assert filtered_origins[0].extra_loader_arguments == { "artifacts": [ { "url": artifact_url, "version": package_info["Version"], "package": package_info["Package"], + "checksums": {"md5": package_info["MD5sum"]}, } ] } filtered_origins[0].last_update == parse_packaged_date(package_info) def test_cran_lister_duplicated_origins(datadir, swh_scheduler, mocker): with open(path.join(datadir, "list-r-packages.json")) as f: cran_data = json.loads(f.read()) lister = CRANLister(swh_scheduler) mock_cran = mocker.patch("swh.lister.cran.lister.read_cran_data") mock_cran.return_value = cran_data + cran_data stats = lister.run() assert stats.pages == 1 assert stats.origins == len(cran_data) @pytest.mark.parametrize( "credentials, expected_credentials", [ (None, []), ({"key": "value"}, []), ( {"CRAN": {"cran": [{"username": "user", "password": "pass"}]}}, [{"username": "user", "password": "pass"}], ), ], ) def test_lister_cran_instantiation_with_credentials( credentials, expected_credentials, swh_scheduler ): lister = CRANLister(swh_scheduler, credentials=credentials) # Credentials are allowed in constructor assert lister.credentials == expected_credentials def test_lister_cran_from_configfile(swh_scheduler_config, mocker): load_from_envvar = mocker.patch("swh.lister.pattern.load_from_envvar") load_from_envvar.return_value = { "scheduler": {"cls": "local", **swh_scheduler_config}, "credentials": {}, } lister = CRANLister.from_configfile() assert lister.scheduler is not None assert lister.credentials is not None diff --git a/swh/lister/puppet/lister.py b/swh/lister/puppet/lister.py index 013075d..4982e92 100644 --- a/swh/lister/puppet/lister.py +++ b/swh/lister/puppet/lister.py @@ -1,98 +1,111 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from datetime import datetime import logging from typing import Any, Dict, Iterator, List, Optional from urllib.parse import urljoin from swh.scheduler.interface import SchedulerInterface from swh.scheduler.model import ListedOrigin from ..pattern import CredentialsType, StatelessLister logger = logging.getLogger(__name__) # Aliasing the page results returned by `get_pages` method from the lister. PuppetListerPage = List[Dict[str, Any]] class PuppetLister(StatelessLister[PuppetListerPage]): """The Puppet lister list origins from 'Puppet Forge'""" LISTER_NAME = "puppet" VISIT_TYPE = "puppet" INSTANCE = "puppet" BASE_URL = "https://forgeapi.puppet.com/" def __init__( self, scheduler: SchedulerInterface, credentials: Optional[CredentialsType] = None, ): super().__init__( scheduler=scheduler, credentials=credentials, instance=self.INSTANCE, url=self.BASE_URL, ) def get_pages(self) -> Iterator[PuppetListerPage]: """Yield an iterator which returns 'page' It request the http api endpoint to get a paginated results of modules, and retrieve a `next` url. It ends when `next` json value is `null`. Open Api specification for getModules endpoint: https://forgeapi.puppet.com/#tag/Module-Operations/operation/getModules """ # limit = 100 is the max value for pagination limit: int = 100 response = self.http_request( f"{self.BASE_URL}v3/modules", params={"limit": limit} ) data: Dict[str, Any] = response.json() yield data["results"] while data["pagination"]["next"]: response = self.http_request( urljoin(self.BASE_URL, data["pagination"]["next"]) ) data = response.json() yield data["results"] def get_origins_from_page(self, page: PuppetListerPage) -> Iterator[ListedOrigin]: """Iterate on all pages and yield ListedOrigin instances.""" assert self.lister_obj.id is not None dt_parse_pattern = "%Y-%m-%d %H:%M:%S %z" for entry in page: last_update = datetime.strptime(entry["updated_at"], dt_parse_pattern) pkgname = entry["name"] owner = entry["owner"]["slug"] url = f"https://forge.puppet.com/modules/{owner}/{pkgname}" artifacts = {} for release in entry["releases"]: # Build an artifact entry following original-artifacts-json specification # https://docs.softwareheritage.org/devel/swh-storage/extrinsic-metadata-specification.html#original-artifacts-json # noqa: B950 + checksums = {} + + if release["version"] == entry["current_release"]["version"]: + # checksums are only available for current release + for checksum in ("md5", "sha256"): + checksums[checksum] = entry["current_release"][ + f"file_{checksum}" + ] + else: + # use file length as basic content check instead + checksums["length"] = release["file_size"] + artifacts[release["version"]] = { "filename": release["file_uri"].split("/")[-1], "url": urljoin(self.BASE_URL, release["file_uri"]), "version": release["version"], "last_update": datetime.strptime( release["created_at"], dt_parse_pattern ).isoformat(), + "checksums": checksums, } yield ListedOrigin( lister_id=self.lister_obj.id, visit_type=self.VISIT_TYPE, url=url, last_update=last_update, extra_loader_arguments={"artifacts": artifacts}, ) diff --git a/swh/lister/puppet/tests/test_lister.py b/swh/lister/puppet/tests/test_lister.py index bc2bd07..5dbfd89 100644 --- a/swh/lister/puppet/tests/test_lister.py +++ b/swh/lister/puppet/tests/test_lister.py @@ -1,79 +1,106 @@ # Copyright (C) 2022 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information + from swh.lister.puppet.lister import PuppetLister +# flake8: noqa: B950 + expected_origins = { "https://forge.puppet.com/modules/electrical/file_concat": { "artifacts": { "1.0.0": { - "url": "https://forgeapi.puppet.com/v3/files/electrical-file_concat-1.0.0.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/electrical-file_concat-1.0.0.tar.gz", "version": "1.0.0", "filename": "electrical-file_concat-1.0.0.tar.gz", "last_update": "2015-04-09T12:03:13-07:00", + "checksums": { + "length": 13289, + }, }, "1.0.1": { - "url": "https://forgeapi.puppet.com/v3/files/electrical-file_concat-1.0.1.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/electrical-file_concat-1.0.1.tar.gz", "version": "1.0.1", "filename": "electrical-file_concat-1.0.1.tar.gz", "last_update": "2015-04-17T01:03:46-07:00", + "checksums": { + "md5": "74901a89544134478c2dfde5efbb7f14", + "sha256": "15e973613ea038d8a4f60bafe2d678f88f53f3624c02df3157c0043f4a400de6", + }, }, } }, "https://forge.puppet.com/modules/puppetlabs/puppetdb": { "artifacts": { "1.0.0": { - "url": "https://forgeapi.puppet.com/v3/files/puppetlabs-puppetdb-1.0.0.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/puppetlabs-puppetdb-1.0.0.tar.gz", "version": "1.0.0", "filename": "puppetlabs-puppetdb-1.0.0.tar.gz", "last_update": "2012-09-19T16:51:22-07:00", + "checksums": { + "length": 16336, + }, }, "7.9.0": { - "url": "https://forgeapi.puppet.com/v3/files/puppetlabs-puppetdb-7.9.0.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/puppetlabs-puppetdb-7.9.0.tar.gz", "version": "7.9.0", "filename": "puppetlabs-puppetdb-7.9.0.tar.gz", "last_update": "2021-06-24T07:48:54-07:00", + "checksums": { + "length": 42773, + }, }, "7.10.0": { - "url": "https://forgeapi.puppet.com/v3/files/puppetlabs-puppetdb-7.10.0.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/puppetlabs-puppetdb-7.10.0.tar.gz", "version": "7.10.0", "filename": "puppetlabs-puppetdb-7.10.0.tar.gz", "last_update": "2021-12-16T14:57:46-08:00", + "checksums": { + "md5": "e91a2074ca8d94a8b3ff7f6c8bbf12bc", + "sha256": "49b1a542fbd2a1378c16cb04809e0f88bf4f3e45979532294fb1f03f56c97fbb", + }, }, } }, "https://forge.puppet.com/modules/saz/memcached": { "artifacts": { "1.0.0": { - "url": "https://forgeapi.puppet.com/v3/files/saz-memcached-1.0.0.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/saz-memcached-1.0.0.tar.gz", "version": "1.0.0", "filename": "saz-memcached-1.0.0.tar.gz", "last_update": "2011-11-20T13:40:30-08:00", + "checksums": { + "length": 2472, + }, }, "8.1.0": { - "url": "https://forgeapi.puppet.com/v3/files/saz-memcached-8.1.0.tar.gz", # noqa: B950 + "url": "https://forgeapi.puppet.com/v3/files/saz-memcached-8.1.0.tar.gz", "version": "8.1.0", "filename": "saz-memcached-8.1.0.tar.gz", "last_update": "2022-07-11T03:34:55-07:00", + "checksums": { + "md5": "aadf80fba5848909429eb002ee1927ea", + "sha256": "883d6186e91c2c3fed13ae2009c3aa596657f6707b76f1f7efc6203c6e4ae986", + }, }, } }, } def test_puppet_lister(datadir, requests_mock_datadir, swh_scheduler): lister = PuppetLister(scheduler=swh_scheduler) res = lister.run() assert res.pages == 2 assert res.origins == 1 + 1 + 1 scheduler_origins = swh_scheduler.get_listed_origins(lister.lister_obj.id).results assert len(scheduler_origins) == len(expected_origins) for origin in scheduler_origins: assert origin.visit_type == "puppet" assert origin.url in expected_origins assert origin.extra_loader_arguments == expected_origins[origin.url]