support provides in aur

This commit is contained in:
2025-06-26 11:05:15 +03:00
parent 7f223ecc0a
commit 68a628d393
7 changed files with 79 additions and 32 deletions

View File

@ -133,18 +133,18 @@ class Application(ApplicationPackages, ApplicationRepository):
if not process_dependencies or not packages:
return packages
def missing_dependencies(source: Iterable[Package]) -> dict[str, str | None]:
def missing_dependencies(sources: Iterable[Package]) -> dict[str, str | None]:
# append list of known packages with packages which are in current sources
satisfied_packages = known_packages | {
single
for package in source
for single in package.packages_full
for source in sources
for single in source.packages_full
}
return {
dependency: package.packager
for package in source
for dependency in package.depends_build
dependency: source.packager
for source in sources
for dependency in source.depends_build
if dependency not in satisfied_packages
}
@ -156,7 +156,7 @@ class Application(ApplicationPackages, ApplicationRepository):
# there is local cache, load package from it
leaf = Package.from_build(source_dir, self.repository.architecture, packager)
else:
leaf = Package.from_aur(package_name, packager)
leaf = Package.from_aur(package_name, packager, include_provides=True)
portion[leaf.base] = leaf
# register package in the database

View File

@ -223,22 +223,32 @@ class Pacman(LazyLogging):
return result
def package(self, package_name: str) -> Generator[Package, None, None]:
def package(self, package_name: str, include_provides: bool = False) -> Generator[Package, None, None]:
"""
retrieve list of the packages from the repository by name
retrieve list of the packages from the repository by name. If ``include_provides`` is set to ``True``, then
additionally this method will search through :attr:`alpm.Package.provides`; these packages will be returned
after exact match
Args:
package_name(str): package name to search
include_provides(bool, optional): search by provides if no exact match found (Default value = False)
Yields:
Package: list of packages which were returned by the query
"""
def is_package_provided(package: Package) -> bool:
return package_name in package.provides
for database in self.handle.get_syncdbs():
package = database.get_pkg(package_name)
if package is None:
continue
yield package
if include_provides:
for database in self.handle.get_syncdbs():
yield from filter(is_package_provided, database.search(package_name))
def packages(self) -> set[str]:
"""
get list of packages known for alpm

View File

@ -113,13 +113,17 @@ class AUR(Remote):
response = self.make_request("GET", self.DEFAULT_RPC_URL, params=query)
return self.parse_response(response.json())
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
def package_info(self, package_name: str, *, pacman: Pacman | None, include_provides: bool) -> AURPackage:
"""
get package info by its name
get package info by its name. If ``include_provides`` is set to ``True``, then, in addition, this method
will perform search by :attr:`ahriman.models.aur_package.AURPackage.provides` and return first package found.
Note, however, that in this case some implementation might not provide this method and search result will might
not be stable
Args:
package_name(str): package name to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
include_provides(bool): search by provides if no exact match found
Returns:
AURPackage: package which match the package name
@ -127,21 +131,29 @@ class AUR(Remote):
Raises:
UnknownPackageError: package doesn't exist
"""
def is_package_provided(package: AURPackage) -> bool:
return package_name in package.provides
packages = self.aur_request("info", package_name)
try:
return next(package for package in packages if package.name == package_name)
except StopIteration:
if include_provides:
for stub in filter(is_package_provided, self.search(package_name, search_by="provides")):
return self.package_info(stub.package_base, pacman=pacman, include_provides=False)
raise UnknownPackageError(package_name) from None
def package_search(self, *keywords: str, pacman: Pacman | None) -> list[AURPackage]:
def package_search(self, *keywords: str, pacman: Pacman | None, search_by: str | None) -> list[AURPackage]:
"""
search package in AUR web
Args:
*keywords(str): keywords to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
search_by(str | None): search by keywords
Returns:
list[AURPackage]: list of packages which match the criteria
"""
return self.aur_request("search", *keywords, by="name-desc")
search_by = search_by or "name-desc"
return self.aur_request("search", *keywords, by=search_by)

View File

@ -107,13 +107,17 @@ class Official(Remote):
response = self.make_request("GET", self.DEFAULT_RPC_URL, params=query)
return self.parse_response(response.json())
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
def package_info(self, package_name: str, *, pacman: Pacman | None, include_provides: bool) -> AURPackage:
"""
get package info by its name
get package info by its name. If ``include_provides`` is set to ``True``, then, in addition, this method
will perform search by :attr:`ahriman.models.aur_package.AURPackage.provides` and return first package found.
Note, however, that in this case some implementation might not provide this method and search result will might
not be stable
Args:
package_name(str): package name to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
include_provides(bool): search by provides if no exact match found
Returns:
AURPackage: package which match the package name
@ -125,17 +129,20 @@ class Official(Remote):
try:
return next(package for package in packages if package.name == package_name)
except StopIteration:
# it does not support search by provides
raise UnknownPackageError(package_name) from None
def package_search(self, *keywords: str, pacman: Pacman | None) -> list[AURPackage]:
def package_search(self, *keywords: str, pacman: Pacman | None, search_by: str | None) -> list[AURPackage]:
"""
search package in AUR web
Args:
*keywords(str): keywords to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
search_by(str | None): search by keywords
Returns:
list[AURPackage]: list of packages which match the criteria
"""
return self.arch_request(*keywords, by="q")
search_by = search_by or "q"
return self.arch_request(*keywords, by=search_by)

View File

@ -38,13 +38,17 @@ class OfficialSyncdb(Official):
Still we leave search function based on the official repositories RPC.
"""
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
def package_info(self, package_name: str, *, pacman: Pacman | None, include_provides: bool) -> AURPackage:
"""
get package info by its name
get package info by its name. If ``include_provides`` is set to ``True``, then, in addition, this method
will perform search by :attr:`ahriman.models.aur_package.AURPackage.provides` and return first package found.
Note, however, that in this case some implementation might not provide this method and search result will might
not be stable
Args:
package_name(str): package name to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
include_provides(bool): search by provides if no exact match found
Returns:
AURPackage: package which match the package name
@ -56,6 +60,6 @@ class OfficialSyncdb(Official):
raise UnknownPackageError(package_name)
try:
return next(AURPackage.from_pacman(package) for package in pacman.package(package_name))
return next(AURPackage.from_pacman(package) for package in pacman.package(package_name, include_provides))
except StopIteration:
raise UnknownPackageError(package_name) from None

View File

@ -41,19 +41,23 @@ class Remote(SyncHttpClient):
"""
@classmethod
def info(cls, package_name: str, *, pacman: Pacman | None = None) -> AURPackage:
def info(cls, package_name: str, *, pacman: Pacman | None = None, include_provides: bool = False) -> AURPackage:
"""
get package info by its name
get package info by its name. If ``include_provides`` is set to ``True``, then, in addition, this method
will perform search by :attr:`ahriman.models.aur_package.AURPackage.provides` and return first package found.
Note, however, that in this case some implementation might not provide this method and search result will might
not be stable
Args:
package_name(str): package name to search
pacman(Pacman | None, optional): alpm wrapper instance, required for official repositories search
(Default value = None)
include_provides(bool, optional): search by provides if no exact match found (Default value = False)
Returns:
AURPackage: package which match the package name
"""
return cls().package_info(package_name, pacman=pacman)
return cls().package_info(package_name, pacman=pacman, include_provides=include_provides)
@classmethod
def multisearch(cls, *keywords: str, pacman: Pacman | None = None) -> list[AURPackage]:
@ -114,7 +118,7 @@ class Remote(SyncHttpClient):
raise NotImplementedError
@classmethod
def search(cls, *keywords: str, pacman: Pacman | None = None) -> list[AURPackage]:
def search(cls, *keywords: str, pacman: Pacman | None = None, search_by: str | None = None) -> list[AURPackage]:
"""
search package in AUR web
@ -122,19 +126,24 @@ class Remote(SyncHttpClient):
*keywords(str): search terms, e.g. "ahriman", "is", "cool"
pacman(Pacman | None, optional): alpm wrapper instance, required for official repositories search
(Default value = None)
search_by(str | None, optional): search by keywords (Default value = None)
Returns:
list[AURPackage]: list of packages which match the criteria
"""
return cls().package_search(*keywords, pacman=pacman)
return cls().package_search(*keywords, pacman=pacman, search_by=search_by)
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
def package_info(self, package_name: str, *, pacman: Pacman | None, include_provides: bool) -> AURPackage:
"""
get package info by its name
get package info by its name. If ``include_provides`` is set to ``True``, then, in addition, this method
will perform search by :attr:`ahriman.models.aur_package.AURPackage.provides` and return first package found.
Note, however, that in this case some implementation might not provide this method and search result will might
not be stable
Args:
package_name(str): package name to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
include_provides(bool): search by provides if no exact match found
Returns:
AURPackage: package which match the package name
@ -144,13 +153,14 @@ class Remote(SyncHttpClient):
"""
raise NotImplementedError
def package_search(self, *keywords: str, pacman: Pacman | None) -> list[AURPackage]:
def package_search(self, *keywords: str, pacman: Pacman | None, search_by: str | None) -> list[AURPackage]:
"""
search package in AUR web
Args:
*keywords(str): keywords to search
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
search_by(str | None): search by keywords
Returns:
list[AURPackage]: list of packages which match the criteria

View File

@ -213,18 +213,19 @@ class Package(LazyLogging):
)
@classmethod
def from_aur(cls, name: str, packager: str | None = None) -> Self:
def from_aur(cls, name: str, packager: str | None = None, *, include_provides: bool = False) -> Self:
"""
construct package properties from AUR page
Args:
name(str): package name (either base or normal name)
packager(str | None, optional): packager to be used for this build (Default value = None)
include_provides(bool, optional): search by provides if no exact match found (Default value = False)
Returns:
Self: package properties
"""
package = AUR.info(name)
package = AUR.info(name, include_provides=include_provides)
remote = RemoteSource(
source=PackageSource.AUR,
@ -310,7 +311,8 @@ class Package(LazyLogging):
)
@classmethod
def from_official(cls, name: str, pacman: Pacman, packager: str | None = None, *, use_syncdb: bool = True) -> Self:
def from_official(cls, name: str, pacman: Pacman, packager: str | None = None, *, use_syncdb: bool = True,
include_provides: bool = False) -> Self:
"""
construct package properties from official repository page
@ -319,11 +321,13 @@ class Package(LazyLogging):
pacman(Pacman): alpm wrapper instance
packager(str | None, optional): packager to be used for this build (Default value = None)
use_syncdb(bool, optional): use pacman databases instead of official repositories RPC (Default value = True)
include_provides(bool, optional): search by provides if no exact match found (Default value = False)
Returns:
Self: package properties
"""
package = OfficialSyncdb.info(name, pacman=pacman) if use_syncdb else Official.info(name)
impl = OfficialSyncdb if use_syncdb else Official
package = impl.info(name, pacman=pacman, include_provides=include_provides)
remote = RemoteSource(
source=PackageSource.Repository,