handle architecture specific fields for dependencies

This change requires srcinfo at least 0.1.2 version. Unfortunatelly aur
api don't support architecture specific arrays for now, so we just leave
it as is

Closes #82
This commit is contained in:
Evgenii Alekseev 2023-01-31 14:34:09 +02:00
parent 0a2ba4ae07
commit 917ec48be5
10 changed files with 81 additions and 19 deletions

View File

@ -84,7 +84,7 @@ class ApplicationPackages(ApplicationProperties):
without_dependencies(bool): if set, dependency check will be disabled without_dependencies(bool): if set, dependency check will be disabled
""" """
source_dir = Path(source) source_dir = Path(source)
package = Package.from_build(source_dir) package = Package.from_build(source_dir, self.architecture)
cache_dir = self.repository.paths.cache_for(package.base) cache_dir = self.repository.paths.cache_for(package.base)
shutil.copytree(source_dir, cache_dir) # copy package to store in caches shutil.copytree(source_dir, cache_dir) # copy package to store in caches
Sources.init(cache_dir) # we need to run init command in directory where we do have permissions Sources.init(cache_dir) # we need to run init command in directory where we do have permissions

View File

@ -111,7 +111,7 @@ class ApplicationRepository(ApplicationProperties):
def unknown_local(probe: Package) -> List[str]: def unknown_local(probe: Package) -> List[str]:
cache_dir = self.repository.paths.cache_for(probe.base) cache_dir = self.repository.paths.cache_for(probe.base)
local = Package.from_build(cache_dir) local = Package.from_build(cache_dir, self.architecture)
packages = set(probe.packages.keys()).difference(local.packages.keys()) packages = set(probe.packages.keys()).difference(local.packages.keys())
return list(packages) return list(packages)

View File

@ -58,7 +58,7 @@ class Patch(Handler):
patch = Patch.patch_create_from_function(args.variable, args.patch) patch = Patch.patch_create_from_function(args.variable, args.patch)
Patch.patch_set_create(application, args.package, patch) Patch.patch_set_create(application, args.package, patch)
elif args.action == Action.Update and args.variable is None: elif args.action == Action.Update and args.variable is None:
package_base, patch = Patch.patch_create_from_diff(args.package, args.track) package_base, patch = Patch.patch_create_from_diff(args.package, architecture, args.track)
Patch.patch_set_create(application, package_base, patch) Patch.patch_set_create(application, package_base, patch)
elif args.action == Action.List: elif args.action == Action.List:
Patch.patch_set_list(application, args.package, args.variable, args.exit_code) Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
@ -66,19 +66,20 @@ class Patch(Handler):
Patch.patch_set_remove(application, args.package, args.variable) Patch.patch_set_remove(application, args.package, args.variable)
@staticmethod @staticmethod
def patch_create_from_diff(sources_dir: Path, track: List[str]) -> Tuple[str, PkgbuildPatch]: def patch_create_from_diff(sources_dir: Path, architecture: str, track: List[str]) -> Tuple[str, PkgbuildPatch]:
""" """
create PKGBUILD plain diff patches from sources directory create PKGBUILD plain diff patches from sources directory
Args: Args:
sources_dir(Path): path to directory with the package sources sources_dir(Path): path to directory with the package sources
architecture(str): repository architecture
track(List[str]): track files which match the glob before creating the patch track(List[str]): track files which match the glob before creating the patch
Returns: Returns:
Tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD Tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
to current files to current files
""" """
package = Package.from_build(sources_dir) package = Package.from_build(sources_dir, architecture)
patch = Sources.patch_create(sources_dir, *track) patch = Sources.patch_create(sources_dir, *track)
return package.base, PkgbuildPatch(None, patch) return package.base, PkgbuildPatch(None, patch)

View File

@ -98,7 +98,7 @@ class UpdateHandler(Cleaner):
with self.in_package_context(cache_dir.name): with self.in_package_context(cache_dir.name):
try: try:
Sources.fetch(cache_dir, remote=None) Sources.fetch(cache_dir, remote=None)
remote = Package.from_build(cache_dir) remote = Package.from_build(cache_dir, self.architecture)
local = packages.get(remote.base) local = packages.get(remote.base)
if local is None: if local is None:

View File

@ -201,12 +201,13 @@ class Package(LazyLogging):
packages={package.name: PackageDescription.from_aur(package)}) packages={package.name: PackageDescription.from_aur(package)})
@classmethod @classmethod
def from_build(cls: Type[Package], path: Path) -> Package: def from_build(cls: Type[Package], path: Path, architecture: str) -> Package:
""" """
construct package properties from sources directory construct package properties from sources directory
Args: Args:
path(Path): path to package sources directory path(Path): path to package sources directory
architecture(str): load package for specific architecture
Returns: Returns:
Package: package properties Package: package properties
@ -220,13 +221,16 @@ class Package(LazyLogging):
raise PackageInfoError(errors) raise PackageInfoError(errors)
def get_property(key: str, properties: Dict[str, Any], default: Any) -> Any: def get_property(key: str, properties: Dict[str, Any], default: Any) -> Any:
return properties.get(key, srcinfo.get(key, default)) return properties.get(key) or srcinfo.get(key) or default
def get_list(key: str, properties: Dict[str, Any]) -> Any:
return get_property(key, properties, []) + get_property(f"{key}_{architecture}", properties, [])
packages = { packages = {
package: PackageDescription( package: PackageDescription(
depends=get_property("depends", properties, []), depends=get_list("depends", properties),
make_depends=get_property("makedepends", properties, []), make_depends=get_list("makedepends", properties),
opt_depends=get_property("optdepends", properties, []), opt_depends=get_list("optdepends", properties),
) )
for package, properties in srcinfo["packages"].items() for package, properties in srcinfo["packages"].items()
} }

View File

@ -45,7 +45,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create") application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
Patch.run(args, "x86_64", configuration, report=False, unsafe=False) Patch.run(args, "x86_64", configuration, report=False, unsafe=False)
patch_mock.assert_called_once_with(args.package, args.track) patch_mock.assert_called_once_with(args.package, "x86_64", args.track)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, PkgbuildPatch(None, "patch")) application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, PkgbuildPatch(None, "patch"))
@ -108,8 +108,8 @@ def test_patch_create_from_diff(package_ahriman: Package, mocker: MockerFixture)
package_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman) package_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
sources_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_create", return_value=patch.value) sources_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_create", return_value=patch.value)
assert Patch.patch_create_from_diff(path, ["*.diff"]) == (package_ahriman.base, patch) assert Patch.patch_create_from_diff(path, "x86_64", ["*.diff"]) == (package_ahriman.base, patch)
package_mock.assert_called_once_with(path) package_mock.assert_called_once_with(path, "x86_64")
sources_mock.assert_called_once_with(path, "*.diff") sources_mock.assert_called_once_with(path, "*.diff")

View File

@ -120,7 +120,7 @@ def test_updates_local(update_handler: UpdateHandler, package_ahriman: Package,
assert update_handler.updates_local(vcs=True) == [package_ahriman] assert update_handler.updates_local(vcs=True) == [package_ahriman]
fetch_mock.assert_called_once_with(Path(package_ahriman.base), remote=None) fetch_mock.assert_called_once_with(Path(package_ahriman.base), remote=None)
package_load_mock.assert_called_once_with(Path(package_ahriman.base)) package_load_mock.assert_called_once_with(Path(package_ahriman.base), "x86_64")
status_client_mock.assert_called_once_with(package_ahriman.base) status_client_mock.assert_called_once_with(package_ahriman.base)
package_is_outdated_mock.assert_called_once_with( package_is_outdated_mock.assert_called_once_with(
package_ahriman, update_handler.paths, package_ahriman, update_handler.paths,

View File

@ -358,6 +358,7 @@ def test_walk(resource_path_root: Path) -> None:
resource_path_root / "models" / "package_akonadi_aur", resource_path_root / "models" / "package_akonadi_aur",
resource_path_root / "models" / "package_ahriman_srcinfo", resource_path_root / "models" / "package_ahriman_srcinfo",
resource_path_root / "models" / "package_gcc10_srcinfo", resource_path_root / "models" / "package_gcc10_srcinfo",
resource_path_root / "models" / "package_jellyfin-ffmpeg5-bin_srcinfo",
resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo", resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo",
resource_path_root / "models" / "package_yay_srcinfo", resource_path_root / "models" / "package_yay_srcinfo",
resource_path_root / "web" / "templates" / "build-status" / "alerts.jinja2", resource_path_root / "web" / "templates" / "build-status" / "alerts.jinja2",

View File

@ -51,7 +51,7 @@ def test_depends_build_with_version_and_overlap(mocker: MockerFixture, resource_
srcinfo = (resource_path_root / "models" / "package_gcc10_srcinfo").read_text() srcinfo = (resource_path_root / "models" / "package_gcc10_srcinfo").read_text()
mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo) mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo)
package_gcc10 = Package.from_build(Path("local")) package_gcc10 = Package.from_build(Path("local"), "x86_64")
assert package_gcc10.depends_build == {"glibc", "doxygen", "binutils", "git", "libmpc", "python", "zstd"} assert package_gcc10.depends_build == {"glibc", "doxygen", "binutils", "git", "libmpc", "python", "zstd"}
@ -154,7 +154,7 @@ def test_from_build(package_ahriman: Package, mocker: MockerFixture, resource_pa
srcinfo = (resource_path_root / "models" / "package_ahriman_srcinfo").read_text() srcinfo = (resource_path_root / "models" / "package_ahriman_srcinfo").read_text()
mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo) mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo)
package = Package.from_build(Path("path")) package = Package.from_build(Path("path"), "x86_64")
assert package_ahriman.packages.keys() == package.packages.keys() assert package_ahriman.packages.keys() == package.packages.keys()
package_ahriman.packages = package.packages # we are not going to test PackageDescription here package_ahriman.packages = package.packages # we are not going to test PackageDescription here
package_ahriman.remote = None package_ahriman.remote = None
@ -168,7 +168,7 @@ def test_from_build_multiple_packages(mocker: MockerFixture, resource_path_root:
srcinfo = (resource_path_root / "models" / "package_gcc10_srcinfo").read_text() srcinfo = (resource_path_root / "models" / "package_gcc10_srcinfo").read_text()
mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo) mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo)
package = Package.from_build(Path("path")) package = Package.from_build(Path("path"), "x86_64")
assert package.packages == { assert package.packages == {
"gcc10": PackageDescription( "gcc10": PackageDescription(
depends=["gcc10-libs=10.3.0-2", "binutils>=2.28", "libmpc", "zstd"], depends=["gcc10-libs=10.3.0-2", "binutils>=2.28", "libmpc", "zstd"],
@ -188,6 +188,34 @@ def test_from_build_multiple_packages(mocker: MockerFixture, resource_path_root:
} }
def test_from_build_architecture(mocker: MockerFixture, resource_path_root: Path) -> None:
"""
must construct package with architecture specific depends list
"""
srcinfo = (resource_path_root / "models" / "package_jellyfin-ffmpeg5-bin_srcinfo").read_text()
mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo)
package = Package.from_build(Path("path"), "x86_64")
assert package.packages == {
"jellyfin-ffmpeg5-bin": PackageDescription(
depends=["glibc"],
make_depends=[],
opt_depends=[
"intel-media-driver: for Intel VAAPI support (Broadwell and newer)",
"intel-media-sdk: for Intel Quick Sync Video",
"onevpl-intel-gpu: for Intel Quick Sync Video (12th Gen and newer)",
"intel-compute-runtime: for Intel OpenCL runtime based Tonemapping",
"libva-intel-driver: for Intel legacy VAAPI support (10th Gen and older)",
"libva-mesa-driver: for AMD VAAPI support",
"nvidia-utils: for Nvidia NVDEC/NVENC support",
"opencl-amd: for AMD OpenCL runtime based Tonemapping",
"vulkan-radeon: for AMD RADV Vulkan support",
"vulkan-intel: for Intel ANV Vulkan support",
],
),
}
def test_from_build_failed(package_ahriman: Package, mocker: MockerFixture) -> None: def test_from_build_failed(package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
must raise exception if there are errors during srcinfo load must raise exception if there are errors during srcinfo load
@ -196,7 +224,7 @@ def test_from_build_failed(package_ahriman: Package, mocker: MockerFixture) -> N
mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"])) mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"]))
with pytest.raises(PackageInfoError): with pytest.raises(PackageInfoError):
Package.from_build(Path("path")) Package.from_build(Path("path"), "x86_64")
def test_from_json_view_1(package_ahriman: Package) -> None: def test_from_json_view_1(package_ahriman: Package) -> None:

View File

@ -0,0 +1,28 @@
pkgbase = jellyfin-ffmpeg5-bin
pkgdesc = FFmpeg5 binary version for Jellyfin
pkgver = 5.1.2
pkgrel = 7
url = https://github.com/jellyfin/jellyfin-ffmpeg
arch = x86_64
arch = aarch64
license = GPL3
optdepends = intel-media-driver: for Intel VAAPI support (Broadwell and newer)
optdepends = intel-media-sdk: for Intel Quick Sync Video
optdepends = onevpl-intel-gpu: for Intel Quick Sync Video (12th Gen and newer)
optdepends = intel-compute-runtime: for Intel OpenCL runtime based Tonemapping
optdepends = libva-intel-driver: for Intel legacy VAAPI support (10th Gen and older)
optdepends = libva-mesa-driver: for AMD VAAPI support
optdepends = nvidia-utils: for Nvidia NVDEC/NVENC support
optdepends = opencl-amd: for AMD OpenCL runtime based Tonemapping
optdepends = vulkan-radeon: for AMD RADV Vulkan support
optdepends = vulkan-intel: for Intel ANV Vulkan support
conflicts = jellyfin-ffmpeg
conflicts = jellyfin-ffmpeg5
source_x86_64 = https://repo.jellyfin.org/releases/ffmpeg/5.1.2-7/jellyfin-ffmpeg_5.1.2-7_portable_linux64-gpl.tar.xz
depends_x86_64 = glibc>=2.23
sha256sums_x86_64 = 78420fd1edbaf24a07e92938878d8582d895e009cae02c8e9d5be3f26de905e3
source_aarch64 = https://repo.jellyfin.org/releases/ffmpeg/5.1.2-7/jellyfin-ffmpeg_5.1.2-7_portable_linuxarm64-gpl.tar.xz
depends_aarch64 = glibc>=2.27
sha256sums_aarch64 = 8ac4066981f203c2b442754eaf7286b4e481df9692d0ff8910a824d89c831df0
pkgname = jellyfin-ffmpeg5-bin