rewrite repository definition logic

This commit is contained in:
Evgenii Alekseev 2023-08-31 03:49:40 +03:00
parent b6a9284b92
commit b7dc4c7ef4
45 changed files with 668 additions and 241 deletions

View File

@ -157,7 +157,8 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("--sort-by", help="sort field by this field. In case if two packages have the same value of "
"the specified field, they will be always sorted by name",
default="name", choices=sorted(handlers.Search.SORT_FIELDS))
parser.set_defaults(handler=handlers.Search, architecture=[""], lock=None, report=False, quiet=True, unsafe=True)
parser.set_defaults(handler=handlers.Search, architecture=[""], lock=None, report=False, repository=[""],
quiet=True, unsafe=True)
return parser
@ -175,8 +176,8 @@ def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="show help message for application or command and exit",
formatter_class=_formatter)
parser.add_argument("command", help="show help message for specific command", nargs="?")
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, quiet=True, unsafe=True,
parser=_parser)
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, repository=[""], quiet=True,
unsafe=True, parser=_parser)
return parser
@ -194,8 +195,8 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
description="list unsafe commands as defined in default args", formatter_class=_formatter)
parser.add_argument("command", help="instead of showing commands, just test command line for unsafe subcommand "
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, quiet=True,
unsafe=True, parser=_parser)
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, repository=[""],
quiet=True, unsafe=True, parser=_parser)
return parser
@ -213,8 +214,8 @@ def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="request AUR for current version and compare with current service version",
formatter_class=_formatter)
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available", action="store_true")
parser.set_defaults(handler=handlers.ServiceUpdates, architecture=[""], lock=None, report=False, quiet=True,
unsafe=True)
parser.set_defaults(handler=handlers.ServiceUpdates, architecture=[""], lock=None, report=False, repository=[""],
quiet=True, unsafe=True)
return parser
@ -230,7 +231,8 @@ def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
parser = root.add_parser("help-version", aliases=["version"], help="application version",
description="print application and its dependencies versions", formatter_class=_formatter)
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, quiet=True, unsafe=True)
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, repository=[""],
quiet=True, unsafe=True)
return parser
@ -381,7 +383,8 @@ def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
"it must end with ()")
parser.add_argument("patch", help="path to file which contains function or variable value. If not set, "
"the value will be read from stdin", type=Path, nargs="?")
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False)
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False,
repository=[""])
return parser
@ -402,7 +405,7 @@ def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("-v", "--variable", help="if set, show only patches for specified PKGBUILD variables",
action="append")
parser.set_defaults(handler=handlers.Patch, action=Action.List, architecture=[""], lock=None, report=False,
unsafe=True)
repository=[""], unsafe=True)
return parser
@ -423,7 +426,8 @@ def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
"to remove only specified PKGBUILD variables. In case if not set, "
"it will remove all patches related to the package",
action="append")
parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture=[""], lock=None, report=False)
parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture=[""], lock=None, report=False,
repository=[""])
return parser
@ -448,7 +452,7 @@ def _set_patch_set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("-t", "--track", help="files which has to be tracked", action="append",
default=["*.diff", "*.patch"])
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False,
variable=None)
repository=[""], variable=None)
return parser
@ -465,7 +469,8 @@ def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser = root.add_parser("repo-backup", help="backup repository data",
description="backup repository settings and database", formatter_class=_formatter)
parser.add_argument("path", help="path of the output archive", type=Path)
parser.set_defaults(handler=handlers.Backup, architecture=[""], lock=None, report=False, unsafe=True)
parser.set_defaults(handler=handlers.Backup, architecture=[""], lock=None, report=False, repository=[""],
unsafe=True)
return parser
@ -644,7 +649,8 @@ def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="restore settings and database", formatter_class=_formatter)
parser.add_argument("path", help="path of the input archive", type=Path)
parser.add_argument("-o", "--output", help="root path of the extracted files", type=Path, default=Path("/"))
parser.set_defaults(handler=handlers.Restore, architecture=[""], lock=None, report=False, unsafe=True)
parser.set_defaults(handler=handlers.Restore, architecture=[""], lock=None, report=False, repository=[""],
unsafe=True)
return parser
@ -681,7 +687,7 @@ def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentPa
description="update repository status on the status page", formatter_class=_formatter)
parser.add_argument("-s", "--status", help="new status",
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, report=False, package=[],
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, package=[], report=False,
quiet=True, unsafe=True)
return parser
@ -865,7 +871,7 @@ def _set_service_key_import_parser(root: SubParserAction) -> argparse.ArgumentPa
formatter_class=_formatter)
parser.add_argument("--key-server", help="key server for key import", default="keyserver.ubuntu.com")
parser.add_argument("key", help="PGP key to import from public server")
parser.set_defaults(handler=handlers.KeyImport, architecture=[""], lock=None, report=False)
parser.set_defaults(handler=handlers.KeyImport, architecture=[""], lock=None, report=False, repository=[""])
return parser
@ -946,7 +952,7 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("-R", "--role", help="user access level",
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
quiet=True)
repository=[""], quiet=True)
return parser
@ -967,7 +973,7 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.add_argument("-R", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False,
quiet=True, unsafe=True)
repository=[""], quiet=True, unsafe=True)
return parser
@ -986,7 +992,7 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
formatter_class=_formatter)
parser.add_argument("username", help="username for web service")
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False,
quiet=True)
repository=[""], quiet=True)
return parser

View File

@ -34,7 +34,7 @@ class Backup(Handler):
backup packages handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -30,7 +30,7 @@ class Dump(Handler):
dump configuration handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -35,7 +35,6 @@ class Handler:
base handler class for command callbacks
Attributes:
ALLOW_AUTO_ARCHITECTURE_RUN(bool): (class attribute) allow defining architecture from existing repositories
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
Examples:
@ -47,7 +46,6 @@ class Handler:
>>> Add.execute(args)
"""
ALLOW_AUTO_ARCHITECTURE_RUN = True
ALLOW_MULTI_ARCHITECTURE_RUN = True
@classmethod
@ -121,32 +119,35 @@ class Handler:
Raises:
MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed
"""
if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None:
# for some parsers (e.g. config) we need to run with specific architecture
# for those cases architecture must be set explicitly
raise MissingArchitectureError(args.command)
configuration = Configuration()
configuration.load(args.configuration)
name = configuration.get("repository", "name", fallback="") # will only be used for legacy mode
# pylint, wtf???
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
if args.architecture: # architecture is specified explicitly
repositories = args.repository or [name] # fallback for legacy mode
return sorted(
set(
RepositoryId(architecture, repository)
for architecture in args.architecture
for repository in repositories
)
# extract repository names first
names = args.repository
if names is None: # try to read file system first
names = RepositoryPaths.known_repositories(root)
if not names: # try to read configuration now
names = [configuration.get("repository", "name")]
# extract architecture names
if (architectures := args.architecture) is not None:
repositories = set(
RepositoryId(architecture, name)
for name in names
for architecture in architectures
)
else: # try to read from file system
repositories = set(
RepositoryId(architecture, name)
for name in names
for architecture in RepositoryPaths.known_architectures(root, name)
)
# wtf???
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
architectures = RepositoryPaths.known_architectures(root, name)
if not architectures: # well we did not find anything
if not repositories:
raise MissingArchitectureError(args.command)
return sorted(architectures)
return sorted(repositories)
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -29,7 +29,7 @@ class Help(Handler):
help handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -30,7 +30,7 @@ class KeyImport(Handler):
key import packages handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -38,6 +38,8 @@ class Patch(Handler):
patch control handler
"""
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
report: bool) -> None:

View File

@ -31,7 +31,7 @@ class Restore(Handler):
restore packages handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -40,7 +40,7 @@ class Search(Handler):
SORT_FIELDS(set[str]): (class attribute) allowed fields to sort the package list
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
SORT_FIELDS = {
field.name
for field in fields(AURPackage)

View File

@ -33,7 +33,7 @@ class ServiceUpdates(Handler):
service updates handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -25,6 +25,7 @@ from pwd import getpwuid
from ahriman.application.application import Application
from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitectureError
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.user import User
@ -40,7 +41,7 @@ class Setup(Handler):
SUDOERS_DIR_PATH(Path): (class attribute) path to sudoers.d includes directory
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
ARCHBUILD_COMMAND_PATH = Path("/usr") / "bin" / "archbuild"
MIRRORLIST_PATH = Path("/etc") / "pacman.d" / "mirrorlist"
@ -58,6 +59,10 @@ class Setup(Handler):
configuration(Configuration): configuration instance
report(bool): force enable or disable reporting
"""
# special check for args to avoid auto definition for setup command
if args.architecture is None or args.repository is None:
raise MissingArchitectureError(args.command)
Setup.configuration_create_ahriman(args, repository_id, configuration)
configuration.reload()

View File

@ -34,7 +34,7 @@ class Shell(Handler):
python shell handler
"""
ALLOW_MULTI_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -35,7 +35,7 @@ class Status(Handler):
package status handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -31,7 +31,7 @@ class StatusUpdate(Handler):
status update handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -32,7 +32,7 @@ class Structure(Handler):
dump repository structure handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -30,7 +30,7 @@ class UnsafeCommands(Handler):
unsafe command help parser
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -35,7 +35,7 @@ class Users(Handler):
user management handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -37,7 +37,7 @@ class Validate(Handler):
configuration validator handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -39,7 +39,7 @@ class Versions(Handler):
PEP423_PACKAGE_NAME(str): (class attribute) special regex for valid PEP423 package name
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
@classmethod

View File

@ -32,7 +32,6 @@ class Web(Handler):
web server handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
@classmethod

View File

@ -165,7 +165,7 @@ class MissingArchitectureError(ValueError):
Args:
command(str): command name which throws exception
"""
ValueError.__init__(self, f"Architecture required for subcommand {command}, but missing")
ValueError.__init__(self, f"Architecture/repository required for subcommand {command}, but missing")
class MultipleArchitecturesError(ValueError):
@ -180,7 +180,7 @@ class MultipleArchitecturesError(ValueError):
Args:
command(str): command name which throws exception
"""
ValueError.__init__(self, f"Multiple architectures are not supported by subcommand {command}")
ValueError.__init__(self, f"Multiple architectures/repositories are not supported by subcommand {command}")
class OptionError(ValueError):

View File

@ -20,8 +20,6 @@
from dataclasses import dataclass
from typing import Any
from ahriman.core.exceptions import InitializeError
@dataclass(frozen=True)
class RepositoryId:
@ -36,16 +34,6 @@ class RepositoryId:
architecture: str
name: str
def __post_init__(self) -> None:
"""
check that name is set
Raises:
InitializeError: in case if name is not set
"""
if not self.name:
raise InitializeError("Repository name is not set")
def __lt__(self, other: Any) -> bool:
"""
comparison operator for sorting

View File

@ -140,31 +140,57 @@ class RepositoryPaths:
"""
return self.owner(self.root)
# TODO see https://github.com/python/mypy/issues/12534, remove type: ignore after release
# pylint: disable=protected-access
@classmethod
def known_architectures(cls, root: Path, name: str) -> set[RepositoryId]:
def known_architectures(cls, root: Path, name: str = "") -> set[str]: # type: ignore[return]
"""
get known architectures
get known architecture names
Args:
root(Path): repository root
name(str): repository name from configuration
name(str, optional): repository name (Default value = "")
Returns:
set[RepositoryId]: list of tuple of repository name and architectures for which tree is created
set[str]: list of repository architectures for which there is created tree
"""
def walk(repository_path: Path, repository_name: str) -> Generator[RepositoryId, None, None]:
for architecture in filter(lambda path: path.is_dir(), repository_path.iterdir()):
yield RepositoryId(architecture.name, repository_name)
def walk(repository_dir: Path) -> Generator[str, None, None]:
for architecture in filter(lambda path: path.is_dir(), repository_dir.iterdir()):
yield architecture.name
def walk_root(paths: RepositoryPaths) -> Generator[RepositoryId, None, None]:
# pylint: disable=protected-access
instance = cls(root, RepositoryId("", ""))
match (instance._repository_root / name):
case full_tree if full_tree.is_dir():
return set(walk(full_tree)) # actually works for legacy too in case if name is set to empty string
case _ if instance._repository_root.is_dir():
return set(walk(instance._repository_root)) # legacy only tree
case _:
return set() # no tree detected at all
# pylint: disable=protected-access
@classmethod
def known_repositories(cls, root: Path) -> set[str]:
"""
get known repository names
Args:
root(Path): repository root
Returns:
set[str]: list of repository names for which there is created tree. Returns empty set in case if repository
is loaded in legacy mode
"""
# simply walk through the root. In case if there are subdirectories, emit the name
def walk(paths: RepositoryPaths) -> Generator[str, None, None]:
for repository in filter(lambda path: path.is_dir(), paths._repository_root.iterdir()):
print(repository)
yield from walk(repository, repository.name)
if any(path.is_dir() for path in repository.iterdir()):
yield repository.name
instance = cls(root, RepositoryId("", root.name)) # suppress initialization error
# try to get list per repository first and then fallback to old schema if nothing found
return set(walk_root(instance)) or set(walk(instance._repository_root, name))
instance = cls(root, RepositoryId("", ""))
if not instance._repository_root.is_dir():
return set() # no tree created
return set(walk(instance))
@staticmethod
def owner(path: Path) -> tuple[int, int]:

View File

@ -117,14 +117,68 @@ def test_run(args: argparse.Namespace, configuration: Configuration) -> None:
def test_repositories_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must generate list of available architectures
must generate list of available repositories based on flags
"""
args.architecture = ["arch"]
args.configuration = configuration.path
_, repository_id = configuration.check_loaded()
args.repository = ["repo"]
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
Handler.repositories_extract(args)
known_architectures_mock.assert_called_once_with(configuration.getpath("repository", "root"), repository_id.name)
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_not_called()
def test_repositories_extract_repository(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must generate list of available repositories based on flags and tree
"""
args.architecture = ["arch"]
args.configuration = configuration.path
args.repository = None
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
return_value={"repo"})
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
def test_repositories_extract_repository_legacy(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must generate list of available repositories based on flags and tree
"""
args.architecture = ["arch"]
args.configuration = configuration.path
args.repository = None
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
return_value={"repo"})
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_not_called()
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
def test_repositories_extract_architecture(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must read repository name from config
"""
args.architecture = None
args.configuration = configuration.path
args.repository = ["repo"]
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures",
return_value={"arch"})
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
known_architectures_mock.assert_called_once_with(configuration.repository_paths.root, "repo")
known_repositories_mock.assert_not_called()
def test_repositories_extract_empty(args: argparse.Namespace, configuration: Configuration,
@ -133,52 +187,16 @@ def test_repositories_extract_empty(args: argparse.Namespace, configuration: Con
must raise exception if no available architectures found
"""
args.command = "config"
args.architecture = None
args.configuration = configuration.path
args.repository = None
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures", return_value=set())
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories", return_value=set())
with pytest.raises(MissingArchitectureError):
Handler.repositories_extract(args)
def test_repositories_extract_exception(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise exception on missing architectures
"""
args.command = "config"
mocker.patch.object(Handler, "ALLOW_AUTO_ARCHITECTURE_RUN", False)
with pytest.raises(MissingArchitectureError):
Handler.repositories_extract(args)
def test_repositories_extract_specified(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must return architecture list if it has been specified
"""
args.configuration = configuration.path
args.architecture = ["i686", "x86_64"]
args.repository = []
_, repository_id = configuration.check_loaded()
ids = [RepositoryId(architecture, repository_id.name) for architecture in args.architecture]
assert Handler.repositories_extract(args) == sorted(set(ids))
def test_repositories_extract_specified_with_repository(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must return architecture list if it has been specified together with repositories
"""
args.configuration = configuration.path
args.architecture = ["i686", "x86_64"]
args.repository = ["repo1", "repo2"]
ids = [
RepositoryId(architecture, name)
for architecture in args.architecture
for name in args.repository
]
assert Handler.repositories_extract(args) == sorted(set(ids))
def test_check_if_empty() -> None:
"""
must raise exception in case if predicate is True and enabled

View File

@ -56,8 +56,8 @@ def test_get_paths(configuration: Configuration, mocker: MockerFixture) -> None:
assert all(path.exists() for path in paths if path.name not in (".gnupg", "cache"))
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Backup.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Backup.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -35,8 +35,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
print_mock.assert_called()
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Dump.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Dump.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -47,8 +47,8 @@ def test_run_command(args: argparse.Namespace, configuration: Configuration, moc
parse_mock.assert_called_once_with(["aur-search", "--help"])
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Help.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Help.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -36,8 +36,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock.assert_called_once_with(args.key_server, args.key)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not KeyImport.ALLOW_AUTO_ARCHITECTURE_RUN
assert not KeyImport.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -190,3 +190,10 @@ def test_patch_set_remove(application: Application, package_ahriman: Package, mo
remove_mock = mocker.patch("ahriman.core.database.SQLite.patches_remove")
Patch.patch_set_remove(application, package_ahriman.base, ["version"])
remove_mock.assert_called_once_with(package_ahriman.base, ["version"])
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Patch.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -37,8 +37,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
extract_mock.extractall.assert_called_once_with(path=args.output)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Restore.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Restore.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -128,11 +128,11 @@ def test_sort_exception(aur_package_ahriman: AURPackage) -> None:
Search.sort([aur_package_ahriman], "random_field")
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Search.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Search.ALLOW_MULTI_ARCHITECTURE_RUN
def test_sort_fields(aur_package_ahriman: AURPackage) -> None:

View File

@ -58,3 +58,10 @@ def test_run_skip(args: argparse.Namespace, configuration: Configuration, reposi
ServiceUpdates.run(args, repository_id, configuration, report=False)
application_mock.assert_not_called()
check_mock.assert_not_called()
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not ServiceUpdates.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -8,6 +8,7 @@ from unittest.mock import call as MockCall
from ahriman.application.handlers import Setup
from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitectureError
from ahriman.core.repository import Repository
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths
@ -24,6 +25,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.architecture = ["x86_64"]
args.build_as_user = "ahriman"
args.from_configuration = Path("/usr/share/devtools/pacman.conf.d/extra.conf")
args.generate_salt = True
@ -31,6 +33,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
args.mirror = "mirror"
args.multilib = True
args.packager = "John Doe <john@doe.com>"
args.repository = ["aur-clone"]
args.server = None
args.sign_key = "key"
args.sign_target = [SignSettings.Packages]
@ -64,6 +67,25 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
init_mock.assert_called_once_with()
def test_run_no_architecture_or_repository(configuration: Configuration) -> None:
"""
must raise MissingArchitectureError if either architecture or repository are not supplied
"""
_, repository_id = configuration.check_loaded()
args = argparse.Namespace(architecture=None, command="service-setup", repository=None)
with pytest.raises(MissingArchitectureError):
Setup.run(args, repository_id, configuration, report=False)
args = argparse.Namespace(architecture=[repository_id.architecture], command="service-setup", repository=None)
with pytest.raises(MissingArchitectureError):
Setup.run(args, repository_id, configuration, report=False)
args = argparse.Namespace(architecture=None, command="service-setup", repository=[repository_id.name])
with pytest.raises(MissingArchitectureError):
Setup.run(args, repository_id, configuration, report=False)
def test_run_with_server(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None:
"""
@ -251,8 +273,8 @@ def test_executable_create(configuration: Configuration, repository_paths: Repos
unlink_mock.assert_called_once_with(missing_ok=True)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Setup.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Setup.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -69,3 +69,10 @@ def test_run_verbose(args: argparse.Namespace, configuration: Configuration, rep
application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int))
read_mock.assert_called_once_with(encoding="utf8")
print_mock.assert_called_once_with(verbose=False)
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Shell.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -133,8 +133,8 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Status.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Status.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -86,8 +86,8 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not StatusUpdate.ALLOW_AUTO_ARCHITECTURE_RUN
assert not StatusUpdate.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -46,8 +46,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
])
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Structure.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Structure.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -83,8 +83,8 @@ def test_get_unsafe_commands() -> None:
assert subparser.choices[command].get_default("unsafe")
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not UnsafeCommands.ALLOW_AUTO_ARCHITECTURE_RUN
assert not UnsafeCommands.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -175,8 +175,8 @@ def test_user_create_getpass_exception(args: argparse.Namespace, mocker: MockerF
Users.user_create(args)
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Users.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Users.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -115,8 +115,8 @@ def test_schema_merge() -> None:
assert key in merged["gitremote"]["schema"]
def test_disallow_auto_architecture_run() -> None:
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Validate.ALLOW_AUTO_ARCHITECTURE_RUN
assert not Validate.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -37,3 +37,10 @@ def test_package_dependencies_missing() -> None:
assert packages
assert packages.get("pyalpm") is not None
assert packages.get("Sphinx") is None
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run
"""
assert not Versions.ALLOW_MULTI_ARCHITECTURE_RUN

View File

@ -116,13 +116,6 @@ def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration:
]
def test_disallow_auto_architecture_run() -> None:
"""
must not allow auto architecture run
"""
assert not Web.ALLOW_AUTO_ARCHITECTURE_RUN
def test_disallow_multi_architecture_run() -> None:
"""
must not allow multi architecture run

View File

@ -18,16 +18,16 @@ def test_parser(parser: argparse.ArgumentParser) -> None:
"""
must parse valid command line
"""
parser.parse_args(["-a", "x86_64", "service-config"])
parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config"])
def test_parser_option_configuration(parser: argparse.ArgumentParser) -> None:
"""
must convert configuration option to Path instance
"""
args = parser.parse_args(["-a", "x86_64", "service-config"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config"])
assert isinstance(args.configuration, Path)
args = parser.parse_args(["-a", "x86_64", "-c", "ahriman.ini", "service-config"])
args = parser.parse_args(["-a", "x86_64", "-c", "ahriman.ini", "-r", "repo", "service-config"])
assert isinstance(args.configuration, Path)
@ -93,12 +93,13 @@ def test_parser_option_repository_multiple(parser: argparse.ArgumentParser) -> N
def test_subparsers_aur_search(parser: argparse.ArgumentParser) -> None:
"""
aur-search command must imply architecture list, lock, report, quiet and unsafe
aur-search command must imply architecture list, lock, report, repository, quiet and unsafe
"""
args = parser.parse_args(["aur-search", "ahriman"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
assert args.unsafe
@ -111,14 +112,23 @@ def test_subparsers_aur_search_option_architecture(parser: argparse.ArgumentPars
assert args.architecture == [""]
def test_subparsers_aur_search_option_repository(parser: argparse.ArgumentParser) -> None:
"""
aur-search command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "aur-search", "ahriman"])
assert args.repository == [""]
def test_subparsers_help(parser: argparse.ArgumentParser) -> None:
"""
help command must imply architecture list, lock, report, quiet, unsafe and parser
help command must imply architecture list, lock, report, repository, quiet, unsafe and parser
"""
args = parser.parse_args(["help"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
assert args.unsafe
assert args.parser is not None and args.parser()
@ -132,14 +142,23 @@ def test_subparsers_help_option_architecture(parser: argparse.ArgumentParser) ->
assert args.architecture == [""]
def test_subparsers_help_option_repository(parser: argparse.ArgumentParser) -> None:
"""
help command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "help"])
assert args.repository == [""]
def test_subparsers_help_commands_unsafe(parser: argparse.ArgumentParser) -> None:
"""
help-commands-unsafe command must imply architecture list, lock, report, quiet, unsafe and parser
help-commands-unsafe command must imply architecture list, lock, report, repository, quiet, unsafe and parser
"""
args = parser.parse_args(["help-commands-unsafe"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
assert args.unsafe
assert args.parser is not None and args.parser()
@ -153,14 +172,23 @@ def test_subparsers_help_commands_unsafe_option_architecture(parser: argparse.Ar
assert args.architecture == [""]
def test_subparsers_help_commands_unsafe_option_repository(parser: argparse.ArgumentParser) -> None:
"""
help-commands-unsafe command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "help-commands-unsafe"])
assert args.repository == [""]
def test_subparsers_help_updates(parser: argparse.ArgumentParser) -> None:
"""
help-updates command must imply architecture list, lock, report, quiet and unsafe
help-updates command must imply architecture list, lock, report, repository, quiet and unsafe
"""
args = parser.parse_args(["help-updates"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
assert args.unsafe
@ -173,14 +201,23 @@ def test_subparsers_help_updates_option_architecture(parser: argparse.ArgumentPa
assert args.architecture == [""]
def test_subparsers_help_updates_option_repository(parser: argparse.ArgumentParser) -> None:
"""
help-updates command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "help-updates"])
assert args.repository == [""]
def test_subparsers_help_version(parser: argparse.ArgumentParser) -> None:
"""
help-version command must imply architecture, lock, report, quiet and unsafe
help-version command must imply architecture, lock, report, repository, quiet and unsafe
"""
args = parser.parse_args(["help-version"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
assert args.unsafe
@ -193,6 +230,14 @@ def test_subparsers_help_version_option_architecture(parser: argparse.ArgumentPa
assert args.architecture == [""]
def test_subparsers_help_version_option_repository(parser: argparse.ArgumentParser) -> None:
"""
help-version command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "help-version"])
assert args.repository == [""]
def test_subparsers_package_add_option_architecture(parser: argparse.ArgumentParser) -> None:
"""
package-add command must correctly parse architecture list
@ -203,6 +248,16 @@ def test_subparsers_package_add_option_architecture(parser: argparse.ArgumentPar
assert args.architecture == ["x86_64"]
def test_subparsers_package_add_option_repository(parser: argparse.ArgumentParser) -> None:
"""
package-add command must correctly parse repository list
"""
args = parser.parse_args(["package-add", "ahriman"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "package-add", "ahriman"])
assert args.repository == ["repo"]
def test_subparsers_package_add_option_refresh(parser: argparse.ArgumentParser) -> None:
"""
package-add command must count refresh options
@ -225,14 +280,25 @@ def test_subparsers_package_remove_option_architecture(parser: argparse.Argument
assert args.architecture == ["x86_64"]
def test_subparsers_package_remove_option_repository(parser: argparse.ArgumentParser) -> None:
"""
package-remove command must correctly parse repository list
"""
args = parser.parse_args(["package-remove", "ahriman"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "package-remove", "ahriman"])
assert args.repository == ["repo"]
def test_subparsers_package_status(parser: argparse.ArgumentParser) -> None:
"""
package-status command must imply lock, report, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "package-status"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status"])
assert args.architecture == ["x86_64"]
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert args.quiet
assert args.unsafe
@ -241,11 +307,12 @@ def test_subparsers_package_status_remove(parser: argparse.ArgumentParser) -> No
"""
package-status-remove command must imply action, lock, report, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "package-status-remove", "ahriman"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-remove", "ahriman"])
assert args.architecture == ["x86_64"]
assert args.action == Action.Remove
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert args.quiet
assert args.unsafe
@ -254,11 +321,12 @@ def test_subparsers_package_status_update(parser: argparse.ArgumentParser) -> No
"""
package-status-update command must imply action, lock, report, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "package-status-update"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
assert args.architecture == ["x86_64"]
assert args.action == Action.Update
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert args.quiet
assert args.unsafe
@ -267,21 +335,22 @@ def test_subparsers_package_status_update_option_status(parser: argparse.Argumen
"""
package-status-update command must convert status option to buildstatusenum instance
"""
args = parser.parse_args(["-a", "x86_64", "package-status-update"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
assert isinstance(args.status, BuildStatusEnum)
args = parser.parse_args(["-a", "x86_64", "package-status-update", "--status", "failed"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update", "--status", "failed"])
assert isinstance(args.status, BuildStatusEnum)
def test_subparsers_patch_add(parser: argparse.ArgumentParser) -> None:
"""
patch-add command must imply action, architecture list, lock and report
patch-add command must imply action, architecture list, lock, report and repository
"""
args = parser.parse_args(["patch-add", "ahriman", "version"])
assert args.action == Action.Update
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
def test_subparsers_patch_add_option_architecture(parser: argparse.ArgumentParser) -> None:
@ -292,15 +361,24 @@ def test_subparsers_patch_add_option_architecture(parser: argparse.ArgumentParse
assert args.architecture == [""]
def test_subparsers_patch_add_option_repository(parser: argparse.ArgumentParser) -> None:
"""
patch-add command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "patch-add", "ahriman", "version"])
assert args.repository == [""]
def test_subparsers_patch_list(parser: argparse.ArgumentParser) -> None:
"""
patch-list command must imply action, architecture list, lock, report and unsafe
patch-list command must imply action, architecture list, lock, report, repository and unsafe
"""
args = parser.parse_args(["patch-list", "ahriman"])
assert args.action == Action.List
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.unsafe
@ -312,6 +390,14 @@ def test_subparsers_patch_list_option_architecture(parser: argparse.ArgumentPars
assert args.architecture == [""]
def test_subparsers_patch_list_option_repository(parser: argparse.ArgumentParser) -> None:
"""
patch-list command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "patch-list", "ahriman"])
assert args.repository == [""]
def test_subparsers_patch_list_option_variable_empty(parser: argparse.ArgumentParser) -> None:
"""
patch-list command must accept empty variable list as None
@ -330,13 +416,14 @@ def test_subparsers_patch_list_option_variable_multiple(parser: argparse.Argumen
def test_subparsers_patch_remove(parser: argparse.ArgumentParser) -> None:
"""
patch-remove command must imply action, architecture list, lock and report
patch-remove command must imply action, architecture list, lock, report and repository
"""
args = parser.parse_args(["patch-remove", "ahriman"])
assert args.action == Action.Remove
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
def test_subparsers_patch_remove_option_architecture(parser: argparse.ArgumentParser) -> None:
@ -347,6 +434,14 @@ def test_subparsers_patch_remove_option_architecture(parser: argparse.ArgumentPa
assert args.architecture == [""]
def test_subparsers_patch_remove_option_repository(parser: argparse.ArgumentParser) -> None:
"""
patch-remove command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "patch-remove", "ahriman"])
assert args.repository == [""]
def test_subparsers_patch_remove_option_variable_empty(parser: argparse.ArgumentParser) -> None:
"""
patch-remove command must accept empty variable list as None
@ -365,13 +460,14 @@ def test_subparsers_patch_remove_option_variable_multiple(parser: argparse.Argum
def test_subparsers_patch_set_add(parser: argparse.ArgumentParser) -> None:
"""
patch-set-add command must imply action, architecture list, lock, report and variable
patch-set-add command must imply action, architecture list, lock, report, repository and variable
"""
args = parser.parse_args(["patch-set-add", "ahriman"])
assert args.action == Action.Update
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.variable is None
@ -391,6 +487,14 @@ def test_subparsers_patch_set_add_option_package(parser: argparse.ArgumentParser
assert isinstance(args.package, Path)
def test_subparsers_patch_set_add_option_repository(parser: argparse.ArgumentParser) -> None:
"""
patch-set-add command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "patch-set-add", "ahriman"])
assert args.repository == [""]
def test_subparsers_patch_set_add_option_track(parser: argparse.ArgumentParser) -> None:
"""
patch-set-add command must correctly parse track files patterns
@ -401,12 +505,13 @@ def test_subparsers_patch_set_add_option_track(parser: argparse.ArgumentParser)
def test_subparsers_repo_backup(parser: argparse.ArgumentParser) -> None:
"""
repo-backup command must imply architecture list, lock, report and unsafe
repo-backup command must imply architecture list, lock, report, repository and unsafe
"""
args = parser.parse_args(["repo-backup", "output.zip"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.unsafe
@ -418,6 +523,14 @@ def test_subparsers_repo_backup_option_architecture(parser: argparse.ArgumentPar
assert args.architecture == [""]
def test_subparsers_repo_backup_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-backup command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "repo-backup", "output.zip"])
assert args.repository == [""]
def test_subparsers_repo_check(parser: argparse.ArgumentParser) -> None:
"""
repo-check command must imply dependencies, dry-run, aur, manual and username
@ -440,6 +553,16 @@ def test_subparsers_repo_check_option_architecture(parser: argparse.ArgumentPars
assert args.architecture == ["x86_64"]
def test_subparsers_repo_check_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-check command must correctly parse architecture list
"""
args = parser.parse_args(["repo-check"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-check"])
assert args.repository == ["repo"]
def test_subparsers_repo_check_option_refresh(parser: argparse.ArgumentParser) -> None:
"""
repo-check command must count refresh options
@ -470,6 +593,16 @@ def test_subparsers_repo_create_keyring_option_architecture(parser: argparse.Arg
assert args.architecture == ["x86_64"]
def test_subparsers_repo_create_keyring_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-create-keyring command must correctly parse repository list
"""
args = parser.parse_args(["repo-create-keyring"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-create-keyring"])
assert args.repository == ["repo"]
def test_subparsers_repo_create_mirrorlist(parser: argparse.ArgumentParser) -> None:
"""
repo-create-mirrorlist command must imply trigger
@ -488,6 +621,16 @@ def test_subparsers_repo_create_mirrorlist_option_architecture(parser: argparse.
assert args.architecture == ["x86_64"]
def test_subparsers_repo_create_mirrorlist_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-create-mirrorlist command must correctly parse repository list
"""
args = parser.parse_args(["repo-create-mirrorlist"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-create-mirrorlist"])
assert args.repository == ["repo"]
def test_subparsers_repo_daemon(parser: argparse.ArgumentParser) -> None:
"""
repo-daemon command must imply dry run, exit code and package
@ -530,6 +673,16 @@ def test_subparsers_repo_rebuild_option_architecture(parser: argparse.ArgumentPa
assert args.architecture == ["x86_64"]
def test_subparsers_repo_rebuild_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-rebuild command must correctly parse repository list
"""
args = parser.parse_args(["repo-rebuild"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-rebuild"])
assert args.repository == ["repo"]
def test_subparsers_repo_rebuild_option_depends_on_empty(parser: argparse.ArgumentParser) -> None:
"""
repo-rebuild command must accept empty depends-on list as None
@ -550,7 +703,7 @@ def test_subparsers_repo_rebuild_option_status(parser: argparse.ArgumentParser)
"""
repo-rebuild command must convert status option to BuildStatusEnum instance
"""
args = parser.parse_args(["-a", "x86_64", "repo-rebuild", "--status", "failed"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "repo-rebuild", "--status", "failed"])
assert isinstance(args.status, BuildStatusEnum)
@ -564,6 +717,16 @@ def test_subparsers_repo_remove_unknown_option_architecture(parser: argparse.Arg
assert args.architecture == ["x86_64"]
def test_subparsers_repo_remove_unknown_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-remove-unknown command must correctly parse repository list
"""
args = parser.parse_args(["repo-remove-unknown"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-remove-unknown"])
assert args.repository == ["repo"]
def test_subparsers_repo_report(parser: argparse.ArgumentParser) -> None:
"""
repo-report command must imply trigger
@ -582,14 +745,25 @@ def test_subparsers_repo_report_option_architecture(parser: argparse.ArgumentPar
assert args.architecture == ["x86_64"]
def test_subparsers_repo_report_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-report command must correctly parse repository list
"""
args = parser.parse_args(["repo-report"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-report"])
assert args.repository == ["repo"]
def test_subparsers_repo_restore(parser: argparse.ArgumentParser) -> None:
"""
repo-restore command must imply architecture list, lock, report and unsafe
repo-restore command must imply architecture list, lock, report, repository and unsafe
"""
args = parser.parse_args(["repo-restore", "output.zip"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.unsafe
@ -601,6 +775,14 @@ def test_subparsers_repo_restore_option_architecture(parser: argparse.ArgumentPa
assert args.architecture == [""]
def test_subparsers_repo_restore_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-restore command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "repo-restore", "output.zip"])
assert args.repository == [""]
def test_subparsers_repo_sign_option_architecture(parser: argparse.ArgumentParser) -> None:
"""
repo-sign command must correctly parse architecture list
@ -611,15 +793,26 @@ def test_subparsers_repo_sign_option_architecture(parser: argparse.ArgumentParse
assert args.architecture == ["x86_64"]
def test_subparsers_repo_sign_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-sign command must correctly parse repository list
"""
args = parser.parse_args(["repo-sign"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-sign"])
assert args.repository == ["repo"]
def test_subparsers_repo_status_update(parser: argparse.ArgumentParser) -> None:
"""
re[p-status-update command must imply action, lock, report, package, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "package-status-update"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
assert args.architecture == ["x86_64"]
assert args.action == Action.Update
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert not args.package
assert args.quiet
assert args.unsafe
@ -629,9 +822,9 @@ def test_subparsers_repo_status_update_option_status(parser: argparse.ArgumentPa
"""
repo-status-update command must convert status option to BuildStatusEnum instance
"""
args = parser.parse_args(["-a", "x86_64", "repo-status-update"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "repo-status-update"])
assert isinstance(args.status, BuildStatusEnum)
args = parser.parse_args(["-a", "x86_64", "repo-status-update", "--status", "failed"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "repo-status-update", "--status", "failed"])
assert isinstance(args.status, BuildStatusEnum)
@ -653,6 +846,16 @@ def test_subparsers_repo_sync_option_architecture(parser: argparse.ArgumentParse
assert args.architecture == ["x86_64"]
def test_subparsers_repo_sync_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-sync command must correctly parse repository list
"""
args = parser.parse_args(["repo-sync"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-sync"])
assert args.repository == ["repo"]
def test_subparsers_repo_tree(parser: argparse.ArgumentParser) -> None:
"""
repo-tree command must imply lock, report, quiet and unsafe
@ -674,6 +877,16 @@ def test_subparsers_repo_tree_option_architecture(parser: argparse.ArgumentParse
assert args.architecture == ["x86_64"]
def test_subparsers_repo_tree_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-tree command must correctly parse repository list
"""
args = parser.parse_args(["repo-tree"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-tree"])
assert args.repository == ["repo"]
def test_subparsers_repo_tree_option_partitions(parser: argparse.ArgumentParser) -> None:
"""
must convert partitions option to int instance
@ -694,6 +907,16 @@ def test_subparsers_repo_triggers_option_architecture(parser: argparse.ArgumentP
assert args.architecture == ["x86_64"]
def test_subparsers_repo_triggers_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-triggers command must correctly parse repository list
"""
args = parser.parse_args(["repo-triggers"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-triggers"])
assert args.repository == ["repo"]
def test_subparsers_repo_update_option_architecture(parser: argparse.ArgumentParser) -> None:
"""
repo-update command must correctly parse architecture list
@ -704,6 +927,16 @@ def test_subparsers_repo_update_option_architecture(parser: argparse.ArgumentPar
assert args.architecture == ["x86_64"]
def test_subparsers_repo_update_option_repository(parser: argparse.ArgumentParser) -> None:
"""
repo-update command must correctly parse repository list
"""
args = parser.parse_args(["repo-update"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "repo-update"])
assert args.repository == ["repo"]
def test_subparsers_repo_update_option_refresh(parser: argparse.ArgumentParser) -> None:
"""
repo-update command must count refresh options
@ -735,14 +968,25 @@ def test_subparsers_service_clean_option_architecture(parser: argparse.ArgumentP
assert args.architecture == ["x86_64"]
def test_subparsers_service_clean_option_repository(parser: argparse.ArgumentParser) -> None:
"""
service-clean command must correctly parse repository list
"""
args = parser.parse_args(["service-clean"])
assert args.repository is None
args = parser.parse_args(["-r", "repo", "service-clean"])
assert args.repository == ["repo"]
def test_subparsers_service_config(parser: argparse.ArgumentParser) -> None:
"""
service-config command must imply lock, report, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "service-config"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config"])
assert args.architecture == ["x86_64"]
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert args.quiet
assert args.unsafe
@ -751,22 +995,24 @@ def test_subparsers_service_config_validate(parser: argparse.ArgumentParser) ->
"""
service-config-validate command must imply lock, report, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "service-config-validate"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config-validate"])
assert args.architecture == ["x86_64"]
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert args.quiet
assert args.unsafe
def test_subparsers_service_key_import(parser: argparse.ArgumentParser) -> None:
"""
service-key-import command must imply architecture list, lock and report
service-key-import command must imply architecture list, lock, report and repository
"""
args = parser.parse_args(["service-key-import", "key"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
def test_subparsers_service_key_import_option_architecture(parser: argparse.ArgumentParser) -> None:
@ -777,14 +1023,23 @@ def test_subparsers_service_key_import_option_architecture(parser: argparse.Argu
assert args.architecture == [""]
def test_subparsers_service_key_import_option_repository(parser: argparse.ArgumentParser) -> None:
"""
service-key-import command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "service-key-import", "key"])
assert args.repository == [""]
def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None:
"""
service-setup command must imply lock, report, quiet and unsafe
"""
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>"])
assert args.architecture == ["x86_64"]
assert args.lock is None
assert not args.report
assert args.repository == ["repo"]
assert args.quiet
assert args.unsafe
@ -793,9 +1048,9 @@ def test_subparsers_service_setup_option_from_configuration(parser: argparse.Arg
"""
service-setup command must convert from-configuration option to path instance
"""
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>"])
assert isinstance(args.from_configuration, Path)
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>",
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>",
"--from-configuration", "path"])
assert isinstance(args.from_configuration, Path)
@ -804,7 +1059,7 @@ def test_subparsers_service_setup_option_sign_target(parser: argparse.ArgumentPa
"""
service-setup command must convert sign-target option to SignSettings instance
"""
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>",
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>",
"--sign-target", "packages"])
assert args.sign_target
assert all(isinstance(target, SignSettings) for target in args.sign_target)
@ -814,7 +1069,7 @@ def test_subparsers_service_setup_option_sign_target_empty(parser: argparse.Argu
"""
service-setup command must accept empty sign-target list as None
"""
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>"])
assert args.sign_target is None
@ -822,7 +1077,7 @@ def test_subparsers_service_setup_option_sign_target_multiple(parser: argparse.A
"""
service-setup command must accept multiple sign-target
"""
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>",
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>",
"--sign-target", "packages", "--sign-target", "repository"])
assert args.sign_target == [SignSettings.Packages, SignSettings.Repository]
@ -838,13 +1093,14 @@ def test_subparsers_service_shell(parser: argparse.ArgumentParser) -> None:
def test_subparsers_user_add(parser: argparse.ArgumentParser) -> None:
"""
user-add command must imply action, architecture, lock, report and quiet
user-add command must imply action, architecture, lock, report, repository and quiet
"""
args = parser.parse_args(["user-add", "username"])
assert args.action == Action.Update
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
@ -856,6 +1112,14 @@ def test_subparsers_user_add_option_architecture(parser: argparse.ArgumentParser
assert args.architecture == [""]
def test_subparsers_user_add_option_repository(parser: argparse.ArgumentParser) -> None:
"""
user-add command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "user-add", "username"])
assert args.repository == [""]
def test_subparsers_user_add_option_role(parser: argparse.ArgumentParser) -> None:
"""
user-add command must convert role option to UserAccess instance
@ -868,13 +1132,14 @@ def test_subparsers_user_add_option_role(parser: argparse.ArgumentParser) -> Non
def test_subparsers_user_list(parser: argparse.ArgumentParser) -> None:
"""
user-list command must imply action, architecture, lock, report, quiet and unsafe
user-list command must imply action, architecture, lock, report, repository, quiet and unsafe
"""
args = parser.parse_args(["user-list"])
assert args.action == Action.List
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
assert args.unsafe
@ -887,6 +1152,14 @@ def test_subparsers_user_list_option_architecture(parser: argparse.ArgumentParse
assert args.architecture == [""]
def test_subparsers_user_list_option_repository(parser: argparse.ArgumentParser) -> None:
"""
user-list command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "user-list"])
assert args.repository == [""]
def test_subparsers_user_list_option_role(parser: argparse.ArgumentParser) -> None:
"""
user-list command must convert role option to UserAccess instance
@ -897,13 +1170,14 @@ def test_subparsers_user_list_option_role(parser: argparse.ArgumentParser) -> No
def test_subparsers_user_remove(parser: argparse.ArgumentParser) -> None:
"""
user-remove command must imply action, architecture, lock, report and quiet
user-remove command must imply action, architecture, lock, report, repository and quiet
"""
args = parser.parse_args(["user-remove", "username"])
assert args.action == Action.Remove
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.repository == [""]
assert args.quiet
@ -915,13 +1189,22 @@ def test_subparsers_user_remove_option_architecture(parser: argparse.ArgumentPar
assert args.architecture == [""]
def test_subparsers_user_remove_option_repository(parser: argparse.ArgumentParser) -> None:
"""
user-remove command must correctly parse repository list
"""
args = parser.parse_args(["-r", "repo", "user-remove", "username"])
assert args.repository == [""]
def test_subparsers_web(parser: argparse.ArgumentParser) -> None:
"""
web command must imply report and parser
"""
args = parser.parse_args(["-a", "x86_64", "web"])
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "web"])
assert args.architecture == ["x86_64"]
assert not args.report
assert args.repository == ["repo"]
assert args.parser is not None and args.parser()

View File

@ -1,19 +1,8 @@
import pytest
from ahriman.core.exceptions import InitializeError
from ahriman.models.repository_id import RepositoryId
def test_post_init() -> None:
"""
must raise InitializeError if name is empty
"""
RepositoryId("x86_64", "aur-clone")
with pytest.raises(InitializeError):
RepositoryId("x86_64", "")
def test_lt() -> None:
"""
must correctly compare instances

View File

@ -51,61 +51,127 @@ def test_known_architectures(repository_paths: RepositoryPaths, mocker: MockerFi
"""
must list available directory paths /repository/repo/arch
"""
def iterdir(root: Path) -> list[Path]:
if root == repository_paths._repository_root:
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, return_value=True)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root, repository_paths.repository_id.name) == {
"i686",
"x86_64",
}
iterdir_mock.assert_called_once_with(repository_paths._repository_root / repository_paths.repository_id.name)
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root / repository_paths.repository_id.name),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
def test_known_architectures_legacy(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths /repository/arch
"""
def is_dir(path: Path) -> bool:
return path.name != repository_paths.repository_id.name
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=is_dir)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root, repository_paths.repository_id.name) == {
"i686",
"x86_64",
}
iterdir_mock.assert_called_once_with(repository_paths._repository_root)
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root / repository_paths.repository_id.name),
MockCall(repository_paths._repository_root),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
def test_known_architectures_legacy_backward(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths /repository/arch in backward compatibility mode
"""
def is_dir(path: Path) -> bool:
return path.name != repository_paths.repository_id.name
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=is_dir)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root) == {"i686", "x86_64"}
iterdir_mock.assert_called_once_with(repository_paths._repository_root)
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
def test_known_architectures_empty(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must return empty architectures if tree is not available
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
iterdir_mock = mocker.patch("pathlib.Path.iterdir")
# new style
assert not repository_paths.known_architectures(repository_paths.root, repository_paths.repository_id.name)
# legacy mode
assert not repository_paths.known_architectures(repository_paths.root)
iterdir_mock.assert_not_called()
def test_known_repositories(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must list available directory paths /repository/repo
"""
def iterdir(path: Path) -> list[Path]:
if path == repository_paths._repository_root:
return [Path("repo1"), Path("repo2")]
if root == Path("repo1"):
return [Path("i686"), Path("x86_64")]
return [Path("x86_64")]
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, return_value=True)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, side_effect=iterdir)
assert repository_paths.known_architectures(repository_paths.root, "") == {
RepositoryId("i686", "repo1"),
RepositoryId("x86_64", "repo1"),
RepositoryId("x86_64", "repo2"),
}
assert repository_paths.known_repositories(repository_paths.root) == {"repo1", "repo2"}
iterdir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("repo1")),
MockCall(Path("repo2")),
])
is_dir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("repo1")),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
MockCall(Path("repo2")),
MockCall(Path("x86_64")),
])
def test_known_architectures_legacy(repository_id: RepositoryId, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
def test_known_repositories_legacy(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must correctly define legacy tree /repository/arch
must return empty repository list for legacy tree
"""
def iterdir(root: Path) -> list[Path]:
if root == repository_paths._repository_root:
return [Path("i686"), Path("x86_64")]
return []
def is_dir(path: Path) -> bool:
return path == repository_paths._repository_root
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, return_value=True)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, side_effect=iterdir)
mocker.patch("pathlib.Path.is_dir", autospec=True, side_effect=is_dir)
iterdir_mock = mocker.patch("pathlib.Path.iterdir", autospec=True, return_value=[Path("i686"), Path("x86_64")])
assert repository_paths.known_architectures(repository_paths.root, repository_id.name) == {
RepositoryId("i686", repository_id.name),
RepositoryId("x86_64", repository_id.name),
}
iterdir_mock.assert_has_calls([
MockCall(repository_paths._repository_root),
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
is_dir_mock.assert_has_calls([
MockCall(Path("i686")),
MockCall(Path("x86_64")),
])
assert not repository_paths.known_repositories(repository_paths.root)
iterdir_mock.assert_called_once_with(repository_paths._repository_root)
def test_known_repositories_empty(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
"""
must return empty repositories if tree is not available
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
iterdir_mock = mocker.patch("pathlib.Path.iterdir")
assert not repository_paths.known_repositories(repository_paths.root)
iterdir_mock.assert_not_called()
def test_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
@ -207,6 +273,7 @@ def test_tree_create(repository_paths: RepositoryPaths, mocker: MockerFixture) -
and not prop.endswith("_for")
and prop not in ("chown",
"known_architectures",
"known_repositories",
"owner",
"repository_id",
"root",