From 8c01c1c6bc46851c75612520470f0e05e63bde0a Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Tue, 10 Feb 2026 12:47:01 +0200 Subject: [PATCH] smol refactoring of archive_tree class --- src/ahriman/core/archive/archive_tree.py | 52 ++++++++++++++----- .../ahriman/core/archive/test_archive_tree.py | 24 +++++++++ 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/src/ahriman/core/archive/archive_tree.py b/src/ahriman/core/archive/archive_tree.py index 09fd17c8..23b1a121 100644 --- a/src/ahriman/core/archive/archive_tree.py +++ b/src/ahriman/core/archive/archive_tree.py @@ -25,6 +25,7 @@ from ahriman.core.alpm.repo import Repo from ahriman.core.log import LazyLogging from ahriman.core.utils import symlink_relative, utcnow, walk from ahriman.models.package import Package +from ahriman.models.package_description import PackageDescription from ahriman.models.repository_paths import RepositoryPaths @@ -48,6 +49,40 @@ class ArchiveTree(LazyLogging): self.repository_id = repository_path.repository_id self.sign_args = sign_args + def _package_symlinks_create(self, package_description: PackageDescription, root: Path, archive: Path) -> bool: + """ + process symlinks creation for single package + + Args: + package_description(PackageDescription): archive descriptor + root(Path): path to the archive repository root + archive(Path): path to directory with archives + + Returns: + bool: ``True`` if symlinks were created and ``False`` otherwise + """ + symlinks_created = False + # here we glob for archive itself and signature if any + for file in archive.glob(f"{package_description.filename}*"): + try: + symlink_relative(root / file.name, file) + symlinks_created = True + except FileExistsError: + continue # symlink is already created, skip processing + + return symlinks_created + + def _repo(self, root: Path) -> Repo: + """ + constructs :class:`ahriman.core.alpm.repo.Repo` object for given path + Args: + root(Path): root of the repository + + Returns: + Repo: constructed object with correct properties + """ + return Repo(self.repository_id.name, self.paths, self.sign_args, root) + def repository_for(self, date: datetime.date | None = None) -> Path: """ get full path to repository at the specified date @@ -78,7 +113,7 @@ class ArchiveTree(LazyLogging): packages(list[Package]): list of packages to be updated """ root = self.repository_for() - repo = Repo(self.repository_id.name, self.paths, self.sign_args, root) + repo = self._repo(root) for package in packages: archive = self.paths.archive_for(package.base) @@ -88,16 +123,7 @@ class ArchiveTree(LazyLogging): self.logger.warning("received empty package filename for %s", package_name) continue - has_file = False - for file in archive.glob(f"{single.filename}*"): - symlink = root / file.name - try: - symlink_relative(symlink, file) - has_file = True - except FileExistsError: - continue # symlink is already created, skip processing - - if has_file: + if self._package_symlinks_create(single, root, archive): repo.add(root / single.filename) def symlinks_fix(self) -> None: @@ -115,7 +141,7 @@ class ArchiveTree(LazyLogging): if path.exists(): continue # filter out not broken symlinks - Repo(self.repository_id.name, self.paths, self.sign_args, root).remove(None, path) + self._repo(root).remove(None, path) def tree_create(self) -> None: """ @@ -128,4 +154,4 @@ class ArchiveTree(LazyLogging): with self.paths.preserve_owner(): root.mkdir(0o755, parents=True) # init empty repository here - Repo(self.repository_id.name, self.paths, self.sign_args, root).init() + self._repo(root).init() diff --git a/tests/ahriman/core/archive/test_archive_tree.py b/tests/ahriman/core/archive/test_archive_tree.py index 28e4bbb3..c95c816c 100644 --- a/tests/ahriman/core/archive/test_archive_tree.py +++ b/tests/ahriman/core/archive/test_archive_tree.py @@ -7,6 +7,30 @@ from ahriman.core.utils import utcnow from ahriman.models.package import Package +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_repo(archive_tree: ArchiveTree) -> None: + """ + must return correct repository object + """ + local = Path("local") + repo = archive_tree._repo(local) + + assert repo.sign_args == archive_tree.sign_args + assert repo.name == archive_tree.repository_id.name + assert repo.root == local + + def test_repository_for(archive_tree: ArchiveTree) -> None: """ must correctly generate path to repository