deprecate init/repo-init command

In current workflow you need to run setup to run init (because of
repository name), but you need to run init before setup (because of
repository tree rights).

New solution just add `Repo.init()` method call to setup subcommand
after config reload to make sure that repository name has been applied.
In addition chown method as well as setuid method for check_output have
been added.
This commit is contained in:
2022-03-21 00:44:44 +03:00
parent 63e79ec57a
commit 13121298f5
24 changed files with 225 additions and 147 deletions

View File

@ -6,7 +6,7 @@ from pytest_mock import MockerFixture
from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitecture, MultipleArchitecture
from ahriman.core.exceptions import MissingArchitecture, MultipleArchitectures
def test_architectures_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
@ -94,7 +94,7 @@ def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: Mocker
args.command = "web"
mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False)
with pytest.raises(MultipleArchitecture):
with pytest.raises(MultipleArchitectures):
Handler.execute(args)

View File

@ -1,26 +0,0 @@
import argparse
from pytest_mock import MockerFixture
from ahriman.application.handlers import Init
from ahriman.core.configuration import Configuration
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
mocker.patch("ahriman.core.repository.properties.check_user")
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
Init.run(args, "x86_64", configuration, True, False)
tree_create_mock.assert_called_once_with()
init_mock.assert_called_once_with()
def test_disallow_auto_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Init.ALLOW_AUTO_ARCHITECTURE_RUN

View File

@ -40,6 +40,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
makepkg_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg")
sudo_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_sudo")
executable_mock = mocker.patch("ahriman.application.handlers.setup.Setup.executable_create")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
paths = RepositoryPaths(configuration.getpath("repository", "root"), "x86_64")
Setup.run(args, "x86_64", configuration, True, False)
@ -49,6 +50,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
makepkg_configuration_mock.assert_called_once_with(args.packager, paths)
sudo_configuration_mock.assert_called_once_with(args.build_command, "x86_64")
executable_mock.assert_called_once_with(args.build_command, "x86_64")
init_mock.assert_called_once()
def test_build_command(args: argparse.Namespace) -> None:

View File

@ -288,15 +288,6 @@ def test_subparsers_repo_config(parser: argparse.ArgumentParser) -> None:
assert args.unsafe
def test_subparsers_repo_init(parser: argparse.ArgumentParser) -> None:
"""
repo-init command must imply no_report
"""
args = parser.parse_args(["-a", "x86_64", "repo-init"])
assert args.architecture == ["x86_64"]
assert args.no_report
def test_subparsers_repo_rebuild_architecture(parser: argparse.ArgumentParser) -> None:
"""
repo-rebuild command must correctly parse architecture list

View File

@ -82,7 +82,7 @@ def test_check_user(lock: Lock, mocker: MockerFixture) -> None:
"""
check_user_patch = mocker.patch("ahriman.application.lock.check_user")
lock.check_user()
check_user_patch.assert_called_once_with(lock.root, False)
check_user_patch.assert_called_once_with(lock.paths, False)
def test_check_user_exception(lock: Lock, mocker: MockerFixture) -> None:

View File

@ -9,6 +9,7 @@ from pytest_mock import MockerFixture
from ahriman.core.exceptions import InvalidOption, UnsafeRun
from ahriman.core.util import check_output, check_user, filter_json, package_like, pretty_datetime, pretty_size, walk
from ahriman.models.package import Package
from ahriman.models.repository_paths import RepositoryPaths
def test_check_output(mocker: MockerFixture) -> None:
@ -56,37 +57,37 @@ def test_check_user(mocker: MockerFixture) -> None:
"""
must check user correctly
"""
cwd = Path.cwd()
mocker.patch("os.getuid", return_value=cwd.stat().st_uid)
check_user(cwd, False)
paths = RepositoryPaths(Path.cwd(), "x86_64")
mocker.patch("os.getuid", return_value=paths.root_owner[0])
check_user(paths, False)
def test_check_user_no_directory(mocker: MockerFixture) -> None:
def test_check_user_no_directory(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must not fail in case if no directory found
"""
mocker.patch("pathlib.Path.exists", return_value=False)
check_user(Path.cwd(), False)
check_user(repository_paths, False)
def test_check_user_exception(mocker: MockerFixture) -> None:
"""
must raise exception if user differs
"""
cwd = Path.cwd()
mocker.patch("os.getuid", return_value=cwd.stat().st_uid + 1)
paths = RepositoryPaths(Path.cwd(), "x86_64")
mocker.patch("os.getuid", return_value=paths.root_owner[0] + 1)
with pytest.raises(UnsafeRun):
check_user(cwd, False)
check_user(paths, False)
def test_check_unsafe(mocker: MockerFixture) -> None:
"""
must skip check if unsafe flag is set
"""
cwd = Path.cwd()
mocker.patch("os.getuid", return_value=cwd.stat().st_uid + 1)
check_user(cwd, True)
paths = RepositoryPaths(Path.cwd(), "x86_64")
mocker.patch("os.getuid", return_value=paths.root_owner[0] + 1)
check_user(paths, True)
def test_filter_json(package_ahriman: Package) -> None:

View File

@ -1,10 +1,36 @@
from pytest_mock import MockerFixture
from unittest import mock
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from typing import Callable, Tuple
from unittest import mock
from unittest.mock import MagicMock
from ahriman.core.exceptions import InvalidPath
from ahriman.models.package import Package
from ahriman.models.repository_paths import RepositoryPaths
def _get_owner(root: Path, same: bool) -> Callable[[Path], Tuple[int, int]]:
"""
mocker function for owner definition
:param root: root directory
:param same: if True then returns the same as root directory and different otherwise
:return: function which can define ownership
"""
root_owner = (42, 42)
nonroot_owner = (42, 42) if same else (1, 1)
return lambda path: root_owner if path == root else nonroot_owner
def test_root_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must correctly define root directory owner
"""
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.owner", return_value=(42, 142))
assert repository_paths.root_owner == (42, 142)
def test_known_architectures(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths
@ -14,6 +40,18 @@ def test_known_architectures(repository_paths: RepositoryPaths, mocker: MockerFi
iterdir_mock.assert_called_once_with()
def test_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must correctly retrieve owner of the path
"""
stat_mock = MagicMock()
stat_mock.st_uid = 42
stat_mock.st_gid = 142
mocker.patch("pathlib.Path.stat", return_value=stat_mock)
assert RepositoryPaths.owner(repository_paths.root) == (42, 142)
def test_cache_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None:
"""
must return correct path for cache directory
@ -23,6 +61,56 @@ def test_cache_for(repository_paths: RepositoryPaths, package_ahriman: Package)
assert path.parent == repository_paths.cache
def test_chown(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must correctly set owner for the directory
"""
repository_paths.owner = _get_owner(repository_paths.root, same=False)
mocker.patch.object(RepositoryPaths, "root_owner", (42, 42))
chown_mock = mocker.patch("os.chown")
path = repository_paths.root / "path"
repository_paths.chown(path)
chown_mock.assert_called_once_with(path, 42, 42, follow_symlinks=False)
def test_chown_parent(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must correctly set owner for the directory including parents
"""
repository_paths.owner = _get_owner(repository_paths.root, same=False)
mocker.patch.object(RepositoryPaths, "root_owner", (42, 42))
chown_mock = mocker.patch("os.chown")
path = repository_paths.root / "parent" / "path"
repository_paths.chown(path)
chown_mock.assert_has_calls([
mock.call(path, 42, 42, follow_symlinks=False),
mock.call(path.parent, 42, 42, follow_symlinks=False)
])
def test_chown_skip(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must skip ownership set in case if it is same as root
"""
repository_paths.owner = _get_owner(repository_paths.root, same=True)
mocker.patch.object(RepositoryPaths, "root_owner", (42, 42))
chown_mock = mocker.patch("os.chown")
path = repository_paths.root / "path"
repository_paths.chown(path)
chown_mock.assert_not_called()
def test_chown_invalid_path(repository_paths: RepositoryPaths) -> None:
"""
must raise invalid path exception in case if directory outside the root supplied
"""
with pytest.raises(InvalidPath):
repository_paths.chown(repository_paths.root.parent)
def test_manual_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None:
"""
must return correct path for manual directory
@ -76,9 +164,17 @@ def test_tree_create(repository_paths: RepositoryPaths, mocker: MockerFixture) -
for prop in dir(repository_paths)
if not prop.startswith("_")
and not prop.endswith("_for")
and prop not in ("architecture", "known_architectures", "root", "tree_clear", "tree_create")
and prop not in ("architecture",
"chown",
"known_architectures",
"owner",
"root",
"root_owner",
"tree_clear",
"tree_create")
}
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
repository_paths.tree_create()
mkdir_mock.assert_has_calls(
@ -86,3 +182,4 @@ def test_tree_create(repository_paths: RepositoryPaths, mocker: MockerFixture) -
mock.call(mode=0o755, parents=True, exist_ok=True)
for _ in paths
], any_order=True)
chown_mock.assert_has_calls([mock.call(getattr(repository_paths, path)) for path in paths], any_order=True)

View File

@ -25,7 +25,7 @@ makepkg_flags = --skippgpcheck
[repository]
name = aur-clone
root = /var/lib/ahriman
root = ../../../
[sign]
target =