mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 07:17:17 +00:00
add ability to specify package source explicitly during the addition
This commit is contained in:
parent
266d2bd77d
commit
427ba0f0ea
@ -26,6 +26,7 @@ from pathlib import Path
|
|||||||
from ahriman import version
|
from ahriman import version
|
||||||
from ahriman.application import handlers
|
from ahriman.application import handlers
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
|
from ahriman.models.package_source import PackageSource
|
||||||
from ahriman.models.sign_settings import SignSettings
|
from ahriman.models.sign_settings import SignSettings
|
||||||
from ahriman.models.user_access import UserAccess
|
from ahriman.models.user_access import UserAccess
|
||||||
|
|
||||||
@ -91,6 +92,8 @@ def _set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||||
parser.add_argument("package", help="package base/name or archive path", nargs="+")
|
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("--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.add_argument("--without-dependencies", help="do not add dependencies", action="store_true")
|
||||||
parser.set_defaults(handler=handlers.Add, architecture=[])
|
parser.set_defaults(handler=handlers.Add, architecture=[])
|
||||||
return parser
|
return parser
|
||||||
|
@ -29,6 +29,7 @@ from ahriman.core.repository.repository import Repository
|
|||||||
from ahriman.core.tree import Tree
|
from ahriman.core.tree import Tree
|
||||||
from ahriman.core.util import package_like
|
from ahriman.core.util import package_like
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.package_source import PackageSource
|
||||||
|
|
||||||
|
|
||||||
class Application:
|
class Application:
|
||||||
@ -96,10 +97,11 @@ class Application:
|
|||||||
|
|
||||||
return updates
|
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
|
add packages for the next build
|
||||||
:param names: list of package bases to add
|
:param names: list of package bases to add
|
||||||
|
:param source: package source to add
|
||||||
:param without_dependencies: if set, dependency check will be disabled
|
:param without_dependencies: if set, dependency check will be disabled
|
||||||
"""
|
"""
|
||||||
known_packages = self._known_packages()
|
known_packages = self._known_packages()
|
||||||
@ -122,14 +124,14 @@ class Application:
|
|||||||
if without_dependencies:
|
if without_dependencies:
|
||||||
return
|
return
|
||||||
dependencies = Package.dependencies(path)
|
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:
|
def process_single(src: str) -> None:
|
||||||
maybe_path = Path(src)
|
resolved_source = source.resolve(src)
|
||||||
if maybe_path.is_dir():
|
if resolved_source == PackageSource.Directory:
|
||||||
add_directory(maybe_path)
|
add_directory(Path(src))
|
||||||
elif maybe_path.is_file():
|
elif resolved_source == PackageSource.Archive:
|
||||||
add_archive(maybe_path)
|
add_archive(Path(src))
|
||||||
else:
|
else:
|
||||||
path = add_manual(src)
|
path = add_manual(src)
|
||||||
process_dependencies(path)
|
process_dependencies(path)
|
||||||
|
@ -42,7 +42,7 @@ class Add(Handler):
|
|||||||
:param no_report: force disable reporting
|
:param no_report: force disable reporting
|
||||||
"""
|
"""
|
||||||
application = Application(architecture, configuration, no_report)
|
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:
|
if not args.now:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from threading import Lock, Thread
|
|||||||
from typing import Callable, Dict, Iterable, Tuple
|
from typing import Callable, Dict, Iterable, Tuple
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.package_source import PackageSource
|
||||||
|
|
||||||
|
|
||||||
class Spawn(Thread):
|
class Spawn(Thread):
|
||||||
@ -79,7 +80,9 @@ class Spawn(Thread):
|
|||||||
:param packages: packages list to add
|
:param packages: packages list to add
|
||||||
:param now: build packages now
|
: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)
|
self.spawn_process("add", *packages, **kwargs)
|
||||||
|
|
||||||
def packages_remove(self, packages: Iterable[str]) -> None:
|
def packages_remove(self, packages: Iterable[str]) -> None:
|
||||||
|
55
src/ahriman/models/package_source.py
Normal file
55
src/ahriman/models/package_source.py
Normal 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
|
@ -4,6 +4,7 @@ from pytest_mock import MockerFixture
|
|||||||
|
|
||||||
from ahriman.application.handlers import Add
|
from ahriman.application.handlers import Add
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.package_source import PackageSource
|
||||||
|
|
||||||
|
|
||||||
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
@ -14,6 +15,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
|||||||
"""
|
"""
|
||||||
args.package = []
|
args.package = []
|
||||||
args.now = False
|
args.now = False
|
||||||
|
args.source = PackageSource.Auto
|
||||||
args.without_dependencies = False
|
args.without_dependencies = False
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from unittest import mock
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.core.tree import Leaf, Tree
|
from ahriman.core.tree import Leaf, Tree
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.package_source import PackageSource
|
||||||
|
|
||||||
|
|
||||||
def test_finalize(application: Application, mocker: MockerFixture) -> None:
|
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
|
must add packages from directory
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
|
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",
|
iterdir_mock = mocker.patch("pathlib.Path.iterdir",
|
||||||
return_value=[package.filepath for package in package_ahriman.packages.values()])
|
return_value=[package.filepath for package in package_ahriman.packages.values()])
|
||||||
move_mock = mocker.patch("shutil.move")
|
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()
|
iterdir_mock.assert_called_once()
|
||||||
move_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)
|
mocker.patch("ahriman.models.package.Package.load", return_value=package_ahriman)
|
||||||
fetch_mock = mocker.patch("ahriman.core.build_tools.task.Task.fetch")
|
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()
|
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")
|
mocker.patch("ahriman.core.build_tools.task.Task.fetch")
|
||||||
dependencies_mock = mocker.patch("ahriman.models.package.Package.dependencies")
|
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()
|
dependencies_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
@ -149,10 +149,9 @@ def test_add_package(application: Application, package_ahriman: Package, mocker:
|
|||||||
must add package from archive
|
must add package from archive
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.application.application.Application._known_packages", return_value=set())
|
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")
|
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()
|
move_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ def test_packages_add(spawner: Spawn, mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn.spawn_process")
|
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn.spawn_process")
|
||||||
spawner.packages_add(["ahriman", "linux"], now=False)
|
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:
|
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")
|
spawn_mock = mocker.patch("ahriman.core.spawn.Spawn.spawn_process")
|
||||||
spawner.packages_add(["ahriman", "linux"], now=True)
|
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:
|
def test_packages_remove(spawner: Spawn, mocker: MockerFixture) -> None:
|
||||||
|
47
tests/ahriman/models/test_package_source.py
Normal file
47
tests/ahriman/models/test_package_source.py
Normal 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
|
Loading…
Reference in New Issue
Block a user