feat: add package copy subcommand

This commit is contained in:
2024-09-27 17:23:04 +03:00
parent 7bc4810377
commit 1e7d4daf18
10 changed files with 300 additions and 12 deletions

View File

@ -110,6 +110,7 @@ Start web service (requires additional configuration):
_set_package_add_parser(subparsers)
_set_package_changes_parser(subparsers)
_set_package_changes_remove_parser(subparsers)
_set_package_copy_parser(subparsers)
_set_package_remove_parser(subparsers)
_set_package_status_parser(subparsers)
_set_package_status_remove_parser(subparsers)
@ -334,6 +335,27 @@ def _set_package_changes_remove_parser(root: SubParserAction) -> argparse.Argume
return parser
def _set_package_copy_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
add parser for package copy subcommand
Args:
root(SubParserAction): subparsers for the commands
Returns:
argparse.ArgumentParser: created argument parser
"""
parser = root.add_parser("package-copy", aliases=["copy"], help="copy package from another repository",
description="copy package and its metadata from another repository",
formatter_class=_HelpFormatter)
parser.add_argument("source", help="source repository name")
parser.add_argument("package", help="package base", nargs="+")
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.add_argument("--remove", help="remove package from the source repository after", action="store_true")
parser.set_defaults(handler=handlers.Copy)
return parser
def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
add parser for package removal subcommand

View File

@ -141,19 +141,19 @@ class ApplicationPackages(ApplicationProperties):
self.database.build_queue_insert(package)
self.reporter.set_unknown(package)
def add(self, names: Iterable[str], source: PackageSource, username: str | None = None) -> None:
def add(self, packages: Iterable[str], source: PackageSource, username: str | None = None) -> None:
"""
add packages for the next build
Args:
names(Iterable[str]): list of package bases to add
packages(Iterable[str]): list of package bases to add
source(PackageSource): package source to add
username(str | None, optional): optional override of username for build process (Default value = None)
"""
for name in names:
resolved_source = source.resolve(name, self.repository.paths)
for package in packages:
resolved_source = source.resolve(package, self.repository.paths)
fn = getattr(self, f"_add_{resolved_source.value}")
fn(name, username)
fn(package, username)
def on_result(self, result: Result) -> None:
"""
@ -167,16 +167,16 @@ class ApplicationPackages(ApplicationProperties):
"""
raise NotImplementedError
def remove(self, names: Iterable[str]) -> Result:
def remove(self, packages: Iterable[str]) -> Result:
"""
remove packages from repository
Args:
names(Iterable[str]): list of packages (either base or name) to remove
packages(Iterable[str]): list of packages (either base or name) to remove
Returns:
Result: removal result
"""
result = self.repository.process_remove(names)
result = self.repository.process_remove(packages)
self.on_result(result)
return result

View File

@ -191,6 +191,12 @@ class ApplicationRepository(ApplicationProperties):
"""
updates = {}
# always add already built packages, because they will be always added
updates.update({
package.base: package
for package in self.repository.load_archives(self.repository.packages_built())
})
if aur:
updates.update({package.base: package for package in self.repository.updates_aur(filter_packages, vcs=vcs)})
if local:

View File

@ -21,6 +21,7 @@ from ahriman.application.handlers.add import Add
from ahriman.application.handlers.backup import Backup
from ahriman.application.handlers.change import Change
from ahriman.application.handlers.clean import Clean
from ahriman.application.handlers.copy import Copy
from ahriman.application.handlers.daemon import Daemon
from ahriman.application.handlers.dump import Dump
from ahriman.application.handlers.handler import Handler

View File

@ -0,0 +1,95 @@
#
# Copyright (c) 2021-2024 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/>.
#
import argparse
from ahriman.application.application import Application
from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration
from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package
from ahriman.models.package_source import PackageSource
from ahriman.models.repository_id import RepositoryId
class Copy(Handler):
"""
copy packages handler
"""
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting action
@classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
report: bool) -> None:
"""
callback for command line
Args:
args(argparse.Namespace): command line args
repository_id(RepositoryId): repository unique identifier
configuration(Configuration): configuration instance
report(bool): force enable or disable reporting
"""
application = Application(repository_id, configuration, report=report)
application.on_start()
configuration_path, _ = configuration.check_loaded()
source_repository_id = RepositoryId(repository_id.architecture, args.source)
source_configuration = Configuration.from_path(configuration_path, source_repository_id)
source_application = Application(source_repository_id, source_configuration, report=report)
packages = source_application.repository.packages(args.package)
Copy.check_status(args.exit_code, packages)
for package in packages:
Copy.copy_package(package, application, source_application)
# run update
application.update([])
if args.remove:
source_application.remove(args.package)
@staticmethod
def copy_package(package: Package, application: Application, source_application: Application) -> None:
"""
copy package ``package`` from source repository to target repository
Args:
package(Package): package to copy
application(Application): application instance of the target repository
source_application(Application): application instance of the source repository
"""
# copy files
source_paths = [
str(source_application.repository.paths.repository / source.filename)
for source in package.packages.values()
if source.filename is not None
]
application.add(source_paths, PackageSource.Archive)
# copy metadata
application.reporter.package_changes_update(
package.base, source_application.reporter.package_changes_get(package.base)
)
application.reporter.package_dependencies_update(
package.base, source_application.reporter.package_dependencies_get(package.base)
)
application.reporter.package_update(package, BuildStatusEnum.Pending)