add ability to specify package source explicitly during the addition

This commit is contained in:
Evgenii Alekseev 2021-09-26 09:55:14 +03:00
parent 266d2bd77d
commit 427ba0f0ea
9 changed files with 128 additions and 17 deletions

View File

@ -26,6 +26,7 @@ from pathlib import Path
from ahriman import version
from ahriman.application import handlers
from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package_source import PackageSource
from ahriman.models.sign_settings import SignSettings
from ahriman.models.user_access import UserAccess
@ -91,6 +92,8 @@ def _set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("package", help="package base/name or archive path", nargs="+")
parser.add_argument("--now", help="run update function after", action="store_true")
parser.add_argument("--source", help="package source", choices=PackageSource, type=PackageSource,
default=PackageSource.Auto)
parser.add_argument("--without-dependencies", help="do not add dependencies", action="store_true")
parser.set_defaults(handler=handlers.Add, architecture=[])
return parser

View File

@ -29,6 +29,7 @@ from ahriman.core.repository.repository import Repository
from ahriman.core.tree import Tree
from ahriman.core.util import package_like
from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource
class Application:
@ -96,10 +97,11 @@ class Application:
return updates
def add(self, names: Iterable[str], without_dependencies: bool) -> None:
def add(self, names: Iterable[str], source: PackageSource, without_dependencies: bool) -> None:
"""
add packages for the next build
:param names: list of package bases to add
:param source: package source to add
:param without_dependencies: if set, dependency check will be disabled
"""
known_packages = self._known_packages()
@ -122,14 +124,14 @@ class Application:
if without_dependencies:
return
dependencies = Package.dependencies(path)
self.add(dependencies.difference(known_packages), without_dependencies)
self.add(dependencies.difference(known_packages), PackageSource.AUR, without_dependencies)
def process_single(src: str) -> None:
maybe_path = Path(src)
if maybe_path.is_dir():
add_directory(maybe_path)
elif maybe_path.is_file():
add_archive(maybe_path)
resolved_source = source.resolve(src)
if resolved_source == PackageSource.Directory:
add_directory(Path(src))
elif resolved_source == PackageSource.Archive:
add_archive(Path(src))
else:
path = add_manual(src)
process_dependencies(path)

View File

@ -42,7 +42,7 @@ class Add(Handler):
:param no_report: force disable reporting
"""
application = Application(architecture, configuration, no_report)
application.add(args.package, args.without_dependencies)
application.add(args.package, args.source, args.without_dependencies)
if not args.now:
return

View File

@ -28,6 +28,7 @@ from threading import Lock, Thread
from typing import Callable, Dict, Iterable, Tuple
from ahriman.core.configuration import Configuration
from ahriman.models.package_source import PackageSource
class Spawn(Thread):
@ -79,7 +80,9 @@ class Spawn(Thread):
:param packages: packages list to add
:param now: build packages now
"""
kwargs = {"now": ""} if now else {}
kwargs = {"source": PackageSource.AUR.value} # avoid abusing by building non-aur packages
if now:
kwargs["now"] = ""
self.spawn_process("add", *packages, **kwargs)
def packages_remove(self, packages: Iterable[str]) -> None:

View File

@ -0,0 +1,55 @@
#
# Copyright (c) 2021 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import annotations
from enum import Enum
from pathlib import Path
from ahriman.core.util import package_like
class PackageSource(Enum):
"""
package source for addition enumeration
:cvar Auto: automatically determine type of the source
:cvar Archive: source is a package archive
:cvar Directory: source is a directory which contains packages
:cvar AUR: source is an AUR package for which it should search
"""
Auto = "auto"
Archive = "archive"
Directory = "directory"
AUR = "aur"
def resolve(self, source: str) -> PackageSource:
"""
resolve auto into the correct type
:param source: source of the package
:return: non-auto type of the package source
"""
if self != PackageSource.Auto:
return self
maybe_path = Path(source)
if maybe_path.is_dir():
return PackageSource.Directory
if maybe_path.is_file() and package_like(maybe_path):
return PackageSource.Archive
return PackageSource.AUR

View File

@ -4,6 +4,7 @@ from pytest_mock import MockerFixture
from ahriman.application.handlers import Add
from ahriman.core.configuration import Configuration
from ahriman.models.package_source import PackageSource
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
@ -14,6 +15,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
args.package = []
args.now = False
args.source = PackageSource.Auto
args.without_dependencies = False
return args

View File

@ -6,6 +6,7 @@ from unittest import mock
from ahriman.application.application import Application
from ahriman.core.tree import Leaf, Tree
from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource
def test_finalize(application: Application, mocker: MockerFixture) -> None:
@ -108,12 +109,11 @@ def test_add_directory(application: Application, package_ahriman: Package, mocke
must add packages from directory
"""
mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
mocker.patch("pathlib.Path.is_dir", return_value=True)
iterdir_mock = mocker.patch("pathlib.Path.iterdir",
return_value=[package.filepath for package in package_ahriman.packages.values()])
move_mock = mocker.patch("shutil.move")
application.add([package_ahriman.base], False)
application.add([package_ahriman.base], PackageSource.Directory, False)
iterdir_mock.assert_called_once()
move_mock.assert_called_once()
@ -126,7 +126,7 @@ def test_add_manual(application: Application, package_ahriman: Package, mocker:
mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman)
fetch_mock = mocker.patch("ahriman.core.build_tools.task.Task.fetch")
application.add([package_ahriman.base], True)
application.add([package_ahriman.base], PackageSource.AUR, True)
fetch_mock.assert_called_once()
@ -140,7 +140,7 @@ def test_add_manual_with_dependencies(application: Application, package_ahriman:
mocker.patch("ahriman.core.build_tools.task.Task.fetch")
dependencies_mock = mocker.patch("ahriman.models.package.Package.dependencies")
application.add([package_ahriman.base], False)
application.add([package_ahriman.base], PackageSource.AUR, False)
dependencies_mock.assert_called_once()
@ -149,10 +149,9 @@ def test_add_package(application: Application, package_ahriman: Package, mocker:
must add package from archive
"""
mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
mocker.patch("pathlib.Path.is_file", return_value=True)
move_mock = mocker.patch("shutil.move")
application.add([package_ahriman.base], False)
application.add([package_ahriman.base], PackageSource.Archive, False)
move_mock.assert_called_once()

View File

@ -42,7 +42,7 @@ def test_packages_add(spawner: Spawn, mocker: MockerFixture) -> None:
"""
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn.spawn_process")
spawner.packages_add(["ahriman", "linux"], now=False)
spawn_mock.assert_called_with("add", "ahriman", "linux")
spawn_mock.assert_called_with("add", "ahriman", "linux", source="aur")
def test_packages_add_with_build(spawner: Spawn, mocker: MockerFixture) -> None:
@ -51,7 +51,7 @@ def test_packages_add_with_build(spawner: Spawn, mocker: MockerFixture) -> None:
"""
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn.spawn_process")
spawner.packages_add(["ahriman", "linux"], now=True)
spawn_mock.assert_called_with("add", "ahriman", "linux", now="")
spawn_mock.assert_called_with("add", "ahriman", "linux", source="aur", now="")
def test_packages_remove(spawner: Spawn, mocker: MockerFixture) -> None:

View File

@ -0,0 +1,47 @@
from pytest_mock import MockerFixture
from ahriman.models.package_source import PackageSource
def test_resolve_non_auto() -> None:
"""
must resolve non auto type to itself
"""
for source in filter(lambda src: src != PackageSource.Auto, PackageSource):
assert source.resolve("") == source
def test_resolve_archive(mocker: MockerFixture) -> None:
"""
must resolve auto type into the archive
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
mocker.patch("pathlib.Path.is_file", return_value=True)
assert PackageSource.Auto.resolve("linux-5.14.2.arch1-2-x86_64.pkg.tar.zst") == PackageSource.Archive
def test_resolve_directory(mocker: MockerFixture) -> None:
"""
must resolve auto type into the directory
"""
mocker.patch("pathlib.Path.is_dir", return_value=True)
mocker.patch("pathlib.Path.is_file", return_value=False)
assert PackageSource.Auto.resolve("path") == PackageSource.Directory
def test_resolve_aur(mocker: MockerFixture) -> None:
"""
must resolve auto type into the AUR package
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
mocker.patch("pathlib.Path.is_file", return_value=False)
assert PackageSource.Auto.resolve("package") == PackageSource.AUR
def test_resolve_aur_not_package_like(mocker: MockerFixture) -> None:
"""
must resolve auto type into the AUR package if it is file, but does not look like a package archive
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
mocker.patch("pathlib.Path.is_file", return_value=True)
assert PackageSource.Auto.resolve("package") == PackageSource.AUR