mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-11-13 20:13:42 +00:00
Compare commits
11 Commits
e6df656ce3
...
feature/tr
| Author | SHA1 | Date | |
|---|---|---|---|
| f12786a0c6 | |||
| b6309caa32 | |||
| f3fef1daf5 | |||
| 0aaf096d73 | |||
| a1b6041ca8 | |||
| a36de5c4b9 | |||
| 1bcdce4e6e | |||
| 2983d7e61a | |||
| 43fb950a0a | |||
| a28589ec74 | |||
| dfab5f56b2 |
29
docs/ahriman.core.archive.rst
Normal file
29
docs/ahriman.core.archive.rst
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
ahriman.core.archive package
|
||||||
|
============================
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
|
||||||
|
ahriman.core.archive.archive\_tree module
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.archive.archive_tree
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.core.archive.archive\_trigger module
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.archive.archive_trigger
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.archive
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
@ -8,6 +8,7 @@ Subpackages
|
|||||||
:maxdepth: 4
|
:maxdepth: 4
|
||||||
|
|
||||||
ahriman.core.alpm
|
ahriman.core.alpm
|
||||||
|
ahriman.core.archive
|
||||||
ahriman.core.auth
|
ahriman.core.auth
|
||||||
ahriman.core.build_tools
|
ahriman.core.build_tools
|
||||||
ahriman.core.configuration
|
ahriman.core.configuration
|
||||||
|
|||||||
@ -23,7 +23,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from ahriman.core.alpm.repo import Repo
|
from ahriman.core.alpm.repo import Repo
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.utils import utcnow
|
from ahriman.core.utils import utcnow, walk
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
@ -54,11 +54,12 @@ class ArchiveTree(LazyLogging):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
date(datetime.date | None, optional): date to generate path. If none supplied then today will be used
|
date(datetime.date | None, optional): date to generate path. If none supplied then today will be used
|
||||||
|
(Default value = None)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path: path to the repository root
|
Path: path to the repository root
|
||||||
"""
|
"""
|
||||||
date = date or utcnow().today()
|
date = date or utcnow().date()
|
||||||
return (
|
return (
|
||||||
self.paths.archive
|
self.paths.archive
|
||||||
/ "repos"
|
/ "repos"
|
||||||
@ -89,39 +90,41 @@ class ArchiveTree(LazyLogging):
|
|||||||
|
|
||||||
has_file = False
|
has_file = False
|
||||||
for file in archive.glob(f"{single.filename}*"):
|
for file in archive.glob(f"{single.filename}*"):
|
||||||
if not (symlink := root / file.name).exists():
|
symlink = root / file.name
|
||||||
has_file |= True
|
if symlink.exists():
|
||||||
symlink.symlink_to(file.relative_to(symlink.parent, walk_up=True))
|
continue # symlink is already created, skip processing
|
||||||
|
has_file = True
|
||||||
|
symlink.symlink_to(file.relative_to(symlink.parent, walk_up=True))
|
||||||
|
|
||||||
if has_file:
|
if has_file:
|
||||||
repo.add(root / single.filename)
|
repo.add(root / single.filename)
|
||||||
|
|
||||||
def symlinks_fix(self) -> None:
|
def symlinks_fix(self) -> None:
|
||||||
"""
|
"""
|
||||||
remove broken symlinks across all repositories
|
remove broken symlinks across repositories for all dates
|
||||||
"""
|
"""
|
||||||
for root, _, files in self.paths.archive.walk():
|
for path in walk(self.paths.archive / "repos"):
|
||||||
|
root = path.parent
|
||||||
*_, name, architecture = root.parts
|
*_, name, architecture = root.parts
|
||||||
if self.repository_id.name != name or self.repository_id.architecture != architecture:
|
if self.repository_id.name != name or self.repository_id.architecture != architecture:
|
||||||
continue # we only process same name repositories
|
continue # we only process same name repositories
|
||||||
|
|
||||||
for file in files:
|
if not path.is_symlink():
|
||||||
path = root / file
|
continue # find symlinks only
|
||||||
if not path.is_symlink():
|
if path.exists():
|
||||||
continue # find symlinks only
|
continue # filter out not broken symlinks
|
||||||
if path.exists():
|
|
||||||
continue # filter out not broken symlinks
|
|
||||||
|
|
||||||
repo = Repo(self.repository_id.name, self.paths, self.sign_args, root)
|
Repo(self.repository_id.name, self.paths, self.sign_args, root).remove(None, path)
|
||||||
repo.remove(None, path)
|
|
||||||
|
|
||||||
def tree_create(self) -> None:
|
def tree_create(self) -> None:
|
||||||
"""
|
"""
|
||||||
create repository tree for current repository
|
create repository tree for current repository
|
||||||
"""
|
"""
|
||||||
path = self.repository_for()
|
root = self.repository_for()
|
||||||
if path.exists():
|
if root.exists():
|
||||||
return
|
return
|
||||||
|
|
||||||
with self.paths.preserve_owner(self.paths.archive):
|
with self.paths.preserve_owner(self.paths.archive):
|
||||||
path.mkdir(0o755, parents=True)
|
root.mkdir(0o755, parents=True)
|
||||||
|
# init empty repository here
|
||||||
|
Repo(self.repository_id.name, self.paths, self.sign_args, root).init()
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from ahriman.core import context
|
|
||||||
from ahriman.core.archive.archive_tree import ArchiveTree
|
from ahriman.core.archive.archive_tree import ArchiveTree
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
@ -33,6 +32,7 @@ class ArchiveTrigger(Trigger):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
|
tree(ArchiveTree): archive tree wrapper
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
@ -44,9 +44,7 @@ class ArchiveTrigger(Trigger):
|
|||||||
Trigger.__init__(self, repository_id, configuration)
|
Trigger.__init__(self, repository_id, configuration)
|
||||||
|
|
||||||
self.paths = configuration.repository_paths
|
self.paths = configuration.repository_paths
|
||||||
|
self.tree = ArchiveTree(self.paths, GPG(configuration).repository_sign_args)
|
||||||
ctx = context.get()
|
|
||||||
self.tree = ArchiveTree(self.paths, ctx.get(GPG).repository_sign_args)
|
|
||||||
|
|
||||||
def on_result(self, result: Result, packages: list[Package]) -> None:
|
def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -36,6 +36,7 @@ class Trigger(LazyLogging):
|
|||||||
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
||||||
CONFIGURATION_SCHEMA_FALLBACK(str | None): (class attribute) optional fallback option for defining
|
CONFIGURATION_SCHEMA_FALLBACK(str | None): (class attribute) optional fallback option for defining
|
||||||
configuration schema type used
|
configuration schema type used
|
||||||
|
REQUIRES_REPOSITORY(bool): (class attribute) either trigger requires loaded repository or not
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
repository_id(RepositoryId): repository unique identifier
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
@ -59,6 +60,7 @@ class Trigger(LazyLogging):
|
|||||||
|
|
||||||
CONFIGURATION_SCHEMA: ClassVar[ConfigurationSchema] = {}
|
CONFIGURATION_SCHEMA: ClassVar[ConfigurationSchema] = {}
|
||||||
CONFIGURATION_SCHEMA_FALLBACK: ClassVar[str | None] = None
|
CONFIGURATION_SCHEMA_FALLBACK: ClassVar[str | None] = None
|
||||||
|
REQUIRES_REPOSITORY: ClassVar[bool] = True
|
||||||
|
|
||||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
@ -79,6 +81,16 @@ class Trigger(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
return self.repository_id.architecture
|
return self.repository_id.architecture
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_allowed_to_run(self) -> bool:
|
||||||
|
"""
|
||||||
|
whether trigger allowed to run or not
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: ``True`` in case if trigger allowed to run and ``False`` otherwise
|
||||||
|
"""
|
||||||
|
return not (self.REQUIRES_REPOSITORY and self.repository_id.is_empty)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def configuration_schema(cls, configuration: Configuration | None) -> ConfigurationSchema:
|
def configuration_schema(cls, configuration: Configuration | None) -> ConfigurationSchema:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -77,8 +77,9 @@ class TriggerLoader(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
instance = cls()
|
instance = cls()
|
||||||
instance.triggers = [
|
instance.triggers = [
|
||||||
instance.load_trigger(trigger, repository_id, configuration)
|
trigger
|
||||||
for trigger in instance.selected_triggers(configuration)
|
for trigger_name in instance.selected_triggers(configuration)
|
||||||
|
if (trigger := instance.load_trigger(trigger_name, repository_id, configuration)).is_allowed_to_run
|
||||||
]
|
]
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from pathlib import Path
|
|||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from ahriman.core.alpm.repo import Repo
|
from ahriman.core.alpm.repo import Repo
|
||||||
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
@ -56,21 +57,37 @@ def test_repo_init(repo: Repo, mocker: MockerFixture) -> None:
|
|||||||
assert check_output_mock.call_args[0][0] == "repo-add"
|
assert check_output_mock.call_args[0][0] == "repo-add"
|
||||||
|
|
||||||
|
|
||||||
def test_repo_remove(repo: Repo, mocker: MockerFixture) -> None:
|
def test_repo_remove(repo: Repo, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must call repo-remove on package addition
|
must call repo-remove on package removal
|
||||||
"""
|
"""
|
||||||
|
filepath = package_ahriman.packages[package_ahriman.base].filepath
|
||||||
mocker.patch("pathlib.Path.glob", return_value=[])
|
mocker.patch("pathlib.Path.glob", return_value=[])
|
||||||
check_output_mock = mocker.patch("ahriman.core.alpm.repo.check_output")
|
check_output_mock = mocker.patch("ahriman.core.alpm.repo.check_output")
|
||||||
|
|
||||||
repo.remove("package", Path("package.pkg.tar.xz"))
|
repo.remove(package_ahriman.base, filepath)
|
||||||
check_output_mock.assert_called_once() # it will be checked later
|
check_output_mock.assert_called_once() # it will be checked later
|
||||||
assert check_output_mock.call_args[0][0] == "repo-remove"
|
assert check_output_mock.call_args[0][0] == "repo-remove"
|
||||||
|
assert package_ahriman.base in check_output_mock.call_args[0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_repo_remove_guess_package(repo: Repo, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call repo-remove on package removal if no package name set
|
||||||
|
"""
|
||||||
|
filepath = package_ahriman.packages[package_ahriman.base].filepath
|
||||||
|
mocker.patch("pathlib.Path.glob", return_value=[])
|
||||||
|
check_output_mock = mocker.patch("ahriman.core.alpm.repo.check_output")
|
||||||
|
|
||||||
|
repo.remove(None, filepath)
|
||||||
|
check_output_mock.assert_called_once() # it will be checked later
|
||||||
|
assert check_output_mock.call_args[0][0] == "repo-remove"
|
||||||
|
assert package_ahriman.base in check_output_mock.call_args[0]
|
||||||
|
|
||||||
|
|
||||||
def test_repo_remove_fail_no_file(repo: Repo, mocker: MockerFixture) -> None:
|
def test_repo_remove_fail_no_file(repo: Repo, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must fail on missing file
|
must fail removal on missing file
|
||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.glob", return_value=[Path("package.pkg.tar.xz")])
|
mocker.patch("pathlib.Path.glob", return_value=[Path("package.pkg.tar.xz")])
|
||||||
mocker.patch("pathlib.Path.unlink", side_effect=FileNotFoundError)
|
mocker.patch("pathlib.Path.unlink", side_effect=FileNotFoundError)
|
||||||
|
|||||||
34
tests/ahriman/core/archive/conftest.py
Normal file
34
tests/ahriman/core/archive/conftest.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ahriman.core.archive import ArchiveTrigger
|
||||||
|
from ahriman.core.archive.archive_tree import ArchiveTree
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def archive_tree(configuration: Configuration) -> ArchiveTree:
|
||||||
|
"""
|
||||||
|
archive tree fixture
|
||||||
|
|
||||||
|
Args:
|
||||||
|
configuration(Configuration): configuration fixture
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ArchiveTree: archive tree test instance
|
||||||
|
"""
|
||||||
|
return ArchiveTree(configuration.repository_paths, [])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def archive_trigger(configuration: Configuration) -> ArchiveTrigger:
|
||||||
|
"""
|
||||||
|
archive trigger fixture
|
||||||
|
|
||||||
|
Args:
|
||||||
|
configuration(Configuration): configuration fixture
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ArchiveTrigger: archive trigger test instance
|
||||||
|
"""
|
||||||
|
_, repository_id = configuration.check_loaded()
|
||||||
|
return ArchiveTrigger(repository_id, configuration)
|
||||||
135
tests/ahriman/core/archive/test_archive_tree.py
Normal file
135
tests/ahriman/core/archive/test_archive_tree.py
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from ahriman.core.archive.archive_tree import ArchiveTree
|
||||||
|
from ahriman.core.utils import utcnow
|
||||||
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
|
def test_repository_for(archive_tree: ArchiveTree) -> None:
|
||||||
|
"""
|
||||||
|
must correctly generate path to repository
|
||||||
|
"""
|
||||||
|
path = archive_tree.repository_for()
|
||||||
|
assert path.is_relative_to(archive_tree.paths.archive / "repos")
|
||||||
|
assert (archive_tree.repository_id.name, archive_tree.repository_id.architecture) == path.parts[-2:]
|
||||||
|
assert set(map("{:02d}".format, utcnow().timetuple()[:3])).issubset(path.parts)
|
||||||
|
|
||||||
|
|
||||||
|
def test_symlinks_create(archive_tree: ArchiveTree, package_ahriman: Package, package_python_schedule: Package,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create symlinks
|
||||||
|
"""
|
||||||
|
_original_exists = Path.exists
|
||||||
|
|
||||||
|
def exists_mock(path: Path) -> bool:
|
||||||
|
if path.name in (package.filename for package in package_python_schedule.packages.values()):
|
||||||
|
return True
|
||||||
|
return _original_exists(path)
|
||||||
|
|
||||||
|
symlinks_mock = mocker.patch("pathlib.Path.symlink_to")
|
||||||
|
add_mock = mocker.patch("ahriman.core.alpm.repo.Repo.add")
|
||||||
|
mocker.patch("pathlib.Path.glob", autospec=True, side_effect=lambda path, name: [path / name[:-1]])
|
||||||
|
mocker.patch("pathlib.Path.exists", autospec=True, side_effect=exists_mock)
|
||||||
|
|
||||||
|
archive_tree.symlinks_create([package_ahriman, package_python_schedule])
|
||||||
|
symlinks_mock.assert_called_once_with(
|
||||||
|
Path("..") /
|
||||||
|
".." /
|
||||||
|
".." /
|
||||||
|
".." /
|
||||||
|
".." /
|
||||||
|
".." /
|
||||||
|
archive_tree.paths.archive_for(package_ahriman.base)
|
||||||
|
.relative_to(archive_tree.paths.root)
|
||||||
|
.relative_to("archive") /
|
||||||
|
package_ahriman.packages[package_ahriman.base].filename
|
||||||
|
)
|
||||||
|
add_mock.assert_called_once_with(
|
||||||
|
archive_tree.repository_for() / package_ahriman.packages[package_ahriman.base].filename
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_symlinks_create_empty_filename(archive_tree: ArchiveTree, package_ahriman: Package,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must skip symlinks creation if filename is not set
|
||||||
|
"""
|
||||||
|
package_ahriman.packages[package_ahriman.base].filename = None
|
||||||
|
symlinks_mock = mocker.patch("pathlib.Path.symlink_to")
|
||||||
|
|
||||||
|
archive_tree.symlinks_create([package_ahriman])
|
||||||
|
symlinks_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_symlinks_fix(archive_tree: ArchiveTree, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must fix broken symlinks
|
||||||
|
"""
|
||||||
|
_original_exists = Path.exists
|
||||||
|
|
||||||
|
def exists_mock(path: Path) -> bool:
|
||||||
|
if path.name == "symlink":
|
||||||
|
return True
|
||||||
|
return _original_exists(path)
|
||||||
|
|
||||||
|
mocker.patch("pathlib.Path.is_symlink", side_effect=[True, True, False])
|
||||||
|
mocker.patch("pathlib.Path.exists", autospec=True, side_effect=exists_mock)
|
||||||
|
walk_mock = mocker.patch("ahriman.core.archive.archive_tree.walk", return_value=[
|
||||||
|
archive_tree.repository_for() / filename
|
||||||
|
for filename in ("symlink", "broken_symlink", "file")
|
||||||
|
])
|
||||||
|
remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
||||||
|
|
||||||
|
archive_tree.symlinks_fix()
|
||||||
|
walk_mock.assert_called_once_with(archive_tree.paths.archive / "repos")
|
||||||
|
remove_mock.assert_called_once_with(None, archive_tree.repository_for() / "broken_symlink")
|
||||||
|
|
||||||
|
|
||||||
|
def test_symlinks_fix_foreign_repository(archive_tree: ArchiveTree, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must skip symlinks check if repository name or architecture doesn't match
|
||||||
|
"""
|
||||||
|
_original_exists = Path.exists
|
||||||
|
|
||||||
|
def exists_mock(path: Path) -> bool:
|
||||||
|
if path.name == "symlink":
|
||||||
|
return True
|
||||||
|
return _original_exists(path)
|
||||||
|
|
||||||
|
mocker.patch("pathlib.Path.is_symlink", side_effect=[True, True, False])
|
||||||
|
mocker.patch("pathlib.Path.exists", autospec=True, side_effect=exists_mock)
|
||||||
|
mocker.patch("ahriman.core.archive.archive_tree.walk", return_value=[
|
||||||
|
archive_tree.repository_for().with_name("i686") / filename
|
||||||
|
for filename in ("symlink", "broken_symlink", "file")
|
||||||
|
])
|
||||||
|
remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
||||||
|
|
||||||
|
archive_tree.symlinks_fix()
|
||||||
|
remove_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_tree_create(archive_tree: ArchiveTree, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create repository root if not exists
|
||||||
|
"""
|
||||||
|
owner_guard_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
|
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
||||||
|
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
|
||||||
|
|
||||||
|
archive_tree.tree_create()
|
||||||
|
owner_guard_mock.assert_called_once_with(archive_tree.paths.archive)
|
||||||
|
mkdir_mock.assert_called_once_with(0o755, parents=True)
|
||||||
|
init_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
def test_tree_create_exists(archive_tree: ArchiveTree, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must skip directory creation if already exists
|
||||||
|
"""
|
||||||
|
mocker.patch("pathlib.Path.exists", return_value=True)
|
||||||
|
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
||||||
|
|
||||||
|
archive_tree.tree_create()
|
||||||
|
mkdir_mock.assert_not_called()
|
||||||
32
tests/ahriman/core/archive/test_archive_trigger.py
Normal file
32
tests/ahriman/core/archive/test_archive_trigger.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from ahriman.core.archive import ArchiveTrigger
|
||||||
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_result(archive_trigger: ArchiveTrigger, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create symlinks for actual repository
|
||||||
|
"""
|
||||||
|
symlinks_mock = mocker.patch("ahriman.core.archive.archive_tree.ArchiveTree.symlinks_create")
|
||||||
|
archive_trigger.on_result(Result(), [package_ahriman])
|
||||||
|
symlinks_mock.assert_called_once_with([package_ahriman])
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_start(archive_trigger: ArchiveTrigger, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create repository tree on load
|
||||||
|
"""
|
||||||
|
tree_mock = mocker.patch("ahriman.core.archive.archive_tree.ArchiveTree.tree_create")
|
||||||
|
archive_trigger.on_start()
|
||||||
|
tree_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_stop(archive_trigger: ArchiveTrigger, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create repository tree on load
|
||||||
|
"""
|
||||||
|
symlinks_mock = mocker.patch("ahriman.core.archive.archive_tree.ArchiveTree.symlinks_fix")
|
||||||
|
archive_trigger.on_stop()
|
||||||
|
symlinks_mock.assert_called_once_with()
|
||||||
@ -186,9 +186,7 @@ def test_package_update(executor: Executor, package_ahriman: Package, user: User
|
|||||||
Path("..") /
|
Path("..") /
|
||||||
".." /
|
".." /
|
||||||
".." /
|
".." /
|
||||||
executor.paths.archive_for(
|
executor.paths.archive_for(package_ahriman.base).relative_to(executor.paths.root) /
|
||||||
package_ahriman.base).relative_to(
|
|
||||||
executor.paths.root) /
|
|
||||||
filepath)
|
filepath)
|
||||||
# must add package
|
# must add package
|
||||||
repo_add_mock.assert_called_once_with(executor.paths.repository / filepath)
|
repo_add_mock.assert_called_once_with(executor.paths.repository / filepath)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ from unittest.mock import MagicMock
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.report import ReportTrigger
|
from ahriman.core.report import ReportTrigger
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
@ -13,6 +14,19 @@ def test_architecture(trigger: Trigger) -> None:
|
|||||||
assert trigger.architecture == trigger.repository_id.architecture
|
assert trigger.architecture == trigger.repository_id.architecture
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_allowed_to_run(trigger: Trigger) -> None:
|
||||||
|
"""
|
||||||
|
must return flag correctly
|
||||||
|
"""
|
||||||
|
assert trigger.is_allowed_to_run
|
||||||
|
|
||||||
|
trigger.repository_id = RepositoryId("", "")
|
||||||
|
assert not trigger.is_allowed_to_run
|
||||||
|
|
||||||
|
trigger.REQUIRES_REPOSITORY = False
|
||||||
|
assert trigger.is_allowed_to_run
|
||||||
|
|
||||||
|
|
||||||
def test_configuration_schema(configuration: Configuration) -> None:
|
def test_configuration_schema(configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
must return used configuration schema
|
must return used configuration schema
|
||||||
|
|||||||
Reference in New Issue
Block a user