mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-27 22:31:43 +00:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
84d4523e85 | |||
2c2eae2334 | |||
214d6d7fdd | |||
e9512e9a6a | |||
f984ea75d0 |
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 7.0.4 (0)
|
||||
<!-- Generated by graphviz version 7.0.5 (0)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="15156pt" height="5118pt"
|
||||
|
Before Width: | Height: | Size: 641 KiB After Width: | Height: | Size: 641 KiB |
@ -1,4 +1,4 @@
|
||||
.TH AHRIMAN "1" "2022\-12\-31" "ahriman" "Generated Python Manual"
|
||||
.TH AHRIMAN "1" "2023\-01\-02" "ahriman" "Generated Python Manual"
|
||||
.SH NAME
|
||||
ahriman
|
||||
.SH SYNOPSIS
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Maintainer: Evgeniy Alekseev
|
||||
|
||||
pkgname='ahriman'
|
||||
pkgver=2.5.0
|
||||
pkgver=2.5.2
|
||||
pkgrel=1
|
||||
pkgdesc="ArcH linux ReposItory MANager"
|
||||
arch=('any')
|
||||
|
@ -71,6 +71,8 @@ class Setup(Handler):
|
||||
Setup.configuration_create_sudo(application.repository.paths, args.build_command, architecture)
|
||||
|
||||
application.repository.repo.init()
|
||||
# lazy database sync
|
||||
application.repository.pacman.handle # pylint: disable=pointless-statement
|
||||
|
||||
@staticmethod
|
||||
def build_command(root: Path, prefix: str, architecture: str) -> Path:
|
||||
@ -78,7 +80,7 @@ class Setup(Handler):
|
||||
generate build command name
|
||||
|
||||
Args:
|
||||
root(Path): root directory for the build command (must be root of the reporitory)
|
||||
root(Path): root directory for the build command (must be root of the repository)
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
|
||||
|
@ -21,7 +21,7 @@ import shutil
|
||||
|
||||
from pathlib import Path
|
||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore
|
||||
from typing import Generator, Set
|
||||
from typing import Any, Callable, Generator, Set
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -36,6 +36,8 @@ class Pacman(LazyLogging):
|
||||
handle(Handle): pyalpm root ``Handle``
|
||||
"""
|
||||
|
||||
handle: Handle
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, *, refresh_database: int) -> None:
|
||||
"""
|
||||
default constructor
|
||||
@ -46,6 +48,22 @@ class Pacman(LazyLogging):
|
||||
refresh_database(int): synchronize local cache to remote. If set to ``0``, no syncronization will be
|
||||
enabled, if set to ``1`` - normal syncronization, if set to ``2`` - force syncronization
|
||||
"""
|
||||
self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle(
|
||||
architecture, configuration, refresh_database=refresh_database)
|
||||
|
||||
def __create_handle(self, architecture: str, configuration: Configuration, *, refresh_database: int) -> Handle:
|
||||
"""
|
||||
create lazy handle function
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
refresh_database(int): synchronize local cache to remote. If set to ``0``, no syncronization will be
|
||||
enabled, if set to ``1`` - normal syncronization, if set to ``2`` - force syncronization
|
||||
|
||||
Returns:
|
||||
Handle: fully initialized pacman handle
|
||||
"""
|
||||
root = configuration.getpath("alpm", "root")
|
||||
pacman_root = configuration.getpath("alpm", "database")
|
||||
use_ahriman_cache = configuration.getboolean("alpm", "use_ahriman_cache")
|
||||
@ -53,20 +71,42 @@ class Pacman(LazyLogging):
|
||||
paths = configuration.repository_paths
|
||||
database_path = paths.pacman if use_ahriman_cache else pacman_root
|
||||
|
||||
self.handle = Handle(str(root), str(database_path))
|
||||
handle = Handle(str(root), str(database_path))
|
||||
for repository in configuration.getlist("alpm", "repositories"):
|
||||
database = self.database_init(repository, mirror, architecture)
|
||||
self.database_copy(database, pacman_root, paths, use_ahriman_cache=use_ahriman_cache)
|
||||
database = self.database_init(handle, repository, mirror, architecture)
|
||||
self.database_copy(handle, database, pacman_root, paths, use_ahriman_cache=use_ahriman_cache)
|
||||
|
||||
if use_ahriman_cache and refresh_database:
|
||||
self.database_sync(refresh_database > 1)
|
||||
self.database_sync(handle, force=refresh_database > 1)
|
||||
|
||||
def database_copy(self, database: DB, pacman_root: Path, paths: RepositoryPaths, *,
|
||||
return handle
|
||||
|
||||
def __getattr__(self, item: str) -> Any:
|
||||
"""
|
||||
pacman handle extractor
|
||||
|
||||
Args:
|
||||
item(str): property name
|
||||
|
||||
Returns:
|
||||
Any: attribute by its name
|
||||
|
||||
Raises:
|
||||
AttributeError: in case if no such attribute found
|
||||
"""
|
||||
if item == "handle":
|
||||
handle = self.__create_handle_fn()
|
||||
setattr(self, item, handle)
|
||||
return handle
|
||||
return super().__getattr__(item) # required for logging attribute
|
||||
|
||||
def database_copy(self, handle: Handle, database: DB, pacman_root: Path, paths: RepositoryPaths, *,
|
||||
use_ahriman_cache: bool) -> None:
|
||||
"""
|
||||
copy database from the operating system root to the ahriman local home
|
||||
|
||||
Args:
|
||||
handle(Handle): pacman handle which will be used for database copying
|
||||
database(DB): pacman database instance to be copied
|
||||
pacman_root(Path): operating system pacman root
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
@ -78,7 +118,7 @@ class Pacman(LazyLogging):
|
||||
if not use_ahriman_cache:
|
||||
return
|
||||
# copy root database if no local copy found
|
||||
pacman_db_path = Path(self.handle.dbpath)
|
||||
pacman_db_path = Path(handle.dbpath)
|
||||
if not pacman_db_path.is_dir():
|
||||
return # root directory does not exist yet
|
||||
dst = repository_database(pacman_db_path)
|
||||
@ -92,11 +132,12 @@ class Pacman(LazyLogging):
|
||||
shutil.copy(src, dst)
|
||||
paths.chown(dst)
|
||||
|
||||
def database_init(self, repository: str, mirror: str, architecture: str) -> DB:
|
||||
def database_init(self, handle: Handle, repository: str, mirror: str, architecture: str) -> DB:
|
||||
"""
|
||||
create database instance from pacman handler and set its properties
|
||||
|
||||
Args:
|
||||
handle(Handle): pacman handle which will be used for database initializing
|
||||
repository(str): pacman repository name (e.g. core)
|
||||
mirror(str): arch linux mirror url
|
||||
architecture(str): repository architecture
|
||||
@ -104,21 +145,23 @@ class Pacman(LazyLogging):
|
||||
Returns:
|
||||
DB: loaded pacman database instance
|
||||
"""
|
||||
database: DB = self.handle.register_syncdb(repository, SIG_PACKAGE)
|
||||
self.logger.info("loading pacman databases")
|
||||
database: DB = handle.register_syncdb(repository, SIG_PACKAGE)
|
||||
# replace variables in mirror address
|
||||
database.servers = [mirror.replace("$repo", repository).replace("$arch", architecture)]
|
||||
return database
|
||||
|
||||
def database_sync(self, force: bool) -> None:
|
||||
def database_sync(self, handle: Handle, *, force: bool) -> None:
|
||||
"""
|
||||
sync local database
|
||||
|
||||
Args:
|
||||
handle(Handle): pacman handle which will be used for database sync
|
||||
force(bool): force database syncronization (same as ``pacman -Syy``)
|
||||
"""
|
||||
self.logger.info("refresh ahriman's home pacman database (force refresh %s)", force)
|
||||
transaction = self.handle.init_transaction()
|
||||
for database in self.handle.get_syncdbs():
|
||||
transaction = handle.init_transaction()
|
||||
for database in handle.get_syncdbs():
|
||||
try:
|
||||
database.update(force)
|
||||
except PyalpmError:
|
||||
|
@ -81,7 +81,8 @@ class RemotePush(LazyLogging):
|
||||
# ...secondly, we clone whole tree...
|
||||
Sources.fetch(package_target_dir, package.remote)
|
||||
# ...and last, but not least, we remove the dot-git directory...
|
||||
shutil.rmtree(package_target_dir / ".git", ignore_errors=True)
|
||||
for git_file in package_target_dir.glob(".git*"):
|
||||
shutil.rmtree(package_target_dir / git_file)
|
||||
# ...copy all patches...
|
||||
for patch in self.database.patches_get(package.base):
|
||||
filename = f"ahriman-{package.base}.patch" if patch.key is None else f"ahriman-{patch.key}.patch"
|
||||
|
@ -75,9 +75,6 @@ class UpdateHandler(Cleaner):
|
||||
remote = Package.from_aur(local.base, self.pacman)
|
||||
|
||||
calculate_version = not local.is_newer_than(min_vcs_build_date)
|
||||
self.logger.debug("set VCS version calculation for %s to %s having minimal build date %s",
|
||||
local.base, calculate_version, min_vcs_build_date)
|
||||
|
||||
if local.is_outdated(remote, self.paths, calculate_version=calculate_version):
|
||||
self.reporter.set_pending(local.base)
|
||||
result.append(remote)
|
||||
|
@ -17,4 +17,4 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
__version__ = "2.5.0"
|
||||
__version__ = "2.5.2"
|
||||
|
@ -1,3 +1,5 @@
|
||||
import pytest
|
||||
|
||||
from pathlib import Path
|
||||
from pyalpm import error as PyalpmError
|
||||
from pytest_mock import MockerFixture
|
||||
@ -21,8 +23,9 @@ def test_init_with_local_cache(configuration: Configuration, mocker: MockerFixtu
|
||||
with TemporaryDirectory(ignore_cleanup_errors=True) as pacman_root:
|
||||
mocker.patch.object(RepositoryPaths, "pacman", Path(pacman_root))
|
||||
# during the creation pyalpm.Handle will create also version file which we would like to remove later
|
||||
Pacman("x86_64", configuration, refresh_database=1)
|
||||
sync_mock.assert_called_once_with(False)
|
||||
pacman = Pacman("x86_64", configuration, refresh_database=1)
|
||||
assert pacman.handle
|
||||
sync_mock.assert_called_once_with(pytest.helpers.anyvar(int), force=False)
|
||||
|
||||
|
||||
def test_init_with_local_cache_forced(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||
@ -37,8 +40,9 @@ def test_init_with_local_cache_forced(configuration: Configuration, mocker: Mock
|
||||
with TemporaryDirectory(ignore_cleanup_errors=True) as pacman_root:
|
||||
mocker.patch.object(RepositoryPaths, "pacman", Path(pacman_root))
|
||||
# during the creation pyalpm.Handle will create also version file which we would like to remove later
|
||||
Pacman("x86_64", configuration, refresh_database=2)
|
||||
sync_mock.assert_called_once_with(True)
|
||||
pacman = Pacman("x86_64", configuration, refresh_database=2)
|
||||
assert pacman.handle
|
||||
sync_mock.assert_called_once_with(pytest.helpers.anyvar(int), force=True)
|
||||
|
||||
|
||||
def test_database_copy(pacman: Pacman, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
|
||||
@ -54,7 +58,7 @@ def test_database_copy(pacman: Pacman, repository_paths: RepositoryPaths, mocker
|
||||
copy_mock = mocker.patch("shutil.copy")
|
||||
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
|
||||
|
||||
pacman.database_copy(database, path, repository_paths, use_ahriman_cache=True)
|
||||
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=True)
|
||||
copy_mock.assert_called_once_with(path / "sync" / "core.db", dst_path)
|
||||
chown_mock.assert_called_once_with(dst_path)
|
||||
|
||||
@ -70,7 +74,7 @@ def test_database_copy_skip(pacman: Pacman, repository_paths: RepositoryPaths, m
|
||||
mocker.patch("pathlib.Path.is_file", autospec=True, side_effect=lambda p: True if p.is_relative_to(path) else False)
|
||||
copy_mock = mocker.patch("shutil.copy")
|
||||
|
||||
pacman.database_copy(database, path, repository_paths, use_ahriman_cache=False)
|
||||
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=False)
|
||||
copy_mock.assert_not_called()
|
||||
|
||||
|
||||
@ -85,7 +89,7 @@ def test_database_copy_no_directory(pacman: Pacman, repository_paths: Repository
|
||||
mocker.patch("pathlib.Path.is_file", autospec=True, side_effect=lambda p: True if p.is_relative_to(path) else False)
|
||||
copy_mock = mocker.patch("shutil.copy")
|
||||
|
||||
pacman.database_copy(database, path, repository_paths, use_ahriman_cache=True)
|
||||
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=True)
|
||||
copy_mock.assert_not_called()
|
||||
|
||||
|
||||
@ -100,7 +104,7 @@ def test_database_copy_no_root_file(pacman: Pacman, repository_paths: Repository
|
||||
mocker.patch("pathlib.Path.is_file", return_value=False)
|
||||
copy_mock = mocker.patch("shutil.copy")
|
||||
|
||||
pacman.database_copy(database, path, repository_paths, use_ahriman_cache=True)
|
||||
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=True)
|
||||
copy_mock.assert_not_called()
|
||||
|
||||
|
||||
@ -114,7 +118,7 @@ def test_database_copy_database_exist(pacman: Pacman, repository_paths: Reposito
|
||||
mocker.patch("pathlib.Path.is_file", return_value=True)
|
||||
copy_mock = mocker.patch("shutil.copy")
|
||||
|
||||
pacman.database_copy(database, Path("root"), repository_paths, use_ahriman_cache=True)
|
||||
pacman.database_copy(pacman.handle, database, Path("root"), repository_paths, use_ahriman_cache=True)
|
||||
copy_mock.assert_not_called()
|
||||
|
||||
|
||||
@ -123,7 +127,7 @@ def test_database_init(pacman: Pacman, configuration: Configuration) -> None:
|
||||
must init database with settings
|
||||
"""
|
||||
mirror = configuration.get("alpm", "mirror")
|
||||
database = pacman.database_init("test", mirror, "x86_64")
|
||||
database = pacman.database_init(pacman.handle, "test", mirror, "x86_64")
|
||||
assert len(database.servers) == 1
|
||||
|
||||
|
||||
@ -139,7 +143,7 @@ def test_database_sync(pacman: Pacman) -> None:
|
||||
handle_mock.init_transaction.return_value = transaction_mock
|
||||
pacman.handle = handle_mock
|
||||
|
||||
pacman.database_sync(False)
|
||||
pacman.database_sync(pacman.handle, force=False)
|
||||
handle_mock.init_transaction.assert_called_once_with()
|
||||
core_mock.update.assert_called_once_with(False)
|
||||
extra_mock.update.assert_called_once_with(False)
|
||||
@ -157,7 +161,7 @@ def test_database_sync_failed(pacman: Pacman) -> None:
|
||||
handle_mock.get_syncdbs.return_value = [core_mock, extra_mock]
|
||||
pacman.handle = handle_mock
|
||||
|
||||
pacman.database_sync(False)
|
||||
pacman.database_sync(pacman.handle, force=False)
|
||||
extra_mock.update.assert_called_once_with(False)
|
||||
|
||||
|
||||
@ -170,7 +174,7 @@ def test_database_sync_forced(pacman: Pacman) -> None:
|
||||
handle_mock.get_syncdbs.return_value = [core_mock]
|
||||
pacman.handle = handle_mock
|
||||
|
||||
pacman.database_sync(True)
|
||||
pacman.database_sync(pacman.handle, force=True)
|
||||
handle_mock.init_transaction.assert_called_once_with()
|
||||
core_mock.update.assert_called_once_with(True)
|
||||
|
||||
|
@ -20,18 +20,21 @@ def test_package_update(database: SQLite, configuration: Configuration, package_
|
||||
"""
|
||||
patch1 = PkgbuildPatch(None, "patch")
|
||||
patch2 = PkgbuildPatch("key", "value")
|
||||
local = Path("local")
|
||||
|
||||
glob_mock = mocker.patch("pathlib.Path.glob", return_value=[".git", ".gitignore"])
|
||||
rmtree_mock = mocker.patch("shutil.rmtree")
|
||||
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
|
||||
patches_mock = mocker.patch("ahriman.core.database.SQLite.patches_get", return_value=[patch1, patch2])
|
||||
patches_write_mock = mocker.patch("ahriman.models.pkgbuild_patch.PkgbuildPatch.write")
|
||||
runner = RemotePush(configuration, database, "gitremote")
|
||||
|
||||
local = Path("local")
|
||||
assert runner.package_update(package_ahriman, local) == package_ahriman.base
|
||||
glob_mock.assert_called_once_with(".git*")
|
||||
rmtree_mock.assert_has_calls([
|
||||
MockCall(local / package_ahriman.base, ignore_errors=True),
|
||||
MockCall(local / package_ahriman.base / ".git", ignore_errors=True),
|
||||
MockCall(local / package_ahriman.base / ".git"),
|
||||
MockCall(local / package_ahriman.base / ".gitignore"),
|
||||
])
|
||||
fetch_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman.remote)
|
||||
patches_mock.assert_called_once_with(package_ahriman.base)
|
||||
|
Reference in New Issue
Block a user