Esempio n. 1
0
def test_full_version() -> None:
    """
    must construct full version
    """
    assert Package.full_version("1", "r2388.d30e3201",
                                "1") == "1:r2388.d30e3201-1"
    assert Package.full_version(None, "0.12.1", "1") == "0.12.1-1"
Esempio n. 2
0
async def test_get(client: TestClient, package_ahriman: Package,
                   package_python_schedule: Package) -> None:
    """
    must return status for all packages
    """
    await client.post(f"/api/v1/packages/{package_ahriman.base}",
                      json={
                          "status": BuildStatusEnum.Success.value,
                          "package": package_ahriman.view()
                      })
    await client.post(f"/api/v1/packages/{package_python_schedule.base}",
                      json={
                          "status": BuildStatusEnum.Success.value,
                          "package": package_python_schedule.view()
                      })

    response = await client.get("/api/v1/packages")
    assert response.status == 200

    packages = [
        Package.from_json(item["package"]) for item in await response.json()
    ]
    assert packages
    assert {package.base
            for package in packages
            } == {package_ahriman.base, package_python_schedule.base}
Esempio n. 3
0
def test_is_outdated_true(package_ahriman: Package,
                          repository_paths: RepositoryPaths) -> None:
    """
    must be outdated for the new version
    """
    other = Package.from_json(package_ahriman.view())
    other.version = other.version.replace("-1", "-2")

    assert package_ahriman.is_outdated(other, repository_paths)
Esempio n. 4
0
def test_load_from_aur(package_ahriman: Package, pyalpm_handle: MagicMock,
                       mocker: MockerFixture) -> None:
    """
    must load package from AUR
    """
    load_mock = mocker.patch("ahriman.models.package.Package.from_aur")

    Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
    load_mock.assert_called_once()
Esempio n. 5
0
def test_load_from_build(package_ahriman: Package, pyalpm_handle: MagicMock,
                         mocker: MockerFixture) -> None:
    """
    must load package from build directory
    """
    mocker.patch("pathlib.Path.is_dir", return_value=True)
    load_mock = mocker.patch("ahriman.models.package.Package.from_build")

    Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
    load_mock.assert_called_once()
Esempio n. 6
0
def test_dependencies_failed(mocker: MockerFixture) -> None:
    """
    must raise exception if there are errors during srcinfo load
    """
    mocker.patch("pathlib.Path.read_text", return_value="")
    mocker.patch("ahriman.models.package.parse_srcinfo",
                 return_value=({
                     "packages": {}
                 }, ["an error"]))

    with pytest.raises(InvalidPackageInfo):
        Package.dependencies(Path("path"))
Esempio n. 7
0
def test_from_build_failed(package_ahriman: Package,
                           mocker: MockerFixture) -> None:
    """
    must raise exception if there are errors during srcinfo load
    """
    mocker.patch("pathlib.Path.read_text", return_value="")
    mocker.patch("ahriman.models.package.parse_srcinfo",
                 return_value=({
                     "packages": {}
                 }, ["an error"]))

    with pytest.raises(InvalidPackageInfo):
        Package.from_build(Path("path"), package_ahriman.aur_url)
Esempio n. 8
0
def test_from_build(package_ahriman: Package, mocker: MockerFixture,
                    resource_path_root: Path) -> None:
    """
    must construct package from srcinfo
    """
    srcinfo = (resource_path_root / "models" /
               "package_ahriman_srcinfo").read_text()
    mocker.patch("pathlib.Path.read_text", return_value=srcinfo)

    package = Package.from_build(Path("path"), package_ahriman.aur_url)
    assert package_ahriman.packages.keys() == package.packages.keys()
    package_ahriman.packages = package.packages  # we are not going to test PackageDescription here
    assert package_ahriman == package
Esempio n. 9
0
def test_load_failure(package_ahriman: Package, pyalpm_handle: MagicMock,
                      mocker: MockerFixture) -> None:
    """
    must raise InvalidPackageInfo on exception
    """
    mocker.patch("pathlib.Path.is_dir",
                 side_effect=InvalidPackageInfo("exception!"))
    with pytest.raises(InvalidPackageInfo):
        Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)

    mocker.patch("pathlib.Path.is_dir", side_effect=Exception())
    with pytest.raises(InvalidPackageInfo):
        Package.load(Path("path"), pyalpm_handle, package_ahriman.aur_url)
Esempio n. 10
0
def package_ahriman(
        package_description_ahriman: PackageDescription) -> Package:
    packages = {"ahriman": package_description_ahriman}
    return Package(base="ahriman",
                   version="0.12.1-1",
                   aur_url="https://aur.archlinux.org",
                   packages=packages)
Esempio n. 11
0
    async def post(self) -> Response:
        """
        update package build status

        JSON body must be supplied, the following model is used:
        {
            "status": "unknown",   # package build status string, must be valid `BuildStatusEnum`
            "package": {}  # package body (use `dataclasses.asdict` to generate one), optional.
                           # Must be supplied in case if package base is unknown
        }

        :return: 204 on success
        """
        base = self.request.match_info["package"]
        data = await self.request.json()

        try:
            package = Package.from_json(
                data["package"]) if "package" in data else None
            status = BuildStatusEnum(data["status"])
        except Exception as e:
            raise HTTPBadRequest(text=str(e))

        try:
            self.service.update(base, status, package)
        except UnknownPackage:
            raise HTTPBadRequest(
                text=f"Package {base} is unknown, but no package body set")

        return HTTPNoContent()
Esempio n. 12
0
    def updates_aur(self, filter_packages: Iterable[str],
                    no_vcs: bool) -> List[Package]:
        """
        check AUR for updates
        :param filter_packages: do not check every package just specified in the list
        :param no_vcs: do not check VCS packages
        :return: list of packages which are out-of-dated
        """
        result: List[Package] = []

        for local in self.packages():
            if local.base in self.ignore_list:
                continue
            if local.is_vcs and no_vcs:
                continue
            if filter_packages and local.base not in filter_packages:
                continue

            try:
                remote = Package.load(local.base, self.pacman, self.aur_url)
                if local.is_outdated(remote, self.paths):
                    self.reporter.set_pending(local.base)
                    result.append(remote)
            except Exception:
                self.reporter.set_failed(local.base)
                self.logger.exception(
                    f"could not load remote package {local.base}")
                continue

        return result
Esempio n. 13
0
def test_actual_version(package_ahriman: Package,
                        repository_paths: RepositoryPaths) -> None:
    """
    must return same actual_version as version is
    """
    assert package_ahriman.actual_version(
        repository_paths) == package_ahriman.version
Esempio n. 14
0
def test_dependencies_with_version(mocker: MockerFixture,
                                   resource_path_root: Path) -> None:
    """
    must load correct list of dependencies with version
    """
    srcinfo = (resource_path_root / "models" /
               "package_yay_srcinfo").read_text()
    mocker.patch("pathlib.Path.read_text", return_value=srcinfo)

    assert Package.dependencies(Path("path")) == {"git", "go", "pacman"}
Esempio n. 15
0
def test_from_archive(package_ahriman: Package, pyalpm_handle: MagicMock,
                      mocker: MockerFixture) -> None:
    """
    must construct package from alpm library
    """
    mocker.patch(
        "ahriman.models.package_description.PackageDescription.from_package",
        return_value=package_ahriman.packages[package_ahriman.base])
    assert Package.from_archive(Path("path"), pyalpm_handle,
                                package_ahriman.aur_url) == package_ahriman
Esempio n. 16
0
def package_python_schedule(
        package_description_python_schedule: PackageDescription,
        package_description_python2_schedule: PackageDescription) -> Package:
    packages = {
        "python-schedule": package_description_python_schedule,
        "python2-schedule": package_description_python2_schedule
    }
    return Package(base="python-schedule",
                   version="1.0.0-2",
                   aur_url="https://aur.archlinux.org",
                   packages=packages)
Esempio n. 17
0
def test_actual_version_srcinfo_failed(package_tpacpi_bat_git: Package,
                                       repository_paths: RepositoryPaths,
                                       mocker: MockerFixture) -> None:
    """
    must return same version in case if exception occurred
    """
    mocker.patch("ahriman.models.package.Package._check_output",
                 side_effect=Exception())
    mocker.patch("ahriman.core.build_tools.task.Task.fetch")

    assert package_tpacpi_bat_git.actual_version(
        repository_paths) == package_tpacpi_bat_git.version
Esempio n. 18
0
 def load(cls: Type[Leaf], package: Package) -> Leaf:
     """
     load leaf from package with dependencies
     :param package: package properties
     :return: loaded class
     """
     clone_dir = Path(tempfile.mkdtemp())
     try:
         Task.fetch(clone_dir, package.git_url)
         dependencies = Package.dependencies(clone_dir)
     finally:
         shutil.rmtree(clone_dir, ignore_errors=True)
     return cls(package, dependencies)
Esempio n. 19
0
 def packages(self) -> List[Package]:
     """
     generate list of repository packages
     :return: list of packages properties
     """
     result: Dict[str, Package] = {}
     for full_path in filter(package_like, self.paths.repository.iterdir()):
         try:
             local = Package.load(full_path, self.pacman, self.aur_url)
             result.setdefault(local.base, local).packages.update(local.packages)
         except Exception:
             self.logger.exception(f"could not load package from {full_path}")
             continue
     return list(result.values())
Esempio n. 20
0
def test_from_aur(package_ahriman: Package, mocker: MockerFixture) -> None:
    """
    must construct package from aur
    """
    mock = MagicMock()
    type(mock).name = PropertyMock(return_value=package_ahriman.base)
    type(mock).package_base = PropertyMock(return_value=package_ahriman.base)
    type(mock).version = PropertyMock(return_value=package_ahriman.version)
    mocker.patch("aur.info", return_value=mock)

    package = Package.from_aur(package_ahriman.base, package_ahriman.aur_url)
    assert package_ahriman.base == package.base
    assert package_ahriman.version == package.version
    assert package_ahriman.packages.keys() == package.packages.keys()
Esempio n. 21
0
def test_actual_version_vcs(package_tpacpi_bat_git: Package,
                            repository_paths: RepositoryPaths,
                            mocker: MockerFixture,
                            resource_path_root: Path) -> None:
    """
    must return valid actual_version for VCS package
    """
    srcinfo = (resource_path_root / "models" /
               "package_tpacpi-bat-git_srcinfo").read_text()
    mocker.patch("ahriman.models.package.Package._check_output",
                 return_value=srcinfo)
    mocker.patch("ahriman.core.build_tools.task.Task.fetch")

    assert package_tpacpi_bat_git.actual_version(
        repository_paths) == "3.1.r13.g4959b52-1"
Esempio n. 22
0
def test_actual_version_vcs_failed(package_tpacpi_bat_git: Package,
                                   repository_paths: RepositoryPaths,
                                   mocker: MockerFixture) -> None:
    """
    must return same version in case if exception occurred
    """
    mocker.patch("pathlib.Path.read_text", return_value="")
    mocker.patch("ahriman.models.package.parse_srcinfo",
                 return_value=({
                     "packages": {}
                 }, ["an error"]))
    mocker.patch("ahriman.models.package.Package._check_output")
    mocker.patch("ahriman.core.build_tools.task.Task.fetch")

    assert package_tpacpi_bat_git.actual_version(
        repository_paths) == package_tpacpi_bat_git.version
Esempio n. 23
0
async def test_get(client: TestClient, package_ahriman: Package) -> None:
    """
    must generate web service status correctly
    """
    await client.post(f"/api/v1/packages/{package_ahriman.base}",
                      json={
                          "status": BuildStatusEnum.Success.value,
                          "package": package_ahriman.view()
                      })

    response = await client.get("/api/v1/status")
    assert response.status == 200

    json = await response.json()
    assert json["version"] == version.__version__
    assert json["packages"]
    assert json["packages"]["total"] == 1
Esempio n. 24
0
    def add(self, package: Package, status: BuildStatusEnum) -> None:
        """
        add new package with status
        :param package: package properties
        :param status: current package build status
        """
        payload = {"status": status.value, "package": package.view()}

        try:
            response = requests.post(self._package_url(package.base),
                                     json=payload)
            response.raise_for_status()
        except requests.exceptions.HTTPError as e:
            self.logger.exception(
                f"could not add {package.base}: {exception_response_text(e)}")
        except Exception:
            self.logger.exception(f"could not add {package.base}")
Esempio n. 25
0
    def process_update(self, packages: Iterable[Path]) -> Path:
        """
        sign packages, add them to repository and update repository database
        :param packages: list of filenames to run
        :return: path to repository database
        """
        def update_single(fn: Optional[str], base: str) -> None:
            if fn is None:
                self.logger.warning(
                    f"received empty package name for base {base}")
                return  # suppress type checking, it never can be none actually
            # in theory it might be NOT packages directory, but we suppose it is
            full_path = self.paths.packages / fn
            files = self.sign.sign_package(full_path, base)
            for src in files:
                dst = self.paths.repository / src.name
                shutil.move(src, dst)
            package_path = self.paths.repository / fn
            self.repo.add(package_path)

        # we are iterating over bases, not single packages
        updates: Dict[str, Package] = {}
        for filename in packages:
            try:
                local = Package.load(filename, self.pacman, self.aur_url)
                updates.setdefault(local.base,
                                   local).packages.update(local.packages)
            except Exception:
                self.logger.exception(
                    f"could not load package from {filename}")

        for local in updates.values():
            try:
                for description in local.packages.values():
                    update_single(description.filename, local.base)
                self.reporter.set_success(local)
            except Exception:
                self.reporter.set_failed(local.base)
                self.logger.exception(f"could not process {local.base}")
        self.clear_packages()

        return self.repo.repo_path
Esempio n. 26
0
    def get(self, base: Optional[str]) -> List[Tuple[Package, BuildStatus]]:
        """
        get package status
        :param base: package base to get
        :return: list of current package description and status if it has been found
        """
        try:
            response = requests.get(self._package_url(base or ""))
            response.raise_for_status()

            status_json = response.json()
            return [(Package.from_json(package["package"]),
                     BuildStatus.from_json(package["status"]))
                    for package in status_json]
        except requests.exceptions.HTTPError as e:
            self.logger.exception(
                f"could not get {base}: {exception_response_text(e)}")
        except Exception:
            self.logger.exception(f"could not get {base}")
        return []
Esempio n. 27
0
    def updates_manual(self) -> List[Package]:
        """
        check for packages for which manual update has been requested
        :return: list of packages which are out-of-dated
        """
        result: List[Package] = []
        known_bases = {package.base for package in self.packages()}

        for fn in self.paths.manual.iterdir():
            try:
                local = Package.load(fn, self.pacman, self.aur_url)
                result.append(local)
                if local.base not in known_bases:
                    self.reporter.set_unknown(local)
                else:
                    self.reporter.set_pending(local.base)
            except Exception:
                self.logger.exception(f"could not add package from {fn}")
        self.clear_manual()

        return result
Esempio n. 28
0
def package_tpacpi_bat_git() -> Package:
    return Package(base="tpacpi-bat-git",
                   version="3.1.r12.g4959b52-1",
                   aur_url="https://aur.archlinux.org",
                   packages={"tpacpi-bat-git": PackageDescription()})
Esempio n. 29
0
 def process_update(paths: Iterable[Path]) -> None:
     updated = [Package.load(path, self.repository.pacman, self.repository.aur_url) for path in paths]
     self.repository.process_update(paths)
     self._finalize(updated)
Esempio n. 30
0
 def process_dependencies(path: Path) -> None:
     if without_dependencies:
         return
     dependencies = Package.dependencies(path)
     self.add(dependencies.difference(known_packages), without_dependencies)