Source code for swh.loader.package.aur.loader

# Copyright (C) 2022-2024  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 pathlib import Path
import re
from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple

import attr

from swh.loader.core.utils import EMPTY_AUTHOR, release_name
from swh.loader.package.loader import BasePackageInfo, PackageLoader
from swh.model.model import ObjectType, Release, Sha1Git, TimestampWithTimezone
from swh.storage.interface import StorageInterface


[docs] @attr.s class AurPackageInfo(BasePackageInfo): name = attr.ib(type=str) """Name of the package""" version = attr.ib(type=str) """Current version""" last_modified = attr.ib(type=str) """File last modified date as release date"""
[docs] def extract_intrinsic_metadata(dir_path: Path) -> Dict[str, Any]: """Extract intrinsic metadata from .SRCINFO file at dir_path. Each Aur package has a .SRCINFO file at the root of the archive. Args: dir_path: A directory on disk where a package has been extracted Returns: A dict mapping """ assert dir_path.exists() # top directory from extracted archive is always named with the package name (pkgname,) = [elt.name for elt in dir_path.iterdir() if elt.is_dir()] srcinfo_path = Path(dir_path, pkgname, ".SRCINFO") rex = re.compile(r"^(\w+)\s=\s(.*)$", re.M) with srcinfo_path.open("r") as content: # Except first and last line, lines may starts with a tab, remove them srcinfo = content.read().replace("\t", "") parsed = rex.findall(srcinfo) data: Dict[str, Any] = {} for k, v in parsed: if k in data: if type(data[k]) is not list: data[k] = [data[k]] data[k].append(v) else: data[k] = v return data
[docs] class AurLoader(PackageLoader[AurPackageInfo]): visit_type = "aur" def __init__( self, storage: StorageInterface, url: str, artifacts: List[Dict[str, Any]], aur_metadata: List[Dict[str, Any]], **kwargs, ): super().__init__(storage=storage, url=url, **kwargs) self.url = url self.artifacts: Dict[str, Dict] = { artifact["version"]: artifact for artifact in artifacts } self.aur_metadata: Dict[str, Dict] = { meta["version"]: meta for meta in aur_metadata }
[docs] def get_versions(self) -> Sequence[str]: """Get all released versions of an Aur package Returns: A sequence of versions Example:: ["0.1.1", "0.10.2"] """ return list(self.artifacts)
[docs] def get_package_info(self, version: str) -> Iterator[Tuple[str, AurPackageInfo]]: """Get release name and package information from version Args: version: aur version (e.g: "0.1.0") Returns: Iterator of tuple (release_name, p_info) """ artifact = self.artifacts[version] assert version == artifact["version"] data = self.aur_metadata[version] url = artifact["url"] filename = artifact["filename"] p_info = AurPackageInfo( name=data["pkgname"], filename=filename, url=url, version=version, last_modified=data["last_update"], ) yield release_name(version, filename), p_info
[docs] def build_release( self, p_info: AurPackageInfo, uncompressed_path: str, directory: Sha1Git ) -> Optional[Release]: intrinsic_metadata = extract_intrinsic_metadata(Path(uncompressed_path)) author = EMPTY_AUTHOR description: str = "" assert intrinsic_metadata["pkgdesc"] if type(intrinsic_metadata["pkgdesc"]) is list: description = "\n".join(intrinsic_metadata["pkgdesc"]) else: description = intrinsic_metadata["pkgdesc"] message = ( f"Synthetic release for Aur source package {p_info.name} " f"version {p_info.version}\n\n" f"{description}\n" ) return Release( name=p_info.version.encode(), author=author, date=TimestampWithTimezone.from_iso8601(p_info.last_modified), message=message.encode(), target_type=ObjectType.DIRECTORY, target=directory, synthetic=True, )