diff --git a/ruyi/ruyipkg/pkg_cli.py b/ruyi/ruyipkg/pkg_cli.py index 33bc4210..9cc5ee1c 100644 --- a/ruyi/ruyipkg/pkg_cli.py +++ b/ruyi/ruyipkg/pkg_cli.py @@ -2,6 +2,7 @@ import os.path import pathlib import shutil +import tempfile from .host import canonicalize_host_str @@ -275,10 +276,41 @@ def do_install_binary_pkg( ) shutil.rmtree(install_root) - pathlib.Path(install_root).mkdir(parents=True, exist_ok=True) + ir_parent = pathlib.Path(install_root).resolve().parent + ir_parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix=".ruyi-tmp", dir=ir_parent) as tmp_root: + ret = do_install_binary_pkg_to( + config, + mr, + pm, + canonicalized_host, + fetch_only, + tmp_root, + ) + if ret != 0: + return ret + os.rename(tmp_root, install_root) + + log.I( + f"package [green]{pkg_name}[/green] installed to [yellow]{install_root}[/yellow]" + ) + return 0 + + +def do_install_binary_pkg_to( + config: GlobalConfig, + mr: MetadataRepo, + pm: PackageManifest, + canonicalized_host: str, + fetch_only: bool, + install_root: str, +) -> int: + bm = pm.binary_metadata + assert bm is not None dfs = pm.distfiles() + pkg_name = pm.name_for_installation distfiles_for_host = bm.get_distfile_names_for_host(canonicalized_host) if not distfiles_for_host: log.F( @@ -305,10 +337,6 @@ def do_install_binary_pkg( ) df.unpack(install_root) - log.I( - f"package [green]{pkg_name}[/green] installed to [yellow]{install_root}[/yellow]" - ) - return 0 @@ -334,10 +362,38 @@ def do_install_blob_pkg( ) shutil.rmtree(install_root) - pathlib.Path(install_root).mkdir(parents=True, exist_ok=True) + ir_parent = pathlib.Path(install_root).resolve().parent + ir_parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix=".ruyi-tmp", dir=ir_parent) as tmp_root: + ret = do_install_blob_pkg_to( + config, + mr, + pm, + fetch_only, + tmp_root, + ) + if ret != 0: + return ret + os.rename(tmp_root, install_root) - dfs = pm.distfiles() + log.I( + f"package [green]{pkg_name}[/green] installed to [yellow]{install_root}[/yellow]" + ) + return 0 + +def do_install_blob_pkg_to( + config: GlobalConfig, + mr: MetadataRepo, + pm: PackageManifest, + fetch_only: bool, + install_root: str, +) -> int: + bm = pm.blob_metadata + assert bm is not None + + pkg_name = pm.name_for_installation + dfs = pm.distfiles() distfile_names = bm.get_distfile_names() if not distfile_names: log.F(f"package [green]{pkg_name}[/green] declares no blob distfile") @@ -362,8 +418,4 @@ def do_install_blob_pkg( ) df.unpack_or_symlink(install_root) - log.I( - f"package [green]{pkg_name}[/green] installed to [yellow]{install_root}[/yellow]" - ) - return 0 diff --git a/ruyi/ruyipkg/unpack.py b/ruyi/ruyipkg/unpack.py index 3fe9eb05..ad161b60 100644 --- a/ruyi/ruyipkg/unpack.py +++ b/ruyi/ruyipkg/unpack.py @@ -1,8 +1,6 @@ import os -import pathlib import shutil import subprocess -import tempfile from typing import NoReturn from .. import log @@ -15,26 +13,6 @@ def do_unpack( dest: str | None, strip_components: int, unpack_method: UnpackMethod, -) -> None: - if dest is None: - return _do_unpack_inner(filename, dest, strip_components, unpack_method) - - # dest is a directory, create a temp directory besides it - dest_path = pathlib.Path(dest) - dest_parent = dest_path.resolve().parent - with tempfile.TemporaryDirectory( - prefix=f".{dest_path.name}.tmp", - dir=dest_parent, - ) as tmpdir_path: - _do_unpack_inner(filename, tmpdir_path, strip_components, unpack_method) - os.replace(tmpdir_path, dest) - - -def _do_unpack_inner( - filename: str, - dest: str | None, - strip_components: int, - unpack_method: UnpackMethod, ) -> None: match unpack_method: case UnpackMethod.AUTO: