mirror of
https://github.com/arcan1s/ahriman.git
synced 2026-03-12 13:03:39 +00:00
refactor: lightweight Package.from_archive method
This commit is contained in:
@@ -28,6 +28,14 @@ ahriman.core.alpm.pacman\_database module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.core.alpm.pacman\_handle module
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.alpm.pacman_handle
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.core.alpm.pkgbuild\_parser module
|
ahriman.core.alpm.pkgbuild\_parser module
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ import tarfile
|
|||||||
from collections.abc import Iterable, Iterator
|
from collections.abc import Iterable, Iterator
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pyalpm import DB, Handle, Package, SIG_DATABASE_OPTIONAL, SIG_PACKAGE_OPTIONAL # type: ignore[import-not-found]
|
from pyalpm import DB, Package, SIG_DATABASE_OPTIONAL, SIG_PACKAGE_OPTIONAL # type: ignore[import-not-found]
|
||||||
from string import Template
|
from string import Template
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman_database import PacmanDatabase
|
from ahriman.core.alpm.pacman_database import PacmanDatabase
|
||||||
|
from ahriman.core.alpm.pacman_handle import PacmanHandle
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.utils import trim_package
|
from ahriman.core.utils import trim_package
|
||||||
@@ -61,16 +62,16 @@ class Pacman(LazyLogging):
|
|||||||
self.refresh_database = refresh_database
|
self.refresh_database = refresh_database
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def handle(self) -> Handle:
|
def handle(self) -> PacmanHandle:
|
||||||
"""
|
"""
|
||||||
pyalpm handle
|
pyalpm handle
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Handle: generated pyalpm handle instance
|
PacmanHandle: generated pyalpm handle instance
|
||||||
"""
|
"""
|
||||||
return self.__create_handle(refresh_database=self.refresh_database)
|
return self.__create_handle(refresh_database=self.refresh_database)
|
||||||
|
|
||||||
def __create_handle(self, *, refresh_database: PacmanSynchronization) -> Handle:
|
def __create_handle(self, *, refresh_database: PacmanSynchronization) -> PacmanHandle:
|
||||||
"""
|
"""
|
||||||
create lazy handle function
|
create lazy handle function
|
||||||
|
|
||||||
@@ -78,14 +79,14 @@ class Pacman(LazyLogging):
|
|||||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Handle: fully initialized pacman handle
|
PacmanHandle: fully initialized pacman handle
|
||||||
"""
|
"""
|
||||||
pacman_root = self.configuration.getpath("alpm", "database")
|
pacman_root = self.configuration.getpath("alpm", "database")
|
||||||
use_ahriman_cache = self.configuration.getboolean("alpm", "use_ahriman_cache")
|
use_ahriman_cache = self.configuration.getboolean("alpm", "use_ahriman_cache")
|
||||||
|
|
||||||
database_path = self.repository_paths.pacman if use_ahriman_cache else pacman_root
|
database_path = self.repository_paths.pacman if use_ahriman_cache else pacman_root
|
||||||
root = self.configuration.getpath("alpm", "root")
|
root = self.configuration.getpath("alpm", "root")
|
||||||
handle = Handle(str(root), str(database_path))
|
handle = PacmanHandle(str(root), str(database_path))
|
||||||
|
|
||||||
for repository in self.configuration.getlist("alpm", "repositories"):
|
for repository in self.configuration.getlist("alpm", "repositories"):
|
||||||
database = self.database_init(handle, repository, self.repository_id.architecture)
|
database = self.database_init(handle, repository, self.repository_id.architecture)
|
||||||
@@ -99,12 +100,12 @@ class Pacman(LazyLogging):
|
|||||||
|
|
||||||
return handle
|
return handle
|
||||||
|
|
||||||
def database_copy(self, handle: Handle, database: DB, pacman_root: Path, *, use_ahriman_cache: bool) -> None:
|
def database_copy(self, handle: PacmanHandle, database: DB, pacman_root: Path, *, use_ahriman_cache: bool) -> None:
|
||||||
"""
|
"""
|
||||||
copy database from the operating system root to the ahriman local home
|
copy database from the operating system root to the ahriman local home
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
handle(Handle): pacman handle which will be used for database copying
|
handle(PacmanHandle): pacman handle which will be used for database copying
|
||||||
database(DB): pacman database instance to be copied
|
database(DB): pacman database instance to be copied
|
||||||
pacman_root(Path): operating system pacman root
|
pacman_root(Path): operating system pacman root
|
||||||
use_ahriman_cache(bool): use local ahriman cache instead of system one
|
use_ahriman_cache(bool): use local ahriman cache instead of system one
|
||||||
@@ -133,12 +134,12 @@ class Pacman(LazyLogging):
|
|||||||
with self.repository_paths.preserve_owner():
|
with self.repository_paths.preserve_owner():
|
||||||
shutil.copy(src, dst)
|
shutil.copy(src, dst)
|
||||||
|
|
||||||
def database_init(self, handle: Handle, repository: str, architecture: str) -> DB:
|
def database_init(self, handle: PacmanHandle, repository: str, architecture: str) -> DB:
|
||||||
"""
|
"""
|
||||||
create database instance from pacman handler and set its properties
|
create database instance from pacman handler and set its properties
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
handle(Handle): pacman handle which will be used for database initializing
|
handle(PacmanHandle): pacman handle which will be used for database initializing
|
||||||
repository(str): pacman repository name (e.g. core)
|
repository(str): pacman repository name (e.g. core)
|
||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
|
|
||||||
@@ -164,12 +165,12 @@ class Pacman(LazyLogging):
|
|||||||
|
|
||||||
return database
|
return database
|
||||||
|
|
||||||
def database_sync(self, handle: Handle, *, force: bool) -> None:
|
def database_sync(self, handle: PacmanHandle, *, force: bool) -> None:
|
||||||
"""
|
"""
|
||||||
sync local database
|
sync local database
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
handle(Handle): pacman handle which will be used for database sync
|
handle(PacmanHandle): pacman handle which will be used for database sync
|
||||||
force(bool): force database synchronization (same as ``pacman -Syy``)
|
force(bool): force database synchronization (same as ``pacman -Syy``)
|
||||||
"""
|
"""
|
||||||
self.logger.info("refresh ahriman's home pacman database (force refresh %s)", force)
|
self.logger.info("refresh ahriman's home pacman database (force refresh %s)", force)
|
||||||
|
|||||||
81
src/ahriman/core/alpm/pacman_handle.py
Normal file
81
src/ahriman/core/alpm/pacman_handle.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2026 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 <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from pathlib import Path
|
||||||
|
from pyalpm import Handle, Package # type: ignore[import-not-found]
|
||||||
|
from tempfile import TemporaryDirectory
|
||||||
|
from typing import Any, ClassVar, Self
|
||||||
|
|
||||||
|
|
||||||
|
class PacmanHandle:
|
||||||
|
"""
|
||||||
|
lightweight wrapper for pacman handle to be used for direct alpm operations (e.g. package load)
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
handle(Handle): pyalpm handle instance
|
||||||
|
"""
|
||||||
|
|
||||||
|
_ephemeral: ClassVar[Self | None] = None
|
||||||
|
|
||||||
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
*args(Any): positional arguments for :class:`pyalpm.Handle`
|
||||||
|
**kwargs(Any): keyword arguments for :class:`pyalpm.Handle`
|
||||||
|
"""
|
||||||
|
self.handle = Handle(*args, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def ephemeral(cls) -> Self:
|
||||||
|
"""
|
||||||
|
create temporary instance with no access to real databases
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Self: loaded class
|
||||||
|
"""
|
||||||
|
if cls._ephemeral is None:
|
||||||
|
# handle creates alpm version file, but we don't use it
|
||||||
|
# so it is ok to just remove it
|
||||||
|
with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name:
|
||||||
|
cls._ephemeral = cls("/", dir_name)
|
||||||
|
return cls._ephemeral
|
||||||
|
|
||||||
|
def package_load(self, path: Path) -> Package:
|
||||||
|
"""
|
||||||
|
load package from path to the archive
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path(Path): path to package archive
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Package: package instance
|
||||||
|
"""
|
||||||
|
return self.handle.load_pkg(str(path))
|
||||||
|
|
||||||
|
def __getattr__(self, item: str) -> Any:
|
||||||
|
"""
|
||||||
|
proxy methods for :class:`pyalpm.Handle`, because it doesn't allow subclassing
|
||||||
|
|
||||||
|
Args:
|
||||||
|
item(str): property name
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Any: attribute by its name
|
||||||
|
"""
|
||||||
|
return self.handle.__getattribute__(item)
|
||||||
@@ -19,11 +19,9 @@
|
|||||||
#
|
#
|
||||||
from sqlite3 import Connection
|
from sqlite3 import Connection
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.utils import package_like
|
from ahriman.core.utils import package_like
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["migrate_data", "steps"]
|
__all__ = ["migrate_data", "steps"]
|
||||||
@@ -61,12 +59,9 @@ def migrate_package_depends(connection: Connection, configuration: Configuration
|
|||||||
if not configuration.repository_paths.repository.is_dir():
|
if not configuration.repository_paths.repository.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
_, repository_id = configuration.check_loaded()
|
|
||||||
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
|
||||||
|
|
||||||
package_list = []
|
package_list = []
|
||||||
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
||||||
base = Package.from_archive(full_path, pacman)
|
base = Package.from_archive(full_path)
|
||||||
for package, description in base.packages.items():
|
for package, description in base.packages.items():
|
||||||
package_list.append({
|
package_list.append({
|
||||||
"make_depends": description.make_depends,
|
"make_depends": description.make_depends,
|
||||||
|
|||||||
@@ -19,11 +19,9 @@
|
|||||||
#
|
#
|
||||||
from sqlite3 import Connection
|
from sqlite3 import Connection
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.utils import package_like
|
from ahriman.core.utils import package_like
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["migrate_data", "steps"]
|
__all__ = ["migrate_data", "steps"]
|
||||||
@@ -58,12 +56,9 @@ def migrate_package_check_depends(connection: Connection, configuration: Configu
|
|||||||
if not configuration.repository_paths.repository.is_dir():
|
if not configuration.repository_paths.repository.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
_, repository_id = configuration.check_loaded()
|
|
||||||
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
|
||||||
|
|
||||||
package_list = []
|
package_list = []
|
||||||
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
||||||
base = Package.from_archive(full_path, pacman)
|
base = Package.from_archive(full_path)
|
||||||
for package, description in base.packages.items():
|
for package, description in base.packages.items():
|
||||||
package_list.append({
|
package_list.append({
|
||||||
"check_depends": description.check_depends,
|
"check_depends": description.check_depends,
|
||||||
|
|||||||
@@ -19,11 +19,9 @@
|
|||||||
#
|
#
|
||||||
from sqlite3 import Connection
|
from sqlite3 import Connection
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.utils import package_like
|
from ahriman.core.utils import package_like
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["migrate_data", "steps"]
|
__all__ = ["migrate_data", "steps"]
|
||||||
@@ -64,12 +62,9 @@ def migrate_package_base_packager(connection: Connection, configuration: Configu
|
|||||||
if not configuration.repository_paths.repository.is_dir():
|
if not configuration.repository_paths.repository.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
_, repository_id = configuration.check_loaded()
|
|
||||||
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
|
||||||
|
|
||||||
package_list = []
|
package_list = []
|
||||||
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
for full_path in filter(package_like, configuration.repository_paths.repository.iterdir()):
|
||||||
package = Package.from_archive(full_path, pacman)
|
package = Package.from_archive(full_path)
|
||||||
package_list.append({
|
package_list.append({
|
||||||
"package_base": package.base,
|
"package_base": package.base,
|
||||||
"packager": package.packager,
|
"packager": package.packager,
|
||||||
|
|||||||
@@ -20,13 +20,11 @@
|
|||||||
from dataclasses import replace
|
from dataclasses import replace
|
||||||
from sqlite3 import Connection
|
from sqlite3 import Connection
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.repository import Explorer
|
from ahriman.core.repository import Explorer
|
||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
from ahriman.core.utils import atomic_move, package_like, symlink_relative
|
from ahriman.core.utils import atomic_move, package_like, symlink_relative
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
@@ -45,29 +43,27 @@ def migrate_data(connection: Connection, configuration: Configuration) -> None:
|
|||||||
|
|
||||||
for repository_id in Explorer.repositories_extract(configuration):
|
for repository_id in Explorer.repositories_extract(configuration):
|
||||||
paths = replace(configuration.repository_paths, repository_id=repository_id)
|
paths = replace(configuration.repository_paths, repository_id=repository_id)
|
||||||
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
|
||||||
|
|
||||||
# create archive directory if required
|
# create archive directory if required
|
||||||
if not paths.archive.is_dir():
|
if not paths.archive.is_dir():
|
||||||
with paths.preserve_owner():
|
with paths.preserve_owner():
|
||||||
paths.archive.mkdir(mode=0o755, parents=True)
|
paths.archive.mkdir(mode=0o755, parents=True)
|
||||||
|
|
||||||
move_packages(paths, pacman)
|
move_packages(paths)
|
||||||
|
|
||||||
|
|
||||||
def move_packages(repository_paths: RepositoryPaths, pacman: Pacman) -> None:
|
def move_packages(repository_paths: RepositoryPaths) -> None:
|
||||||
"""
|
"""
|
||||||
move packages from repository to archive and create symbolic links
|
move packages from repository to archive and create symbolic links
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
repository_paths(RepositoryPaths): repository paths instance
|
repository_paths(RepositoryPaths): repository paths instance
|
||||||
pacman(Pacman): alpm wrapper instance
|
|
||||||
"""
|
"""
|
||||||
for archive in filter(package_like, repository_paths.repository.iterdir()):
|
for archive in filter(package_like, repository_paths.repository.iterdir()):
|
||||||
if not archive.is_file(follow_symlinks=False):
|
if not archive.is_file(follow_symlinks=False):
|
||||||
continue # skip symbolic links if any
|
continue # skip symbolic links if any
|
||||||
|
|
||||||
package = Package.from_archive(archive, pacman)
|
package = Package.from_archive(archive)
|
||||||
artifacts = [archive]
|
artifacts = [archive]
|
||||||
# check if there are signatures for this package and append it here too
|
# check if there are signatures for this package and append it here too
|
||||||
if (signature := GPG.signature(archive)).exists():
|
if (signature := GPG.signature(archive)).exists():
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class Executor(PackageInfo, Cleaner):
|
|||||||
|
|
||||||
for path in filter(package_like, archive.iterdir()):
|
for path in filter(package_like, archive.iterdir()):
|
||||||
# check if package version is the same
|
# check if package version is the same
|
||||||
built = Package.from_archive(path, self.pacman)
|
built = Package.from_archive(path)
|
||||||
if built.version != package.version:
|
if built.version != package.version:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ class Executor(PackageInfo, Cleaner):
|
|||||||
else:
|
else:
|
||||||
built = task.build(path, PACKAGER=packager)
|
built = task.build(path, PACKAGER=packager)
|
||||||
|
|
||||||
package.with_packages(built, self.pacman)
|
package.with_packages(built)
|
||||||
for src in built:
|
for src in built:
|
||||||
dst = self.paths.packages / src.name
|
dst = self.paths.packages / src.name
|
||||||
atomic_move(src, dst)
|
atomic_move(src, dst)
|
||||||
|
|||||||
@@ -24,19 +24,31 @@ from functools import cmp_to_key
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.build_tools.package_version import PackageVersion
|
from ahriman.core.build_tools.package_version import PackageVersion
|
||||||
from ahriman.core.build_tools.sources import Sources
|
from ahriman.core.build_tools.sources import Sources
|
||||||
from ahriman.core.repository.repository_properties import RepositoryProperties
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.log import LazyLogging
|
||||||
|
from ahriman.core.status import Client
|
||||||
from ahriman.core.utils import package_like
|
from ahriman.core.utils import package_like
|
||||||
from ahriman.models.changes import Changes
|
from ahriman.models.changes import Changes
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
class PackageInfo(RepositoryProperties):
|
class PackageInfo(LazyLogging):
|
||||||
"""
|
"""
|
||||||
handler for the package information
|
handler for the package information
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
configuration(Configuration): configuration instance
|
||||||
|
pacman(Pacman): alpm wrapper instance
|
||||||
|
reporter(Client): build status reporter instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
configuration: Configuration
|
||||||
|
pacman: Pacman
|
||||||
|
reporter: Client
|
||||||
|
|
||||||
def full_depends(self, package: Package, packages: Iterable[Package]) -> list[str]:
|
def full_depends(self, package: Package, packages: Iterable[Package]) -> list[str]:
|
||||||
"""
|
"""
|
||||||
generate full dependencies list including transitive dependencies
|
generate full dependencies list including transitive dependencies
|
||||||
@@ -87,7 +99,7 @@ class PackageInfo(RepositoryProperties):
|
|||||||
# we are iterating over bases, not single packages
|
# we are iterating over bases, not single packages
|
||||||
for full_path in packages:
|
for full_path in packages:
|
||||||
try:
|
try:
|
||||||
local = Package.from_archive(full_path, self.pacman)
|
local = Package.from_archive(full_path)
|
||||||
if (source := sources.get(local.base)) is not None: # update source with remote
|
if (source := sources.get(local.base)) is not None: # update source with remote
|
||||||
local.remote = source
|
local.remote = source
|
||||||
|
|
||||||
@@ -115,10 +127,12 @@ class PackageInfo(RepositoryProperties):
|
|||||||
Returns:
|
Returns:
|
||||||
list[Package]: list of packages belonging to this base, sorted by version by ascension
|
list[Package]: list of packages belonging to this base, sorted by version by ascension
|
||||||
"""
|
"""
|
||||||
|
paths = self.configuration.repository_paths
|
||||||
|
|
||||||
packages: dict[tuple[str, str], Package] = {}
|
packages: dict[tuple[str, str], Package] = {}
|
||||||
# we can't use here load_archives, because it ignores versions
|
# we can't use here load_archives, because it ignores versions
|
||||||
for full_path in filter(package_like, self.paths.archive_for(package_base).iterdir()):
|
for full_path in filter(package_like, paths.archive_for(package_base).iterdir()):
|
||||||
local = Package.from_archive(full_path, self.pacman)
|
local = Package.from_archive(full_path)
|
||||||
packages.setdefault((local.base, local.version), local).packages.update(local.packages)
|
packages.setdefault((local.base, local.version), local).packages.update(local.packages)
|
||||||
|
|
||||||
comparator: Callable[[Package, Package], int] = lambda left, right: left.vercmp(right.version)
|
comparator: Callable[[Package, Package], int] = lambda left, right: left.vercmp(right.version)
|
||||||
@@ -138,7 +152,7 @@ class PackageInfo(RepositoryProperties):
|
|||||||
with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name:
|
with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name:
|
||||||
dir_path = Path(dir_name)
|
dir_path = Path(dir_name)
|
||||||
patches = self.reporter.package_patches_get(package.base, None)
|
patches = self.reporter.package_patches_get(package.base, None)
|
||||||
current_commit_sha = Sources.load(dir_path, package, patches, self.paths)
|
current_commit_sha = Sources.load(dir_path, package, patches, self.configuration.repository_paths)
|
||||||
|
|
||||||
if current_commit_sha != last_commit_sha:
|
if current_commit_sha != last_commit_sha:
|
||||||
return Sources.changes(dir_path, last_commit_sha)
|
return Sources.changes(dir_path, last_commit_sha)
|
||||||
@@ -154,7 +168,7 @@ class PackageInfo(RepositoryProperties):
|
|||||||
Returns:
|
Returns:
|
||||||
list[Package]: list of packages properties
|
list[Package]: list of packages properties
|
||||||
"""
|
"""
|
||||||
packages = self.load_archives(filter(package_like, self.paths.repository.iterdir()))
|
packages = self.load_archives(filter(package_like, self.configuration.repository_paths.repository.iterdir()))
|
||||||
if filter_packages:
|
if filter_packages:
|
||||||
packages = [package for package in packages if package.base in filter_packages]
|
packages = [package for package in packages if package.base in filter_packages]
|
||||||
|
|
||||||
@@ -167,7 +181,7 @@ class PackageInfo(RepositoryProperties):
|
|||||||
Returns:
|
Returns:
|
||||||
list[Path]: list of filenames from the directory
|
list[Path]: list of filenames from the directory
|
||||||
"""
|
"""
|
||||||
return list(filter(package_like, self.paths.packages.iterdir()))
|
return list(filter(package_like, self.configuration.repository_paths.packages.iterdir()))
|
||||||
|
|
||||||
def packages_depend_on(self, packages: list[Package], depends_on: Iterable[str] | None) -> list[Package]:
|
def packages_depend_on(self, packages: list[Package], depends_on: Iterable[str] | None) -> list[Package]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from pyalpm import vercmp # type: ignore[import-not-found]
|
|||||||
from typing import Any, Self
|
from typing import Any, Self
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
|
from ahriman.core.alpm.pacman_handle import PacmanHandle
|
||||||
from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
|
from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.utils import dataclass_view, full_version, list_flatmap, parse_version, srcinfo_property_list
|
from ahriman.core.utils import dataclass_view, full_version, list_flatmap, parse_version, srcinfo_property_list
|
||||||
@@ -186,18 +187,17 @@ class Package(LazyLogging):
|
|||||||
return sorted(packages)
|
return sorted(packages)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_archive(cls, path: Path, pacman: Pacman) -> Self:
|
def from_archive(cls, path: Path) -> Self:
|
||||||
"""
|
"""
|
||||||
construct package properties from package archive
|
construct package properties from package archive
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path(Path): path to package archive
|
path(Path): path to package archive
|
||||||
pacman(Pacman): alpm wrapper instance
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Self: package properties
|
Self: package properties
|
||||||
"""
|
"""
|
||||||
package = pacman.handle.load_pkg(str(path))
|
package = PacmanHandle.ephemeral().package_load(path)
|
||||||
description = PackageDescription.from_package(package, path)
|
description = PackageDescription.from_package(package, path)
|
||||||
return cls(
|
return cls(
|
||||||
base=package.base or package.name,
|
base=package.base or package.name,
|
||||||
@@ -400,17 +400,16 @@ class Package(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
return dataclass_view(self)
|
return dataclass_view(self)
|
||||||
|
|
||||||
def with_packages(self, packages: Iterable[Path], pacman: Pacman) -> None:
|
def with_packages(self, packages: Iterable[Path]) -> None:
|
||||||
"""
|
"""
|
||||||
replace packages descriptions with ones from archives
|
replace packages descriptions with ones from archives
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
packages(Iterable[Path]): paths to package archives
|
packages(Iterable[Path]): paths to package archives
|
||||||
pacman(Pacman): alpm wrapper instance
|
|
||||||
"""
|
"""
|
||||||
self.packages = {} # reset state
|
self.packages = {} # reset state
|
||||||
for package in packages:
|
for package in packages:
|
||||||
archive = self.from_archive(package, pacman)
|
archive = self.from_archive(package)
|
||||||
if archive.base != self.base:
|
if archive.base != self.base:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
37
tests/ahriman/core/alpm/test_pacman_handle.py
Normal file
37
tests/ahriman/core/alpm/test_pacman_handle.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from ahriman.core.alpm.pacman_handle import PacmanHandle
|
||||||
|
|
||||||
|
|
||||||
|
def test_package_load() -> None:
|
||||||
|
"""
|
||||||
|
must load package from archive path
|
||||||
|
"""
|
||||||
|
local = Path("local")
|
||||||
|
instance = PacmanHandle.ephemeral()
|
||||||
|
handle_mock = instance.handle = MagicMock()
|
||||||
|
|
||||||
|
instance.package_load(local)
|
||||||
|
handle_mock.load_pkg.assert_called_once_with(str(local))
|
||||||
|
|
||||||
|
PacmanHandle._ephemeral = None
|
||||||
|
|
||||||
|
|
||||||
|
def test_getattr() -> None:
|
||||||
|
"""
|
||||||
|
must proxy attribute access to underlying handle
|
||||||
|
"""
|
||||||
|
instance = PacmanHandle.ephemeral()
|
||||||
|
assert instance.dbpath
|
||||||
|
|
||||||
|
|
||||||
|
def test_getattr_not_found() -> None:
|
||||||
|
"""
|
||||||
|
must raise AttributeError for missing handle attributes
|
||||||
|
"""
|
||||||
|
instance = PacmanHandle.ephemeral()
|
||||||
|
with pytest.raises(AttributeError):
|
||||||
|
assert instance.random_attribute
|
||||||
@@ -34,8 +34,7 @@ def test_migrate_package_depends(connection: Connection, configuration: Configur
|
|||||||
package_mock = mocker.patch("ahriman.models.package.Package.from_archive", return_value=package_ahriman)
|
package_mock = mocker.patch("ahriman.models.package.Package.from_archive", return_value=package_ahriman)
|
||||||
|
|
||||||
migrate_package_depends(connection, configuration)
|
migrate_package_depends(connection, configuration)
|
||||||
package_mock.assert_called_once_with(
|
package_mock.assert_called_once_with(package_ahriman.packages[package_ahriman.base].filepath)
|
||||||
package_ahriman.packages[package_ahriman.base].filepath, pytest.helpers.anyvar(int))
|
|
||||||
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [{
|
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [{
|
||||||
"make_depends": package_ahriman.packages[package_ahriman.base].make_depends,
|
"make_depends": package_ahriman.packages[package_ahriman.base].make_depends,
|
||||||
"opt_depends": package_ahriman.packages[package_ahriman.base].opt_depends,
|
"opt_depends": package_ahriman.packages[package_ahriman.base].opt_depends,
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ def test_migrate_package_depends(connection: Connection, configuration: Configur
|
|||||||
package_mock = mocker.patch("ahriman.models.package.Package.from_archive", return_value=package_ahriman)
|
package_mock = mocker.patch("ahriman.models.package.Package.from_archive", return_value=package_ahriman)
|
||||||
|
|
||||||
migrate_package_check_depends(connection, configuration)
|
migrate_package_check_depends(connection, configuration)
|
||||||
package_mock.assert_called_once_with(
|
package_mock.assert_called_once_with(package_ahriman.packages[package_ahriman.base].filepath)
|
||||||
package_ahriman.packages[package_ahriman.base].filepath, pytest.helpers.anyvar(int))
|
|
||||||
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [{
|
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [{
|
||||||
"check_depends": package_ahriman.packages[package_ahriman.base].check_depends,
|
"check_depends": package_ahriman.packages[package_ahriman.base].check_depends,
|
||||||
"package": package_ahriman.base,
|
"package": package_ahriman.base,
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ def test_migrate_package_base_packager(connection: Connection, configuration: Co
|
|||||||
package_mock = mocker.patch("ahriman.models.package.Package.from_archive", return_value=package_ahriman)
|
package_mock = mocker.patch("ahriman.models.package.Package.from_archive", return_value=package_ahriman)
|
||||||
|
|
||||||
migrate_package_base_packager(connection, configuration)
|
migrate_package_base_packager(connection, configuration)
|
||||||
package_mock.assert_called_once_with(
|
package_mock.assert_called_once_with(package_ahriman.packages[package_ahriman.base].filepath)
|
||||||
package_ahriman.packages[package_ahriman.base].filepath, pytest.helpers.anyvar(int))
|
|
||||||
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [{
|
connection.executemany.assert_called_once_with(pytest.helpers.anyvar(str, strict=True), [{
|
||||||
"package_base": package_ahriman.base,
|
"package_base": package_ahriman.base,
|
||||||
"packager": package_ahriman.packager,
|
"packager": package_ahriman.packager,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ from sqlite3 import Connection
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from unittest.mock import call as MockCall
|
from unittest.mock import call as MockCall
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database.migrations.m016_archive import migrate_data, move_packages
|
from ahriman.core.database.migrations.m016_archive import migrate_data, move_packages
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
@@ -28,12 +27,12 @@ def test_migrate_data(connection: Connection, configuration: Configuration, mock
|
|||||||
|
|
||||||
migrate_data(connection, configuration)
|
migrate_data(connection, configuration)
|
||||||
migration_mock.assert_has_calls([
|
migration_mock.assert_has_calls([
|
||||||
MockCall(replace(configuration.repository_paths, repository_id=repository), pytest.helpers.anyvar(int))
|
MockCall(replace(configuration.repository_paths, repository_id=repository))
|
||||||
for repository in repositories
|
for repository in repositories
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
def test_move_packages(repository_paths: RepositoryPaths, pacman: Pacman, package_ahriman: Package,
|
def test_move_packages(repository_paths: RepositoryPaths, package_ahriman: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must move packages to the archive directory
|
must move packages to the archive directory
|
||||||
@@ -57,9 +56,9 @@ def test_move_packages(repository_paths: RepositoryPaths, pacman: Pacman, packag
|
|||||||
move_mock = mocker.patch("ahriman.core.database.migrations.m016_archive.atomic_move")
|
move_mock = mocker.patch("ahriman.core.database.migrations.m016_archive.atomic_move")
|
||||||
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
|
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
|
||||||
|
|
||||||
move_packages(repository_paths, pacman)
|
move_packages(repository_paths)
|
||||||
archive_mock.assert_has_calls([
|
archive_mock.assert_has_calls([
|
||||||
MockCall(repository_paths.repository / filename, pacman)
|
MockCall(repository_paths.repository / filename)
|
||||||
for filename in ("file.pkg.tar.xz", "file2.pkg.tar.xz")
|
for filename in ("file.pkg.tar.xz", "file2.pkg.tar.xz")
|
||||||
])
|
])
|
||||||
move_mock.assert_has_calls([
|
move_mock.assert_has_calls([
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.repository.cleaner import Cleaner
|
from ahriman.core.repository.cleaner import Cleaner
|
||||||
from ahriman.core.repository.executor import Executor
|
from ahriman.core.repository.executor import Executor
|
||||||
from ahriman.core.repository.package_info import PackageInfo
|
|
||||||
from ahriman.core.repository.update_handler import UpdateHandler
|
from ahriman.core.repository.update_handler import UpdateHandler
|
||||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||||
|
|
||||||
@@ -50,23 +49,6 @@ def executor(configuration: Configuration, database: SQLite, mocker: MockerFixtu
|
|||||||
refresh_pacman_database=PacmanSynchronization.Disabled)
|
refresh_pacman_database=PacmanSynchronization.Disabled)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def package_info(configuration: Configuration, database: SQLite) -> PackageInfo:
|
|
||||||
"""
|
|
||||||
fixture for package info
|
|
||||||
|
|
||||||
Args:
|
|
||||||
configuration(Configuration): configuration fixture
|
|
||||||
database(SQLite): database fixture
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
PackageInfo: package info test instance
|
|
||||||
"""
|
|
||||||
_, repository_id = configuration.check_loaded()
|
|
||||||
return PackageInfo(repository_id, configuration, database, report=False,
|
|
||||||
refresh_pacman_database=PacmanSynchronization.Disabled)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def update_handler(configuration: Configuration, database: SQLite, mocker: MockerFixture) -> UpdateHandler:
|
def update_handler(configuration: Configuration, database: SQLite, mocker: MockerFixture) -> UpdateHandler:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ def test_package_build(executor: Executor, package_ahriman: Package, mocker: Moc
|
|||||||
init_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), None)
|
init_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), None)
|
||||||
package_mock.assert_called_once_with(Path("local"), executor.architecture, None)
|
package_mock.assert_called_once_with(Path("local"), executor.architecture, None)
|
||||||
lookup_mock.assert_called_once_with(package_ahriman)
|
lookup_mock.assert_called_once_with(package_ahriman)
|
||||||
with_packages_mock.assert_called_once_with([Path(package_ahriman.base)], executor.pacman)
|
with_packages_mock.assert_called_once_with([Path(package_ahriman.base)])
|
||||||
rename_mock.assert_called_once_with(Path(package_ahriman.base), executor.paths.packages / package_ahriman.base)
|
rename_mock.assert_called_once_with(Path(package_ahriman.base), executor.paths.packages / package_ahriman.base)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ from pathlib import Path
|
|||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from ahriman.core.repository.package_info import PackageInfo
|
from ahriman.core.repository import Repository
|
||||||
from ahriman.models.changes import Changes
|
from ahriman.models.changes import Changes
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
def test_full_depends(package_info: PackageInfo, package_ahriman: Package, package_python_schedule: Package,
|
def test_full_depends(repository: Repository, package_ahriman: Package, package_python_schedule: Package,
|
||||||
pyalpm_package_ahriman: MagicMock) -> None:
|
pyalpm_package_ahriman: MagicMock) -> None:
|
||||||
"""
|
"""
|
||||||
must extract all dependencies from the package
|
must extract all dependencies from the package
|
||||||
@@ -18,18 +18,18 @@ def test_full_depends(package_info: PackageInfo, package_ahriman: Package, packa
|
|||||||
|
|
||||||
database_mock = MagicMock()
|
database_mock = MagicMock()
|
||||||
database_mock.pkgcache = [pyalpm_package_ahriman]
|
database_mock.pkgcache = [pyalpm_package_ahriman]
|
||||||
package_info.pacman = MagicMock()
|
repository.pacman = MagicMock()
|
||||||
package_info.pacman.handle.get_syncdbs.return_value = [database_mock]
|
repository.pacman.handle.get_syncdbs.return_value = [database_mock]
|
||||||
|
|
||||||
assert package_info.full_depends(package_ahriman, [package_python_schedule]) == package_ahriman.depends
|
assert repository.full_depends(package_ahriman, [package_python_schedule]) == package_ahriman.depends
|
||||||
|
|
||||||
package_python_schedule.packages[package_python_schedule.base].depends = [package_ahriman.base]
|
package_python_schedule.packages[package_python_schedule.base].depends = [package_ahriman.base]
|
||||||
expected = sorted(set(package_python_schedule.depends + package_ahriman.depends))
|
expected = sorted(set(package_python_schedule.depends + package_ahriman.depends))
|
||||||
assert package_info.full_depends(package_python_schedule, [package_python_schedule]) == expected
|
assert repository.full_depends(package_python_schedule, [package_python_schedule]) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_load_archives(package_ahriman: Package, package_python_schedule: Package,
|
def test_load_archives(repository: Repository, package_ahriman: Package, package_python_schedule: Package,
|
||||||
package_info: PackageInfo, mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must return all packages grouped by package base
|
must return all packages grouped by package base
|
||||||
"""
|
"""
|
||||||
@@ -45,7 +45,7 @@ def test_load_archives(package_ahriman: Package, package_python_schedule: Packag
|
|||||||
(package_ahriman, None),
|
(package_ahriman, None),
|
||||||
])
|
])
|
||||||
|
|
||||||
packages = package_info.load_archives([Path("a.pkg.tar.xz"), Path("b.pkg.tar.xz"), Path("c.pkg.tar.xz")])
|
packages = repository.load_archives([Path("a.pkg.tar.xz"), Path("b.pkg.tar.xz"), Path("c.pkg.tar.xz")])
|
||||||
assert len(packages) == 2
|
assert len(packages) == 2
|
||||||
assert {package.base for package in packages} == {package_ahriman.base, package_python_schedule.base}
|
assert {package.base for package in packages} == {package_ahriman.base, package_python_schedule.base}
|
||||||
|
|
||||||
@@ -56,22 +56,22 @@ def test_load_archives(package_ahriman: Package, package_python_schedule: Packag
|
|||||||
assert set(archives) == expected
|
assert set(archives) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_load_archives_failed(package_info: PackageInfo, mocker: MockerFixture) -> None:
|
def test_load_archives_failed(repository: Repository, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must skip packages which cannot be loaded
|
must skip packages which cannot be loaded
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.models.package.Package.from_archive", side_effect=Exception)
|
mocker.patch("ahriman.models.package.Package.from_archive", side_effect=Exception)
|
||||||
assert not package_info.load_archives([Path("a.pkg.tar.xz")])
|
assert not repository.load_archives([Path("a.pkg.tar.xz")])
|
||||||
|
|
||||||
|
|
||||||
def test_load_archives_not_package(package_info: PackageInfo) -> None:
|
def test_load_archives_not_package(repository: Repository) -> None:
|
||||||
"""
|
"""
|
||||||
must skip not packages from iteration
|
must skip not packages from iteration
|
||||||
"""
|
"""
|
||||||
assert not package_info.load_archives([Path("a.tar.xz")])
|
assert not repository.load_archives([Path("a.tar.xz")])
|
||||||
|
|
||||||
|
|
||||||
def test_load_archives_different_version(package_info: PackageInfo, package_python_schedule: Package,
|
def test_load_archives_different_version(repository: Repository, package_python_schedule: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must load packages with different versions choosing maximal
|
must load packages with different versions choosing maximal
|
||||||
@@ -86,12 +86,12 @@ def test_load_archives_different_version(package_info: PackageInfo, package_pyth
|
|||||||
single_packages[0].version = "0.0.1-1"
|
single_packages[0].version = "0.0.1-1"
|
||||||
mocker.patch("ahriman.models.package.Package.from_archive", side_effect=single_packages)
|
mocker.patch("ahriman.models.package.Package.from_archive", side_effect=single_packages)
|
||||||
|
|
||||||
packages = package_info.load_archives([Path("a.pkg.tar.xz"), Path("b.pkg.tar.xz")])
|
packages = repository.load_archives([Path("a.pkg.tar.xz"), Path("b.pkg.tar.xz")])
|
||||||
assert len(packages) == 1
|
assert len(packages) == 1
|
||||||
assert packages[0].version == package_python_schedule.version
|
assert packages[0].version == package_python_schedule.version
|
||||||
|
|
||||||
|
|
||||||
def test_package_archives(package_info: PackageInfo, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_package_archives(repository: Repository, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must load package archives sorted by version
|
must load package archives sorted by version
|
||||||
"""
|
"""
|
||||||
@@ -110,12 +110,12 @@ def test_package_archives(package_info: PackageInfo, package_ahriman: Package, m
|
|||||||
mocker.patch("pathlib.Path.iterdir", return_value=[Path(str(i)) for i in range(5)])
|
mocker.patch("pathlib.Path.iterdir", return_value=[Path(str(i)) for i in range(5)])
|
||||||
mocker.patch("ahriman.models.package.Package.from_archive", side_effect=package)
|
mocker.patch("ahriman.models.package.Package.from_archive", side_effect=package)
|
||||||
|
|
||||||
result = package_info.package_archives(package_ahriman.base)
|
result = repository.package_archives(package_ahriman.base)
|
||||||
assert len(result) == 5
|
assert len(result) == 5
|
||||||
assert [p.version for p in result] == [str(i) for i in range(5)]
|
assert [p.version for p in result] == [str(i) for i in range(5)]
|
||||||
|
|
||||||
|
|
||||||
def test_package_changes(package_info: PackageInfo, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_package_changes(repository: Repository, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must load package changes
|
must load package changes
|
||||||
"""
|
"""
|
||||||
@@ -123,23 +123,24 @@ def test_package_changes(package_info: PackageInfo, package_ahriman: Package, mo
|
|||||||
load_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.load", return_value="sha2")
|
load_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.load", return_value="sha2")
|
||||||
changes_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.changes", return_value=changes)
|
changes_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.changes", return_value=changes)
|
||||||
|
|
||||||
assert package_info.package_changes(package_ahriman, changes.last_commit_sha) == changes
|
assert repository.package_changes(package_ahriman, changes.last_commit_sha) == changes
|
||||||
load_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman, [], package_info.paths)
|
load_mock.assert_called_once_with(
|
||||||
|
pytest.helpers.anyvar(int), package_ahriman, [], repository.configuration.repository_paths)
|
||||||
changes_mock.assert_called_once_with(pytest.helpers.anyvar(int), changes.last_commit_sha)
|
changes_mock.assert_called_once_with(pytest.helpers.anyvar(int), changes.last_commit_sha)
|
||||||
|
|
||||||
|
|
||||||
def test_package_changes_skip(package_info: PackageInfo, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_package_changes_skip(repository: Repository, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must skip loading package changes if no new commits
|
must skip loading package changes if no new commits
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources.load", return_value="sha")
|
mocker.patch("ahriman.core.build_tools.sources.Sources.load", return_value="sha")
|
||||||
changes_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.changes")
|
changes_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.changes")
|
||||||
|
|
||||||
assert package_info.package_changes(package_ahriman, "sha") is None
|
assert repository.package_changes(package_ahriman, "sha") is None
|
||||||
changes_mock.assert_not_called()
|
changes_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_packages(package_info: PackageInfo, package_ahriman: Package, package_python_schedule: Package,
|
def test_packages(repository: Repository, package_ahriman: Package, package_python_schedule: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must return repository packages
|
must return repository packages
|
||||||
@@ -147,12 +148,12 @@ def test_packages(package_info: PackageInfo, package_ahriman: Package, package_p
|
|||||||
mocker.patch("pathlib.Path.iterdir")
|
mocker.patch("pathlib.Path.iterdir")
|
||||||
load_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives",
|
load_mock = mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives",
|
||||||
return_value=[package_ahriman, package_python_schedule])
|
return_value=[package_ahriman, package_python_schedule])
|
||||||
assert package_info.packages() == [package_ahriman, package_python_schedule]
|
assert repository.packages() == [package_ahriman, package_python_schedule]
|
||||||
# it uses filter object, so we cannot verify argument list =/
|
# it uses filter object, so we cannot verify argument list =/
|
||||||
load_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
load_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||||
|
|
||||||
|
|
||||||
def test_packages_filter(package_info: PackageInfo, package_ahriman: Package, package_python_schedule: Package,
|
def test_packages_filter(repository: Repository, package_ahriman: Package, package_python_schedule: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must filter result by bases
|
must filter result by bases
|
||||||
@@ -160,33 +161,33 @@ def test_packages_filter(package_info: PackageInfo, package_ahriman: Package, pa
|
|||||||
mocker.patch("pathlib.Path.iterdir")
|
mocker.patch("pathlib.Path.iterdir")
|
||||||
mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives",
|
mocker.patch("ahriman.core.repository.package_info.PackageInfo.load_archives",
|
||||||
return_value=[package_ahriman, package_python_schedule])
|
return_value=[package_ahriman, package_python_schedule])
|
||||||
assert package_info.packages([package_ahriman.base]) == [package_ahriman]
|
assert repository.packages([package_ahriman.base]) == [package_ahriman]
|
||||||
|
|
||||||
|
|
||||||
def test_packages_built(package_info: PackageInfo, mocker: MockerFixture) -> None:
|
def test_packages_built(repository: Repository, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must return build packages
|
must return build packages
|
||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[Path("a.tar.xz"), Path("b.pkg.tar.xz")])
|
mocker.patch("pathlib.Path.iterdir", return_value=[Path("a.tar.xz"), Path("b.pkg.tar.xz")])
|
||||||
assert package_info.packages_built() == [Path("b.pkg.tar.xz")]
|
assert repository.packages_built() == [Path("b.pkg.tar.xz")]
|
||||||
|
|
||||||
|
|
||||||
def test_packages_depend_on(package_info: PackageInfo, package_ahriman: Package, package_python_schedule: Package,
|
def test_packages_depend_on(repository: Repository, package_ahriman: Package, package_python_schedule: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must filter packages by depends list
|
must filter packages by depends list
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.repository.Repository.packages",
|
mocker.patch("ahriman.core.repository.repository.Repository.packages",
|
||||||
return_value=[package_ahriman, package_python_schedule])
|
return_value=[package_ahriman, package_python_schedule])
|
||||||
assert package_info.packages_depend_on([package_ahriman], {"python-srcinfo"}) == [package_ahriman]
|
assert repository.packages_depend_on([package_ahriman], {"python-srcinfo"}) == [package_ahriman]
|
||||||
|
|
||||||
|
|
||||||
def test_packages_depend_on_empty(package_info: PackageInfo, package_ahriman: Package, package_python_schedule: Package,
|
def test_packages_depend_on_empty(repository: Repository, package_ahriman: Package, package_python_schedule: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must return all packages in case if no filter is provided
|
must return all packages in case if no filter is provided
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.repository.Repository.packages",
|
mocker.patch("ahriman.core.repository.repository.Repository.packages",
|
||||||
return_value=[package_ahriman, package_python_schedule])
|
return_value=[package_ahriman, package_python_schedule])
|
||||||
assert package_info.packages_depend_on([package_ahriman, package_python_schedule], None) == \
|
assert repository.packages_depend_on([package_ahriman, package_python_schedule], None) == \
|
||||||
[package_ahriman, package_python_schedule]
|
[package_ahriman, package_python_schedule]
|
||||||
|
|||||||
@@ -89,22 +89,6 @@ def pkgbuild_ahriman(resource_path_root: Path) -> Pkgbuild:
|
|||||||
return Pkgbuild.from_file(pkgbuild)
|
return Pkgbuild.from_file(pkgbuild)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
|
||||||
def pyalpm_handle(pyalpm_package_ahriman: MagicMock) -> MagicMock:
|
|
||||||
"""
|
|
||||||
mock object for pyalpm
|
|
||||||
|
|
||||||
Args:
|
|
||||||
pyalpm_package_ahriman(MagicMock): mock object for pyalpm package
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
MagicMock: pyalpm mock
|
|
||||||
"""
|
|
||||||
mock = MagicMock()
|
|
||||||
mock.handle.load_pkg.return_value = pyalpm_package_ahriman
|
|
||||||
return mock
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def pyalpm_package_description_ahriman(package_description_ahriman: PackageDescription) -> MagicMock:
|
def pyalpm_package_description_ahriman(package_description_ahriman: PackageDescription) -> MagicMock:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -148,13 +148,14 @@ def test_packages_full(package_ahriman: Package) -> None:
|
|||||||
assert package_ahriman.packages_full == [package_ahriman.base, f"{package_ahriman.base}-git"]
|
assert package_ahriman.packages_full == [package_ahriman.base, f"{package_ahriman.base}-git"]
|
||||||
|
|
||||||
|
|
||||||
def test_from_archive(package_ahriman: Package, pyalpm_handle: MagicMock, mocker: MockerFixture) -> None:
|
def test_from_archive(package_ahriman: Package, pyalpm_package_ahriman: MagicMock, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must construct package from alpm library
|
must construct package from alpm library
|
||||||
"""
|
"""
|
||||||
|
mocker.patch("ahriman.core.alpm.pacman_handle.PacmanHandle.package_load", return_value=pyalpm_package_ahriman)
|
||||||
mocker.patch("ahriman.models.package_description.PackageDescription.from_package",
|
mocker.patch("ahriman.models.package_description.PackageDescription.from_package",
|
||||||
return_value=package_ahriman.packages[package_ahriman.base])
|
return_value=package_ahriman.packages[package_ahriman.base])
|
||||||
generated = Package.from_archive(Path("path"), pyalpm_handle)
|
generated = Package.from_archive(Path("path"))
|
||||||
generated.remote = package_ahriman.remote
|
generated.remote = package_ahriman.remote
|
||||||
|
|
||||||
assert generated == package_ahriman
|
assert generated == package_ahriman
|
||||||
@@ -165,13 +166,12 @@ def test_from_archive_empty_base(package_ahriman: Package, pyalpm_package_ahrima
|
|||||||
"""
|
"""
|
||||||
must construct package with empty base from alpm library
|
must construct package with empty base from alpm library
|
||||||
"""
|
"""
|
||||||
pyalpm_handle = MagicMock()
|
|
||||||
type(pyalpm_package_ahriman).base = PropertyMock(return_value=None)
|
type(pyalpm_package_ahriman).base = PropertyMock(return_value=None)
|
||||||
pyalpm_handle.handle.load_pkg.return_value = pyalpm_package_ahriman
|
mocker.patch("ahriman.core.alpm.pacman_handle.PacmanHandle.package_load", return_value=pyalpm_package_ahriman)
|
||||||
|
|
||||||
mocker.patch("ahriman.models.package_description.PackageDescription.from_package",
|
mocker.patch("ahriman.models.package_description.PackageDescription.from_package",
|
||||||
return_value=package_ahriman.packages[package_ahriman.base])
|
return_value=package_ahriman.packages[package_ahriman.base])
|
||||||
generated = Package.from_archive(Path("path"), pyalpm_handle)
|
generated = Package.from_archive(Path("path"))
|
||||||
generated.remote = package_ahriman.remote
|
generated.remote = package_ahriman.remote
|
||||||
|
|
||||||
assert generated == package_ahriman
|
assert generated == package_ahriman
|
||||||
@@ -362,7 +362,7 @@ def test_vercmp(package_ahriman: Package, mocker: MockerFixture) -> None:
|
|||||||
vercmp_mock.assert_called_once_with(package_ahriman.version, "version")
|
vercmp_mock.assert_called_once_with(package_ahriman.version, "version")
|
||||||
|
|
||||||
|
|
||||||
def test_with_packages(package_ahriman: Package, package_python_schedule: Package, pacman: Pacman,
|
def test_with_packages(package_ahriman: Package, package_python_schedule: Package,
|
||||||
mocker: MockerFixture) -> None:
|
mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must correctly replace packages descriptions
|
must correctly replace packages descriptions
|
||||||
@@ -375,8 +375,8 @@ def test_with_packages(package_ahriman: Package, package_python_schedule: Packag
|
|||||||
result = copy.deepcopy(package_ahriman)
|
result = copy.deepcopy(package_ahriman)
|
||||||
package_ahriman.packages[package_ahriman.base].architecture = "i686"
|
package_ahriman.packages[package_ahriman.base].architecture = "i686"
|
||||||
|
|
||||||
result.with_packages(paths, pacman)
|
result.with_packages(paths)
|
||||||
from_archive_mock.assert_has_calls([
|
from_archive_mock.assert_has_calls([
|
||||||
MockCall(path, pacman) for path in paths
|
MockCall(path) for path in paths
|
||||||
])
|
])
|
||||||
assert result.packages[result.base] == package_ahriman.packages[package_ahriman.base]
|
assert result.packages[result.base] == package_ahriman.packages[package_ahriman.base]
|
||||||
|
|||||||
Reference in New Issue
Block a user