Compare commits

..

3 Commits

Author SHA1 Message Date
6551c8d983 merge restore to rebuild commannd 2022-04-10 01:51:12 +03:00
a6c8d64053 Release 2.0.0rc6 2022-04-09 17:34:23 +03:00
fd78f2b5e2 do not render failed packages in jinja (#57)
basic templates require package info which is unavailable if package
wasn't built
2022-04-09 17:31:13 +03:00
13 changed files with 2475 additions and 2517 deletions

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 504 KiB

After

Width:  |  Height:  |  Size: 509 KiB

View File

@ -1,7 +1,7 @@
# Maintainer: Evgeniy Alekseev # Maintainer: Evgeniy Alekseev
pkgname='ahriman' pkgname='ahriman'
pkgver=2.0.0rc5 pkgver=2.0.0rc6
pkgrel=1 pkgrel=1
pkgdesc="ArcH Linux ReposItory MANager" pkgdesc="ArcH Linux ReposItory MANager"
arch=('any') arch=('any')
@ -38,7 +38,7 @@ build() {
package() { package() {
cd "$pkgname" cd "$pkgname"
python -m installer --destdir="$pkgdir" dist/*.whl python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
# python-installer actually thinks that you cannot just copy files to root # python-installer actually thinks that you cannot just copy files to root
# thus we need to copy them manually # thus we need to copy them manually

View File

@ -1,5 +1,4 @@
{#simplified version of full report#} {#simplified version of full report#}
<b>{{ repository }} update</b> <b>{{ repository }} update</b>
{% for package in packages %} {% for package in packages %}
<a href="{{ link_path }}/{{ package.filename }}">{{ package.name }}</a> {{ package.version }} at {{ package.build_date }} <a href="{{ link_path }}/{{ package.filename }}">{{ package.name }}</a> {{ package.version }}{% endfor %}
{% endfor %}

View File

@ -89,7 +89,6 @@ def _parser() -> argparse.ArgumentParser:
_set_repo_rebuild_parser(subparsers) _set_repo_rebuild_parser(subparsers)
_set_repo_remove_unknown_parser(subparsers) _set_repo_remove_unknown_parser(subparsers)
_set_repo_report_parser(subparsers) _set_repo_report_parser(subparsers)
_set_repo_restore_parser(subparsers)
_set_repo_setup_parser(subparsers) _set_repo_setup_parser(subparsers)
_set_repo_sign_parser(subparsers) _set_repo_sign_parser(subparsers)
_set_repo_status_update_parser(subparsers) _set_repo_status_update_parser(subparsers)
@ -375,6 +374,12 @@ def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
parser.add_argument("--depends-on", help="only rebuild packages that depend on specified package", action="append") parser.add_argument("--depends-on", help="only rebuild packages that depend on specified package", action="append")
parser.add_argument("--dry-run", help="just perform check for packages without rebuild process itself", parser.add_argument("--dry-run", help="just perform check for packages without rebuild process itself",
action="store_true") action="store_true")
parser.add_argument("--from-database",
help="read packages from database instead of filesystem. This feature in particular is "
"required in case if you would like to restore repository from another repository "
"instance. Note however that in order to restore packages you need to have original "
"ahriman instance run with web service and have run repo-update at least once.",
action="store_true")
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true") parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.set_defaults(handler=handlers.Rebuild) parser.set_defaults(handler=handlers.Rebuild)
return parser return parser
@ -410,21 +415,6 @@ def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser:
return parser return parser
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
add parser for package addition subcommand
:param root: subparsers for the commands
:return: created argument parser
"""
parser = root.add_parser("repo-restore", aliases=["restore"], help="restore repository",
description="restore repository from database file", formatter_class=_formatter)
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.add_argument("-n", "--now", help="run update function after", action="store_true")
parser.add_argument("--without-dependencies", help="do not add dependencies", action="store_true")
parser.set_defaults(handler=handlers.Add, package=None, source=PackageSource.AUR)
return parser
def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser: def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
""" """
add parser for setup subcommand add parser for setup subcommand

View File

@ -19,7 +19,7 @@
# #
import argparse import argparse
from typing import List, Type from typing import Type
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers.handler import Handler from ahriman.application.handlers.handler import Handler
@ -43,20 +43,10 @@ class Add(Handler):
:param unsafe: if set no user check will be performed before path creation :param unsafe: if set no user check will be performed before path creation
""" """
application = Application(architecture, configuration, no_report, unsafe) application = Application(architecture, configuration, no_report, unsafe)
packages = Add.extract_packages(application) if args.package is None else args.package application.add(args.package, args.source, args.without_dependencies)
application.add(packages, args.source, args.without_dependencies)
if not args.now: if not args.now:
return return
packages = application.updates(packages, True, True, False, True, application.logger.info) packages = application.updates(args.package, True, True, False, True, application.logger.info)
result = application.update(packages) result = application.update(packages)
Add.check_if_empty(args.exit_code, result.is_empty) Add.check_if_empty(args.exit_code, result.is_empty)
@staticmethod
def extract_packages(application: Application) -> List[str]:
"""
extract packages from database file
:param application: application instance
:return: list of packages which were stored in database
"""
return [package.base for (package, _) in application.database.packages_get()]

View File

@ -19,12 +19,13 @@
# #
import argparse import argparse
from typing import Type from typing import List, Type
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers.handler import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters.update_printer import UpdatePrinter from ahriman.core.formatters.update_printer import UpdatePrinter
from ahriman.models.package import Package
class Rebuild(Handler): class Rebuild(Handler):
@ -46,7 +47,10 @@ class Rebuild(Handler):
depends_on = set(args.depends_on) if args.depends_on else None depends_on = set(args.depends_on) if args.depends_on else None
application = Application(architecture, configuration, no_report, unsafe) application = Application(architecture, configuration, no_report, unsafe)
updates = application.repository.packages_depends_on(depends_on) if args.from_database:
updates = Rebuild.extract_packages(application)
else:
updates = application.repository.packages_depends_on(depends_on)
Rebuild.check_if_empty(args.exit_code, not updates) Rebuild.check_if_empty(args.exit_code, not updates)
if args.dry_run: if args.dry_run:
@ -56,3 +60,12 @@ class Rebuild(Handler):
result = application.update(updates) result = application.update(updates)
Rebuild.check_if_empty(args.exit_code, result.is_empty) Rebuild.check_if_empty(args.exit_code, result.is_empty)
@staticmethod
def extract_packages(application: Application) -> List[Package]:
"""
extract packages from database file
:param application: application instance
:return: list of packages which were stored in database
"""
return [package for (package, _) in application.database.packages_get()]

View File

@ -101,7 +101,7 @@ class JinjaTemplate:
"name": package, "name": package,
"url": properties.url or "", "url": properties.url or "",
"version": base.version "version": base.version
} for base in result.updated for package, properties in base.packages.items() } for base in result.success for package, properties in base.packages.items()
] ]
comparator: Callable[[Dict[str, str]], str] = lambda item: item["filename"] comparator: Callable[[Dict[str, str]], str] = lambda item: item["filename"]

View File

@ -19,14 +19,11 @@
# #
from __future__ import annotations from __future__ import annotations
import shutil
import tempfile
from pathlib import Path
from typing import Iterable, List, Set, Type from typing import Iterable, List, Set, Type
from ahriman.core.build_tools.sources import Sources from ahriman.core.build_tools.sources import Sources
from ahriman.core.database.sqlite import SQLite from ahriman.core.database.sqlite import SQLite
from ahriman.core.util import tmpdir
from ahriman.models.package import Package from ahriman.models.package import Package
@ -61,12 +58,9 @@ class Leaf:
:param database: database instance :param database: database instance
:return: loaded class :return: loaded class
""" """
clone_dir = Path(tempfile.mkdtemp()) with tmpdir() as clone_dir:
try:
Sources.load(clone_dir, package.git_url, database.patches_get(package.base)) Sources.load(clone_dir, package.git_url, database.patches_get(package.base))
dependencies = Package.dependencies(clone_dir) dependencies = Package.dependencies(clone_dir)
finally:
shutil.rmtree(clone_dir, ignore_errors=True)
return cls(package, dependencies) return cls(package, dependencies)
def is_root(self, packages: Iterable[Leaf]) -> bool: def is_root(self, packages: Iterable[Leaf]) -> bool:

View File

@ -62,13 +62,6 @@ class Result:
""" """
return list(self._success.values()) return list(self._success.values())
@property
def updated(self) -> List[Package]:
"""
:return: list of updated packages inclding both success and failed
"""
return self.success + self.failed
def add_failed(self, package: Package) -> None: def add_failed(self, package: Package) -> None:
""" """
add new package to failed built add new package to failed built

View File

@ -17,4 +17,4 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
__version__ = "2.0.0rc5" __version__ = "2.0.0rc6"

View File

@ -3,7 +3,6 @@ import pytest
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from ahriman.application.application import Application
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 import Package from ahriman.models.package import Package
@ -37,20 +36,6 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock.assert_called_once_with(args.package, args.source, args.without_dependencies) application_mock.assert_called_once_with(args.package, args.source, args.without_dependencies)
def test_run_extract_packages(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
args.package = None
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
mocker.patch("ahriman.application.application.Application.add")
extract_mock = mocker.patch("ahriman.application.handlers.Add.extract_packages", return_value=[])
Add.run(args, "x86_64", configuration, True, False)
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_run_with_updates(args: argparse.Namespace, configuration: Configuration, def test_run_with_updates(args: argparse.Namespace, configuration: Configuration,
package_ahriman: Package, mocker: MockerFixture) -> None: package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
@ -87,12 +72,3 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
Add.run(args, "x86_64", configuration, True, False) Add.run(args, "x86_64", configuration, True, False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)
def test_extract_packages(application: Application, mocker: MockerFixture) -> None:
"""
must extract packages from database
"""
packages_mock = mocker.patch("ahriman.core.database.sqlite.SQLite.packages_get")
Add.extract_packages(application)
packages_mock.assert_called_once_with()

View File

@ -4,6 +4,7 @@ import pytest
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from unittest import mock from unittest import mock
from ahriman.application.application import Application
from ahriman.application.handlers import Rebuild from ahriman.application.handlers import Rebuild
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.package import Package from ahriman.models.package import Package
@ -18,6 +19,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
""" """
args.depends_on = [] args.depends_on = []
args.dry_run = False args.dry_run = False
args.from_database = False
args.exit_code = False args.exit_code = False
return args return args
@ -42,6 +44,20 @@ def test_run(args: argparse.Namespace, package_ahriman: Package,
check_mock.assert_has_calls([mock.call(False, False), mock.call(False, False)]) check_mock.assert_has_calls([mock.call(False, False), mock.call(False, False)])
def test_run_extract_packages(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must run command
"""
args = _default_args(args)
args.from_database = True
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
mocker.patch("ahriman.application.application.Application.add")
extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
Rebuild.run(args, "x86_64", configuration, True, False)
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, def test_run_dry_run(args: argparse.Namespace, configuration: Configuration,
package_ahriman: Package, mocker: MockerFixture) -> None: package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
@ -116,3 +132,12 @@ def test_run_build_empty_exception(args: argparse.Namespace, configuration: Conf
Rebuild.run(args, "x86_64", configuration, True, False) Rebuild.run(args, "x86_64", configuration, True, False)
check_mock.assert_has_calls([mock.call(True, False), mock.call(True, True)]) check_mock.assert_has_calls([mock.call(True, False), mock.call(True, True)])
def test_extract_packages(application: Application, mocker: MockerFixture) -> None:
"""
must extract packages from database
"""
packages_mock = mocker.patch("ahriman.core.database.sqlite.SQLite.packages_get")
Rebuild.extract_packages(application)
packages_mock.assert_called_once_with()

View File

@ -6,7 +6,6 @@ from pytest_mock import MockerFixture
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.models.action import Action from ahriman.models.action import Action
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
@ -340,25 +339,6 @@ def test_subparsers_repo_report_architecture(parser: argparse.ArgumentParser) ->
assert args.architecture == ["x86_64"] assert args.architecture == ["x86_64"]
def test_subparsers_repo_restore(parser: argparse.ArgumentParser) -> None:
"""
repo-restore command must imply package and source
"""
args = parser.parse_args(["repo-restore"])
assert args.package is None
assert args.source == PackageSource.AUR
def test_subparsers_repo_restore_architecture(parser: argparse.ArgumentParser) -> None:
"""
repo-restore command must correctly parse architecture list
"""
args = parser.parse_args(["repo-restore"])
assert args.architecture is None
args = parser.parse_args(["-a", "x86_64", "repo-restore"])
assert args.architecture == ["x86_64"]
def test_subparsers_repo_setup(parser: argparse.ArgumentParser) -> None: def test_subparsers_repo_setup(parser: argparse.ArgumentParser) -> None:
""" """
repo-setup command must imply lock, no-report, quiet and unsafe repo-setup command must imply lock, no-report, quiet and unsafe