diff --git a/src/python/jw/pkg/lib/Distro.py b/src/python/jw/pkg/lib/Distro.py index 05ca946f..c0f331b9 100644 --- a/src/python/jw/pkg/lib/Distro.py +++ b/src/python/jw/pkg/lib/Distro.py @@ -109,15 +109,51 @@ class Distro(abc.ABC): # -- install + # Pass names to the package manager @abc.abstractmethod async def _install(self, names: Iterable[str], only_update: bool) -> None: pass + # Default implementation assumes package manager can handle local files. + # Not true for all distros. Override if Distro knows better. + async def _install_local_files(self, paths: Iterable[str], only_update: bool) -> None: + await self._install(paths, only_update=only_update) + + # Download first and then install. Override if Distro knows better. + async def _install_urls(self, urls: Iterable[str], only_update: bool) -> None: + import tempfile + from .util import copy + with tempfile.TemporaryDirectory(prefix='jw-pkg-') as tmp: + paths: list[str] = [] + for url in urls: + paths.append(await copy(url, tmp)) + await self._install_local_files(paths, only_update=only_update) + + # Default implementation installs in two steps: + # - Download URLs into local directories and install + # - Pass names to package manager + # Override if Distro knows better. + async def _install_urls_and_names(self, packages: Iterable[str], only_update: bool) -> None: + urls: list[str] = [] + names: list[str] = [] + for package in packages: + if package[0] == '/': + urls.append('file://' + package) + continue + if package.find('://') != -1: + urls.append(package) + continue + names.append(package) + if urls: + await self._install_urls(urls, only_update=only_update) + if names: + await self._install(names, only_update=only_update) + async def install(self, names: Iterable[str], only_update: bool=False) -> None: if not names: log(WARNING, f'No packages specified for installation') return - return await self._install(names, only_update=only_update) + await self._install_urls_and_names(names, only_update=only_update) # -- delete