implement single-function patches (#69)

This commit is contained in:
2022-10-30 03:11:03 +03:00
committed by GitHub
parent ad7cdb7d95
commit 649df81aa5
25 changed files with 632 additions and 163 deletions

View File

@ -6,6 +6,7 @@ from unittest import mock
from ahriman.core.build_tools.sources import Sources
from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.remote_source import RemoteSource
from ahriman.models.repository_paths import RepositoryPaths
@ -16,11 +17,9 @@ def test_extend_architectures(mocker: MockerFixture) -> None:
"""
mocker.patch("pathlib.Path.is_file", return_value=True)
archs_mock = mocker.patch("ahriman.models.package.Package.supported_architectures", return_value={"x86_64"})
write_mock = mocker.patch("ahriman.models.pkgbuild_patch.PkgbuildPatch.write")
Sources.extend_architectures(Path("local"), "i686")
assert Sources.extend_architectures(Path("local"), "i686") == [PkgbuildPatch("arch", list({"x86_64", "i686"}))]
archs_mock.assert_called_once_with(Path("local"))
write_mock.assert_called_once_with(Path("local") / "PKGBUILD")
def test_extend_architectures_any(mocker: MockerFixture) -> None:
@ -29,21 +28,7 @@ def test_extend_architectures_any(mocker: MockerFixture) -> None:
"""
mocker.patch("pathlib.Path.is_file", return_value=True)
mocker.patch("ahriman.models.package.Package.supported_architectures", return_value={"any"})
write_mock = mocker.patch("ahriman.models.pkgbuild_patch.PkgbuildPatch.write")
Sources.extend_architectures(Path("local"), "i686")
write_mock.assert_not_called()
def test_extend_architectures_skip(mocker: MockerFixture) -> None:
"""
must skip extending list of the architectures in case if no PKGBUILD file found
"""
mocker.patch("pathlib.Path.is_file", return_value=False)
write_mock = mocker.patch("ahriman.models.pkgbuild_patch.PkgbuildPatch.write")
Sources.extend_architectures(Path("local"), "i686")
write_mock.assert_not_called()
assert Sources.extend_architectures(Path("local"), "i686") == []
def test_fetch_empty(remote_source: RemoteSource, mocker: MockerFixture) -> None:
@ -167,15 +152,16 @@ def test_load(package_ahriman: Package, repository_paths: RepositoryPaths, mocke
"""
must load packages sources correctly
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
patch = PkgbuildPatch(None, "patch")
path = Path("local")
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
patch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_apply")
architectures_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.extend_architectures")
architectures_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.extend_architectures", return_value=[])
Sources.load(Path("local"), package_ahriman, "patch", repository_paths)
fetch_mock.assert_called_once_with(Path("local"), package_ahriman.remote)
patch_mock.assert_called_once_with(Path("local"), "patch")
architectures_mock.assert_called_once_with(Path("local"), repository_paths.architecture)
Sources.load(path, package_ahriman, [patch], repository_paths)
fetch_mock.assert_called_once_with(path, package_ahriman.remote)
patch_mock.assert_called_once_with(path, patch)
architectures_mock.assert_called_once_with(path, repository_paths.architecture)
def test_load_no_patch(package_ahriman: Package, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
@ -184,9 +170,10 @@ def test_load_no_patch(package_ahriman: Package, repository_paths: RepositoryPat
"""
mocker.patch("pathlib.Path.is_dir", return_value=False)
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
mocker.patch("ahriman.core.build_tools.sources.Sources.extend_architectures", return_value=[])
patch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_apply")
Sources.load(Path("local"), package_ahriman, None, repository_paths)
Sources.load(Path("local"), package_ahriman, [], repository_paths)
patch_mock.assert_not_called()
@ -197,8 +184,9 @@ def test_load_with_cache(package_ahriman: Package, repository_paths: RepositoryP
mocker.patch("pathlib.Path.is_dir", return_value=True)
copytree_mock = mocker.patch("shutil.copytree")
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
mocker.patch("ahriman.core.build_tools.sources.Sources.extend_architectures", return_value=[])
Sources.load(Path("local"), package_ahriman, None, repository_paths)
Sources.load(Path("local"), package_ahriman, [], repository_paths)
copytree_mock.assert_called_once() # we do not check full command here, sorry
@ -331,11 +319,24 @@ def test_patch_apply(sources: Sources, mocker: MockerFixture) -> None:
"""
must apply patches if any
"""
patch = PkgbuildPatch(None, "patch")
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
local = Path("local")
sources.patch_apply(local, "patches")
sources.patch_apply(local, patch)
check_output_mock.assert_called_once_with(
"git", "apply", "--ignore-space-change", "--ignore-whitespace",
exception=None, cwd=local, input_data="patches", logger=pytest.helpers.anyvar(int)
exception=None, cwd=local, input_data=patch.value, logger=pytest.helpers.anyvar(int)
)
def test_patch_apply_function(sources: Sources, mocker: MockerFixture) -> None:
"""
must apply single-function patches
"""
patch = PkgbuildPatch("version", "42")
local = Path("local")
write_mock = mocker.patch("ahriman.models.pkgbuild_patch.PkgbuildPatch.write")
sources.patch_apply(local, patch)
write_mock.assert_called_once_with(local / "PKGBUILD")

View File

@ -20,4 +20,4 @@ def test_init(task_ahriman: Task, database: SQLite, mocker: MockerFixture) -> No
"""
load_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.load")
task_ahriman.init(Path("ahriman"), database)
load_mock.assert_called_once_with(Path("ahriman"), task_ahriman.package, None, task_ahriman.paths)
load_mock.assert_called_once_with(Path("ahriman"), task_ahriman.package, [], task_ahriman.paths)

View File

@ -0,0 +1,8 @@
from ahriman.core.database.migrations.m003_patch_variables import steps
def test_migration_package_source() -> None:
"""
migration must not be empty
"""
assert steps

View File

@ -1,55 +1,96 @@
from ahriman.core.database import SQLite
from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
def test_patches_get_insert(database: SQLite, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must insert patch to database
"""
database.patches_insert(package_ahriman.base, "patch_1")
database.patches_insert(package_python_schedule.base, "patch_2")
assert database.patches_get(package_ahriman.base) == "patch_1"
assert not database.build_queue_get()
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch_1"))
database.patches_insert(package_ahriman.base, PkgbuildPatch("key", "patch_3"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch_2"))
assert database.patches_get(package_ahriman.base) == [
PkgbuildPatch(None, "patch_1"), PkgbuildPatch("key", "patch_3")
]
def test_patches_list(database: SQLite, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must list all patches
"""
database.patches_insert(package_ahriman.base, "patch1")
database.patches_insert(package_python_schedule.base, "patch2")
assert database.patches_list(None) == {package_ahriman.base: "patch1", package_python_schedule.base: "patch2"}
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_ahriman.base, PkgbuildPatch("key", "patch3"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
assert database.patches_list(None, []) == {
package_ahriman.base: [PkgbuildPatch(None, "patch1"), PkgbuildPatch("key", "patch3")],
package_python_schedule.base: [PkgbuildPatch(None, "patch2")],
}
def test_patches_list_filter(database: SQLite, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must list all patches filtered by package name (same as get)
"""
database.patches_insert(package_ahriman.base, "patch1")
database.patches_insert(package_python_schedule.base, "patch2")
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
assert database.patches_list(package_ahriman.base) == {package_ahriman.base: "patch1"}
assert database.patches_list(package_python_schedule.base) == {package_python_schedule.base: "patch2"}
assert database.patches_list(package_ahriman.base, []) == {package_ahriman.base: [PkgbuildPatch(None, "patch1")]}
assert database.patches_list(package_python_schedule.base, []) == {
package_python_schedule.base: [PkgbuildPatch(None, "patch2")],
}
def test_patches_list_filter_by_variable(database: SQLite, package_ahriman: Package,
package_python_schedule: Package) -> None:
"""
must list all patches filtered by package name (same as get)
"""
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_ahriman.base, PkgbuildPatch("key", "patch2"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch3"))
assert database.patches_list(None, []) == {
package_ahriman.base: [PkgbuildPatch(None, "patch1"), PkgbuildPatch("key", "patch2")],
package_python_schedule.base: [PkgbuildPatch(None, "patch3")],
}
assert database.patches_list(None, ["key"]) == {
package_ahriman.base: [PkgbuildPatch("key", "patch2")],
}
def test_patches_insert_remove(database: SQLite, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must remove patch from database
"""
database.patches_insert(package_ahriman.base, "patch_1")
database.patches_insert(package_python_schedule.base, "patch_2")
database.patches_remove(package_ahriman.base)
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
database.patches_remove(package_ahriman.base, [])
assert database.patches_get(package_ahriman.base) is None
database.patches_insert(package_python_schedule.base, "patch_2")
assert database.patches_get(package_ahriman.base) == []
assert database.patches_get(package_python_schedule.base) == [PkgbuildPatch(None, "patch2")]
def test_patches_insert_remove_by_variable(database: SQLite, package_ahriman: Package,
package_python_schedule: Package) -> None:
"""
must remove patch from database by variable
"""
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
database.patches_insert(package_ahriman.base, PkgbuildPatch("key", "patch3"))
database.patches_insert(package_python_schedule.base, PkgbuildPatch(None, "patch2"))
database.patches_remove(package_ahriman.base, ["key"])
assert database.patches_get(package_ahriman.base) == [PkgbuildPatch(None, "patch1")]
assert database.patches_get(package_python_schedule.base) == [PkgbuildPatch(None, "patch2")]
def test_patches_insert_insert(database: SQLite, package_ahriman: Package) -> None:
"""
must update patch in database
"""
database.patches_insert(package_ahriman.base, "patch_1")
assert database.patches_get(package_ahriman.base) == "patch_1"
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch1"))
assert database.patches_get(package_ahriman.base) == [PkgbuildPatch(None, "patch1")]
database.patches_insert(package_ahriman.base, "patch_2")
assert database.patches_get(package_ahriman.base) == "patch_2"
database.patches_insert(package_ahriman.base, PkgbuildPatch(None, "patch2"))
assert database.patches_get(package_ahriman.base) == [PkgbuildPatch(None, "patch2")]

View File

@ -1,10 +1,11 @@
import pytest
from ahriman.core.formatters import AurPrinter, ConfigurationPrinter, PackagePrinter, StatusPrinter, StringPrinter, \
UpdatePrinter, UserPrinter, VersionPrinter
from ahriman.core.formatters import AurPrinter, ConfigurationPrinter, PackagePrinter, PatchPrinter, StatusPrinter, \
StringPrinter, UpdatePrinter, UserPrinter, VersionPrinter
from ahriman.models.aur_package import AURPackage
from ahriman.models.build_status import BuildStatus
from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.user import User
@ -47,6 +48,20 @@ def package_ahriman_printer(package_ahriman: Package) -> PackagePrinter:
return PackagePrinter(package_ahriman, BuildStatus())
@pytest.fixture
def patch_printer(package_ahriman: Package) -> PatchPrinter:
"""
fixture for patch printer
Args:
package_ahriman(Package): package fixture
Returns:
PatchPrinter: patch printer test instance
"""
return PatchPrinter(package_ahriman.base, [PkgbuildPatch("key", "value")])
@pytest.fixture
def status_printer() -> StatusPrinter:
"""

View File

@ -0,0 +1,22 @@
from ahriman.core.formatters import PatchPrinter
def test_properties(patch_printer: PatchPrinter) -> None:
"""
must return non empty properties list
"""
assert patch_printer.properties()
def test_properties_required(patch_printer: PatchPrinter) -> None:
"""
must return all properties as required
"""
assert all(prop.is_required for prop in patch_printer.properties())
def test_title(patch_printer: PatchPrinter) -> None:
"""
must return non empty title
"""
assert patch_printer.title() == "ahriman"

View File

@ -72,7 +72,7 @@ def test_process_remove_base(executor: Executor, package_ahriman: Package, mocke
# must update status and remove package files
tree_clear_mock.assert_called_once_with(package_ahriman.base)
build_queue_mock.assert_called_once_with(package_ahriman.base)
patches_mock.assert_called_once_with(package_ahriman.base)
patches_mock.assert_called_once_with(package_ahriman.base, [])
status_client_mock.assert_called_once_with(package_ahriman.base)

View File

@ -49,8 +49,7 @@ def test_leaf_load(package_ahriman: Package, repository_paths: RepositoryPaths,
leaf = Leaf.load(package_ahriman, repository_paths, database)
assert leaf.package == package_ahriman
assert leaf.dependencies == {"ahriman-dependency"}
load_mock.assert_called_once_with(
pytest.helpers.anyvar(int), package_ahriman, None, repository_paths)
load_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman, [], repository_paths)
dependencies_mock.assert_called_once_with(pytest.helpers.anyvar(int))