From c1f174ed79ebf40c6f8948c97ac5104e342a896e Mon Sep 17 00:00:00 2001 From: Evgeniy Alekseev Date: Sat, 2 Oct 2021 22:45:14 +0300 Subject: [PATCH] patch support --- src/ahriman/application/application.py | 10 +- src/ahriman/core/build_tools/sources.py | 83 ++++++++++++++ src/ahriman/core/build_tools/task.py | 45 ++------ src/ahriman/core/tree.py | 13 ++- src/ahriman/models/package.py | 16 +-- src/ahriman/models/repository_paths.py | 40 +++++++ tests/ahriman/application/test_application.py | 6 +- .../ahriman/core/build_tools/test_sources.py | 107 ++++++++++++++++++ tests/ahriman/core/build_tools/test_task.py | 50 +------- tests/ahriman/core/test_tree.py | 18 +-- tests/ahriman/models/test_package.py | 6 +- tests/ahriman/models/test_repository_paths.py | 41 ++++++- 12 files changed, 313 insertions(+), 122 deletions(-) create mode 100644 src/ahriman/core/build_tools/sources.py create mode 100644 tests/ahriman/core/build_tools/test_sources.py diff --git a/src/ahriman/application/application.py b/src/ahriman/application/application.py index 07111db4..241f473a 100644 --- a/src/ahriman/application/application.py +++ b/src/ahriman/application/application.py @@ -23,7 +23,7 @@ import shutil from pathlib import Path from typing import Callable, Iterable, List, Set -from ahriman.core.build_tools.task import Task +from ahriman.core.build_tools.sources import Sources from ahriman.core.configuration import Configuration from ahriman.core.repository.repository import Repository from ahriman.core.tree import Tree @@ -112,9 +112,9 @@ class Application: def add_manual(src: str) -> Path: package = Package.load(src, self.repository.pacman, self.configuration.get("alpm", "aur_url")) - path = self.repository.paths.manual / package.base - Task.fetch(path, package.git_url) - return path + Sources.load(self.repository.paths.manual_for(package.base), package.git_url, + self.repository.paths.patches_for(package.base)) + return self.repository.paths.manual_for(package.base) def add_archive(src: Path) -> None: dst = self.repository.paths.packages / src.name @@ -238,7 +238,7 @@ class Application: process_update(packages) # process manual packages - tree = Tree.load(updates) + tree = Tree.load(updates, self.repository.paths) for num, level in enumerate(tree.levels()): self.logger.info("processing level #%i %s", num, [package.base for package in level]) packages = self.repository.process_build(level) diff --git a/src/ahriman/core/build_tools/sources.py b/src/ahriman/core/build_tools/sources.py new file mode 100644 index 00000000..9ffb3157 --- /dev/null +++ b/src/ahriman/core/build_tools/sources.py @@ -0,0 +1,83 @@ +# +# Copyright (c) 2021 ahriman team. +# +# This file is part of ahriman +# (see https://github.com/arcan1s/ahriman). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +import logging + +from pathlib import Path + +from ahriman.core.util import check_output + + +class Sources: + """ + helper to download package sources (PKGBUILD etc) + """ + + _check_output = check_output + + @staticmethod + def fetch(local_path: Path, remote: str, branch: str = "master") -> None: + """ + either clone repository or update it to origin/`branch` + :param local_path: local path to fetch + :param remote: remote target (from where to fetch) + :param branch: branch name to checkout, master by default + """ + logger = logging.getLogger("build_details") + # local directory exists and there is .git directory + if (local_path / ".git").is_dir(): + logger.info("update HEAD to remote to %s", local_path) + Sources._check_output("git", "fetch", "origin", branch, exception=None, cwd=local_path, logger=logger) + else: + logger.info("clone remote %s to %s", remote, local_path) + Sources._check_output("git", "clone", remote, str(local_path), exception=None, logger=logger) + # and now force reset to our branch + Sources._check_output("git", "checkout", "--force", branch, exception=None, cwd=local_path, logger=logger) + Sources._check_output("git", "reset", "--hard", f"origin/{branch}", + exception=None, cwd=local_path, logger=logger) + + @staticmethod + def load(local_path: Path, remote: str, patch_path: Path) -> None: + """ + fetch sources from remote and apply patches + :param local_path: local path to fetch + :param remote: remote target (from where to fetch) + :param patch_path: path to directory with package patches + """ + Sources.fetch(local_path, remote) + Sources.patch(local_path, patch_path) + + @staticmethod + def patch(local_path: Path, patch_path: Path) -> None: + """ + apply patches if any + :param local_path: local path to directory with git sources + :param patch_path: path to directory with package patches + """ + # check if even there are patches + if not patch_path.is_dir(): + return # no patches provided + logger = logging.getLogger("build_details") + # find everything that looks like patch and sort it + patches = sorted(patch_path.glob("*.patch")) + logger.info("found %s patches", patches) + for patch in patches: + logger.info("apply patch %s", patch.name) + Sources._check_output("git", "apply", "--ignore-space-change", "--ignore-whitespace", str(patch), + exception=None, cwd=local_path, logger=logger) diff --git a/src/ahriman/core/build_tools/task.py b/src/ahriman/core/build_tools/task.py index 0b0ecf0f..48195843 100644 --- a/src/ahriman/core/build_tools/task.py +++ b/src/ahriman/core/build_tools/task.py @@ -23,6 +23,7 @@ import shutil from pathlib import Path from typing import List, Optional +from ahriman.core.build_tools.sources import Sources from ahriman.core.configuration import Configuration from ahriman.core.exceptions import BuildFailed from ahriman.core.util import check_output @@ -58,38 +59,6 @@ class Task: self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[]) self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[]) - @property - def cache_path(self) -> Path: - """ - :return: path to cached packages - """ - return self.paths.cache / self.package.base - - @property - def git_path(self) -> Path: - """ - :return: path to clone package from git - """ - return self.paths.sources / self.package.base - - @staticmethod - def fetch(local: Path, remote: str, branch: str = "master") -> None: - """ - either clone repository or update it to origin/`branch` - :param local: local path to fetch - :param remote: remote target (from where to fetch) - :param branch: branch name to checkout, master by default - """ - logger = logging.getLogger("build_details") - # local directory exists and there is .git directory - if (local / ".git").is_dir(): - Task._check_output("git", "fetch", "origin", branch, exception=None, cwd=local, logger=logger) - else: - Task._check_output("git", "clone", remote, str(local), exception=None, logger=logger) - # and now force reset to our branch - Task._check_output("git", "checkout", "--force", branch, exception=None, cwd=local, logger=logger) - Task._check_output("git", "reset", "--hard", f"origin/{branch}", exception=None, cwd=local, logger=logger) - def build(self) -> List[Path]: """ run package build @@ -104,13 +73,13 @@ class Task: Task._check_output( *command, exception=BuildFailed(self.package.base), - cwd=self.git_path, + cwd=self.paths.sources_for(self.package.base), logger=self.build_logger) # well it is not actually correct, but we can deal with it packages = Task._check_output("makepkg", "--packagelist", exception=BuildFailed(self.package.base), - cwd=self.git_path, + cwd=self.paths.sources_for(self.package.base), logger=self.build_logger).splitlines() return [Path(package) for package in packages] @@ -119,8 +88,8 @@ class Task: fetch package from git :param path: optional local path to fetch. If not set default path will be used """ - git_path = path or self.git_path - if self.cache_path.is_dir(): + git_path = path or self.paths.sources_for(self.package.base) + if self.paths.cache_for(self.package.base).is_dir(): # no need to clone whole repository, just copy from cache first - shutil.copytree(self.cache_path, git_path) - return self.fetch(git_path, self.package.git_url) + shutil.copytree(self.paths.cache_for(self.package.base), git_path) + Sources.load(git_path, self.package.git_url, self.paths.patches_for(self.package.base)) diff --git a/src/ahriman/core/tree.py b/src/ahriman/core/tree.py index 56b1ac41..e7cb7ff7 100644 --- a/src/ahriman/core/tree.py +++ b/src/ahriman/core/tree.py @@ -25,8 +25,9 @@ import tempfile from pathlib import Path from typing import Iterable, List, Set, Type -from ahriman.core.build_tools.task import Task +from ahriman.core.build_tools.sources import Sources from ahriman.models.package import Package +from ahriman.models.repository_paths import RepositoryPaths class Leaf: @@ -53,15 +54,16 @@ class Leaf: return self.package.packages.keys() @classmethod - def load(cls: Type[Leaf], package: Package) -> Leaf: + def load(cls: Type[Leaf], package: Package, paths: RepositoryPaths) -> Leaf: """ load leaf from package with dependencies :param package: package properties + :param paths: repository paths instance :return: loaded class """ clone_dir = Path(tempfile.mkdtemp()) try: - Task.fetch(clone_dir, package.git_url) + Sources.load(clone_dir, package.git_url, paths.patches_for(package.base)) dependencies = Package.dependencies(clone_dir) finally: shutil.rmtree(clone_dir, ignore_errors=True) @@ -93,13 +95,14 @@ class Tree: self.leaves = leaves @classmethod - def load(cls: Type[Tree], packages: Iterable[Package]) -> Tree: + def load(cls: Type[Tree], packages: Iterable[Package], paths: RepositoryPaths) -> Tree: """ load tree from packages :param packages: packages list + :param paths: repository paths instance :return: loaded class """ - return cls([Leaf.load(package) for package in packages]) + return cls([Leaf.load(package, paths) for package in packages]) def levels(self) -> List[List[Package]]: """ diff --git a/src/ahriman/models/package.py b/src/ahriman/models/package.py index 19676588..fd048444 100644 --- a/src/ahriman/models/package.py +++ b/src/ahriman/models/package.py @@ -231,22 +231,18 @@ class Package: if not self.is_vcs: return self.version - from ahriman.core.build_tools.task import Task + from ahriman.core.build_tools.sources import Sources - clone_dir = paths.cache / self.base logger = logging.getLogger("build_details") - Task.fetch(clone_dir, self.git_url) + Sources.load(paths.cache_for(self.base), self.git_url, paths.patches_for(self.base)) try: # update pkgver first - Package._check_output("makepkg", "--nodeps", "--nobuild", exception=None, cwd=clone_dir, logger=logger) + Package._check_output("makepkg", "--nodeps", "--nobuild", + exception=None, cwd=paths.cache_for(self.base), logger=logger) # generate new .SRCINFO and put it to parser - srcinfo_source = Package._check_output( - "makepkg", - "--printsrcinfo", - exception=None, - cwd=clone_dir, - logger=logger) + srcinfo_source = Package._check_output("makepkg", "--printsrcinfo", + exception=None, cwd=paths.cache_for(self.base), logger=logger) srcinfo, errors = parse_srcinfo(srcinfo_source) if errors: raise InvalidPackageInfo(errors) diff --git a/src/ahriman/models/repository_paths.py b/src/ahriman/models/repository_paths.py index 12c6ebfa..1025c111 100644 --- a/src/ahriman/models/repository_paths.py +++ b/src/ahriman/models/repository_paths.py @@ -64,6 +64,13 @@ class RepositoryPaths: """ return self.root / "packages" / self.architecture + @property + def patches(self) -> Path: + """ + :return: directory for source patches + """ + return self.root / "patches" + @property def repository(self) -> Path: """ @@ -92,6 +99,14 @@ class RepositoryPaths: if path.is_dir() } + def cache_for(self, package_base: str) -> Path: + """ + get cache path for specific package base + :param package_base: package base name + :return: full path to directory for specified package base cache + """ + return self.cache / package_base + def create_tree(self) -> None: """ create ahriman working tree @@ -100,5 +115,30 @@ class RepositoryPaths: self.chroot.mkdir(mode=0o755, parents=True, exist_ok=True) self.manual.mkdir(mode=0o755, parents=True, exist_ok=True) self.packages.mkdir(mode=0o755, parents=True, exist_ok=True) + self.patches.mkdir(mode=0o755, parents=True, exist_ok=True) self.repository.mkdir(mode=0o755, parents=True, exist_ok=True) self.sources.mkdir(mode=0o755, parents=True, exist_ok=True) + + def manual_for(self, package_base: str) -> Path: + """ + get manual path for specific package base + :param package_base: package base name + :return: full path to directory for specified package base manual updates + """ + return self.manual / package_base + + def patches_for(self, package_base: str) -> Path: + """ + get patches path for specific package base + :param package_base: package base name + :return: full path to directory for specified package base patches + """ + return self.patches / package_base + + def sources_for(self, package_base: str) -> Path: + """ + get sources path for specific package base + :param package_base: package base name + :return: full path to directory for specified package base sources + """ + return self.sources / package_base diff --git a/tests/ahriman/application/test_application.py b/tests/ahriman/application/test_application.py index 85f1b25b..b8c30341 100644 --- a/tests/ahriman/application/test_application.py +++ b/tests/ahriman/application/test_application.py @@ -124,10 +124,10 @@ def test_add_manual(application: Application, package_ahriman: Package, mocker: """ mocker.patch("ahriman.application.application.Application._known_packages", return_value=set()) mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman) - fetch_mock = mocker.patch("ahriman.core.build_tools.task.Task.fetch") + load_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.load") application.add([package_ahriman.base], PackageSource.AUR, True) - fetch_mock.assert_called_once() + load_mock.assert_called_once() def test_add_manual_with_dependencies(application: Application, package_ahriman: Package, @@ -137,7 +137,7 @@ def test_add_manual_with_dependencies(application: Application, package_ahriman: """ mocker.patch("ahriman.application.application.Application._known_packages", return_value=set()) mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman) - mocker.patch("ahriman.core.build_tools.task.Task.fetch") + mocker.patch("ahriman.core.build_tools.sources.Sources.load") dependencies_mock = mocker.patch("ahriman.models.package.Package.dependencies") application.add([package_ahriman.base], PackageSource.AUR, False) diff --git a/tests/ahriman/core/build_tools/test_sources.py b/tests/ahriman/core/build_tools/test_sources.py new file mode 100644 index 00000000..cad0716d --- /dev/null +++ b/tests/ahriman/core/build_tools/test_sources.py @@ -0,0 +1,107 @@ +import pytest + +from pathlib import Path +from pytest_mock import MockerFixture +from unittest import mock + +from ahriman.core.build_tools.sources import Sources + + +def test_fetch_existing(mocker: MockerFixture) -> None: + """ + must fetch new package via clone command + """ + mocker.patch("pathlib.Path.is_dir", return_value=True) + check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output") + + local = Path("local") + Sources.fetch(local, "remote", "master") + check_output_mock.assert_has_calls([ + mock.call("git", "fetch", "origin", "master", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)), + mock.call("git", "checkout", "--force", "master", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)), + mock.call("git", "reset", "--hard", "origin/master", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)) + ]) + + +def test_fetch_new(mocker: MockerFixture) -> None: + """ + must fetch new package via clone command + """ + mocker.patch("pathlib.Path.is_dir", return_value=False) + check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output") + + local = Path("local") + Sources.fetch(local, "remote", "master") + check_output_mock.assert_has_calls([ + mock.call("git", "clone", "remote", str(local), + exception=pytest.helpers.anyvar(int), + logger=pytest.helpers.anyvar(int)), + mock.call("git", "checkout", "--force", "master", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)), + mock.call("git", "reset", "--hard", "origin/master", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)) + ]) + + +def test_load(mocker: MockerFixture) -> None: + """ + must load packages sources correctly + """ + fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch") + patch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch") + + Sources.load(Path("local"), "remote", Path("patches")) + fetch_mock.assert_called_with(Path("local"), "remote") + patch_mock.assert_called_with(Path("local"), Path("patches")) + + +def test_patches(mocker: MockerFixture) -> None: + """ + must apply patches if any + """ + mocker.patch("pathlib.Path.is_dir", return_value=True) + glob_mock = mocker.patch("pathlib.Path.glob", return_value=[Path("01.patch"), Path("02.patch")]) + check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output") + + local = Path("local") + Sources.patch(local, Path("patches")) + glob_mock.assert_called_once() + check_output_mock.assert_has_calls([ + mock.call("git", "apply", "--ignore-space-change", "--ignore-whitespace", "01.patch", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)), + mock.call("git", "apply", "--ignore-space-change", "--ignore-whitespace", "02.patch", + exception=pytest.helpers.anyvar(int), + cwd=local, logger=pytest.helpers.anyvar(int)), + ]) + + +def test_patches_no_dir(mocker: MockerFixture) -> None: + """ + must not fail if no patches directory exists + """ + mocker.patch("pathlib.Path.is_dir", return_value=False) + glob_mock = mocker.patch("pathlib.Path.glob") + + Sources.patch(Path("local"), Path("patches")) + glob_mock.assert_not_called() + + +def test_patches_no_patches(mocker: MockerFixture) -> None: + """ + must not fail if no patches exist + """ + mocker.patch("pathlib.Path.is_dir", return_value=True) + mocker.patch("pathlib.Path.glob", return_value=[]) + check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output") + + Sources.patch(Path("local"), Path("patches")) + check_output_mock.assert_not_called() diff --git a/tests/ahriman/core/build_tools/test_task.py b/tests/ahriman/core/build_tools/test_task.py index 8dffd758..b6735d44 100644 --- a/tests/ahriman/core/build_tools/test_task.py +++ b/tests/ahriman/core/build_tools/test_task.py @@ -1,56 +1,8 @@ -import pytest - -from pathlib import Path from pytest_mock import MockerFixture -from unittest import mock from ahriman.core.build_tools.task import Task -def test_fetch_existing(mocker: MockerFixture) -> None: - """ - must fetch new package via clone command - """ - mocker.patch("pathlib.Path.is_dir", return_value=True) - check_output_mock = mocker.patch("ahriman.core.build_tools.task.Task._check_output") - - local = Path("local") - Task.fetch(local, "remote", "master") - check_output_mock.assert_has_calls([ - mock.call("git", "fetch", "origin", "master", - exception=pytest.helpers.anyvar(int), - cwd=local, logger=pytest.helpers.anyvar(int)), - mock.call("git", "checkout", "--force", "master", - exception=pytest.helpers.anyvar(int), - cwd=local, logger=pytest.helpers.anyvar(int)), - mock.call("git", "reset", "--hard", "origin/master", - exception=pytest.helpers.anyvar(int), - cwd=local, logger=pytest.helpers.anyvar(int)) - ]) - - -def test_fetch_new(mocker: MockerFixture) -> None: - """ - must fetch new package via clone command - """ - mocker.patch("pathlib.Path.is_dir", return_value=False) - check_output_mock = mocker.patch("ahriman.core.build_tools.task.Task._check_output") - - local = Path("local") - Task.fetch(local, "remote", "master") - check_output_mock.assert_has_calls([ - mock.call("git", "clone", "remote", str(local), - exception=pytest.helpers.anyvar(int), - logger=pytest.helpers.anyvar(int)), - mock.call("git", "checkout", "--force", "master", - exception=pytest.helpers.anyvar(int), - cwd=local, logger=pytest.helpers.anyvar(int)), - mock.call("git", "reset", "--hard", "origin/master", - exception=pytest.helpers.anyvar(int), - cwd=local, logger=pytest.helpers.anyvar(int)) - ]) - - def test_build(task_ahriman: Task, mocker: MockerFixture) -> None: """ must build package @@ -65,7 +17,7 @@ def test_init_with_cache(task_ahriman: Task, mocker: MockerFixture) -> None: must copy tree instead of fetch """ mocker.patch("pathlib.Path.is_dir", return_value=True) - mocker.patch("ahriman.core.build_tools.task.Task.fetch") + mocker.patch("ahriman.core.build_tools.sources.Sources.load") copytree_mock = mocker.patch("shutil.copytree") task_ahriman.init(None) diff --git a/tests/ahriman/core/test_tree.py b/tests/ahriman/core/test_tree.py index f6dc7069..bc890514 100644 --- a/tests/ahriman/core/test_tree.py +++ b/tests/ahriman/core/test_tree.py @@ -2,6 +2,7 @@ from pytest_mock import MockerFixture from ahriman.core.tree import Leaf, Tree from ahriman.models.package import Package +from ahriman.models.repository_paths import RepositoryPaths def test_leaf_is_root_empty(leaf_ahriman: Leaf) -> None: @@ -34,25 +35,25 @@ def test_leaf_is_root_true(leaf_ahriman: Leaf, leaf_python_schedule: Leaf) -> No assert not leaf_ahriman.is_root([leaf_python_schedule]) -def test_leaf_load(package_ahriman: Package, mocker: MockerFixture) -> None: +def test_leaf_load(package_ahriman: Package, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: """ must load with dependencies """ tempdir_mock = mocker.patch("tempfile.mkdtemp") - fetch_mock = mocker.patch("ahriman.core.build_tools.task.Task.fetch") + load_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.load") dependencies_mock = mocker.patch("ahriman.models.package.Package.dependencies", return_value={"ahriman-dependency"}) rmtree_mock = mocker.patch("shutil.rmtree") - leaf = Leaf.load(package_ahriman) + leaf = Leaf.load(package_ahriman, repository_paths) assert leaf.package == package_ahriman assert leaf.dependencies == {"ahriman-dependency"} tempdir_mock.assert_called_once() - fetch_mock.assert_called_once() + load_mock.assert_called_once() dependencies_mock.assert_called_once() rmtree_mock.assert_called_once() -def test_tree_levels(leaf_ahriman: Leaf, leaf_python_schedule: Leaf, mocker: MockerFixture) -> None: +def test_tree_levels(leaf_ahriman: Leaf, leaf_python_schedule: Leaf) -> None: """ must generate correct levels in the simples case """ @@ -65,14 +66,15 @@ def test_tree_levels(leaf_ahriman: Leaf, leaf_python_schedule: Leaf, mocker: Moc assert second == [leaf_ahriman.package] -def test_tree_load(package_ahriman: Package, package_python_schedule: Package, mocker: MockerFixture) -> None: +def test_tree_load(package_ahriman: Package, package_python_schedule: Package, + repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: """ must package list """ mocker.patch("tempfile.mkdtemp") - mocker.patch("ahriman.core.build_tools.task.Task.fetch") + mocker.patch("ahriman.core.build_tools.sources.Sources.load") mocker.patch("ahriman.models.package.Package.dependencies") mocker.patch("shutil.rmtree") - tree = Tree.load([package_ahriman, package_python_schedule]) + tree = Tree.load([package_ahriman, package_python_schedule], repository_paths) assert len(tree.leaves) == 2 diff --git a/tests/ahriman/models/test_package.py b/tests/ahriman/models/test_package.py index 44ef7006..c30cfb09 100644 --- a/tests/ahriman/models/test_package.py +++ b/tests/ahriman/models/test_package.py @@ -244,7 +244,7 @@ def test_actual_version_vcs(package_tpacpi_bat_git: Package, repository_paths: R """ srcinfo = (resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo").read_text() mocker.patch("ahriman.models.package.Package._check_output", return_value=srcinfo) - mocker.patch("ahriman.core.build_tools.task.Task.fetch") + mocker.patch("ahriman.core.build_tools.sources.Sources.load") assert package_tpacpi_bat_git.actual_version(repository_paths) == "3.1.r13.g4959b52-1" @@ -255,7 +255,7 @@ def test_actual_version_srcinfo_failed(package_tpacpi_bat_git: Package, reposito must return same version in case if exception occurred """ mocker.patch("ahriman.models.package.Package._check_output", side_effect=Exception()) - mocker.patch("ahriman.core.build_tools.task.Task.fetch") + mocker.patch("ahriman.core.build_tools.sources.Sources.load") assert package_tpacpi_bat_git.actual_version(repository_paths) == package_tpacpi_bat_git.version @@ -268,7 +268,7 @@ def test_actual_version_vcs_failed(package_tpacpi_bat_git: Package, repository_p mocker.patch("pathlib.Path.read_text", return_value="") mocker.patch("ahriman.models.package.parse_srcinfo", return_value=({"packages": {}}, ["an error"])) mocker.patch("ahriman.models.package.Package._check_output") - mocker.patch("ahriman.core.build_tools.task.Task.fetch") + mocker.patch("ahriman.core.build_tools.sources.Sources.load") assert package_tpacpi_bat_git.actual_version(repository_paths) == package_tpacpi_bat_git.version diff --git a/tests/ahriman/models/test_repository_paths.py b/tests/ahriman/models/test_repository_paths.py index cdac58c7..c91058fc 100644 --- a/tests/ahriman/models/test_repository_paths.py +++ b/tests/ahriman/models/test_repository_paths.py @@ -1,6 +1,7 @@ from pytest_mock import MockerFixture from unittest import mock +from ahriman.models.package import Package from ahriman.models.repository_paths import RepositoryPaths @@ -13,6 +14,15 @@ def test_known_architectures(repository_paths: RepositoryPaths, mocker: MockerFi iterdir_mock.assert_called_once() +def test_cache_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None: + """ + must return correct path for cache directory + """ + path = repository_paths.cache_for(package_ahriman.base) + assert path.name == package_ahriman.base + assert path.parent == repository_paths.cache + + def test_create_tree(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: """ must create whole tree @@ -20,7 +30,9 @@ def test_create_tree(repository_paths: RepositoryPaths, mocker: MockerFixture) - paths = { prop for prop in dir(repository_paths) - if not prop.startswith("_") and prop not in ("architecture", "create_tree", "known_architectures", "root") + if not prop.startswith("_") + and not prop.endswith("_for") + and prop not in ("architecture", "create_tree", "known_architectures", "root") } mkdir_mock = mocker.patch("pathlib.Path.mkdir") @@ -30,3 +42,30 @@ def test_create_tree(repository_paths: RepositoryPaths, mocker: MockerFixture) - mock.call(mode=0o755, parents=True, exist_ok=True) for _ in paths ]) + + +def test_manual_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None: + """ + must return correct path for manual directory + """ + path = repository_paths.manual_for(package_ahriman.base) + assert path.name == package_ahriman.base + assert path.parent == repository_paths.manual + + +def test_patches_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None: + """ + must return correct path for patches directory + """ + path = repository_paths.patches_for(package_ahriman.base) + assert path.name == package_ahriman.base + assert path.parent == repository_paths.patches + + +def test_sources_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None: + """ + must return correct path for sources directory + """ + path = repository_paths.sources_for(package_ahriman.base) + assert path.name == package_ahriman.base + assert path.parent == repository_paths.sources