From 084169ad1b2e548ea2a363e96a607e40ad7f3bbc Mon Sep 17 00:00:00 2001 From: Ahmed Allam Date: Mon, 27 Jul 2026 23:12:58 +0000 Subject: [PATCH] perf(cli): drop legacy single-file compat from install/self-update --- scripts/install.sh | 22 +++------- strix/interface/update_check.py | 72 ++++++--------------------------- 2 files changed, 17 insertions(+), 77 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index d381eab8e..a454f6446 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -159,28 +159,16 @@ download_and_install() { fi echo -e "${MUTED}Extracting...${NC}" + # Archive contains an app bundle dir: strix-{version}-{target}/ (strix + _internal/). local extracted="strix-${specific_version}-${target}" if [ "$os" = "windows" ]; then unzip -q "$filename" - if [ -d "$extracted" ]; then - # Onedir app bundle (strix.exe + _internal/). - rm -rf "$INSTALL_DIR/_internal" "$INSTALL_DIR/strix.exe" - cp -R "$extracted/." "$INSTALL_DIR/" - else - # Legacy single-file binary. - mv "${extracted}.exe" "$INSTALL_DIR/strix.exe" - fi + rm -rf "$INSTALL_DIR/_internal" "$INSTALL_DIR/strix.exe" + cp -R "$extracted/." "$INSTALL_DIR/" else tar -xzf "$filename" - if [ -d "$extracted" ]; then - # Onedir app bundle (strix + _internal/). - rm -rf "$INSTALL_DIR/_internal" "$INSTALL_DIR/strix" - cp -R "$extracted/." "$INSTALL_DIR/" - else - # Legacy single-file binary. - rm -rf "$INSTALL_DIR/strix" - mv "$extracted" "$INSTALL_DIR/strix" - fi + rm -rf "$INSTALL_DIR/_internal" "$INSTALL_DIR/strix" + cp -R "$extracted/." "$INSTALL_DIR/" chmod 755 "$INSTALL_DIR/strix" fi diff --git a/strix/interface/update_check.py b/strix/interface/update_check.py index 01bd4ece8..15bb7f78e 100644 --- a/strix/interface/update_check.py +++ b/strix/interface/update_check.py @@ -286,7 +286,6 @@ def _download_and_replace(version: str, target: str, console: Console) -> bool: archive_ext = ".zip" if is_windows else ".tar.gz" filename = f"strix-{version}-{target}{archive_ext}" url = f"https://github.com/{GITHUB_REPO}/releases/download/v{version}/{filename}" - binary_name = f"strix-{version}-{target}" + (".exe" if is_windows else "") current_exe = Path(sys.executable).resolve() with tempfile.TemporaryDirectory() as tmp: @@ -322,41 +321,10 @@ def _download_and_replace(version: str, target: str, console: Console) -> bool: tf.extractall(tmp_dir, filter="data") # nosec B202 bundle_dir = tmp_dir / f"strix-{version}-{target}" - if bundle_dir.is_dir(): - _swap_app_bundle(bundle_dir, current_exe, is_windows=is_windows) - return True - - new_binary = tmp_dir / binary_name - if not new_binary.is_file(): - raise RuntimeError(f"unexpected archive layout in {filename}") - _swap_single_binary(new_binary, current_exe, is_windows=is_windows) + _swap_app_bundle(bundle_dir, current_exe, is_windows=is_windows) return True -def _swap_single_binary(new_binary: Path, current_exe: Path, *, is_windows: bool) -> None: - """Replace a legacy single-file binary in place.""" - new_binary.chmod(new_binary.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) - - staged = current_exe.with_name(current_exe.name + ".new") - try: - shutil.copy2(new_binary, staged) - if is_windows: - # Windows can't replace a running executable in place; move it aside first. - old = current_exe.with_name(current_exe.name + ".old") - old.unlink(missing_ok=True) - current_exe.rename(old) - try: - staged.replace(current_exe) - except Exception: - old.rename(current_exe) - raise - else: - staged.replace(current_exe) - except Exception: - staged.unlink(missing_ok=True) - raise - - def _swap_app_bundle(bundle_dir: Path, current_exe: Path, *, is_windows: bool) -> None: """Swap an onedir app bundle (exe + ``_internal/``) into place.""" exe_name = "strix.exe" if is_windows else "strix" @@ -369,39 +337,23 @@ def _swap_app_bundle(bundle_dir: Path, current_exe: Path, *, is_windows: bool) - app_dir = current_exe.parent internal = app_dir / "_internal" old_internal = app_dir / "_internal.old" - staged_internal = app_dir / "_internal.new" - staged_exe = current_exe.with_name(current_exe.name + ".new") old_exe = current_exe.with_name(current_exe.name + ".old") - shutil.rmtree(staged_internal, ignore_errors=True) shutil.rmtree(old_internal, ignore_errors=True) - staged_exe.unlink(missing_ok=True) old_exe.unlink(missing_ok=True) - shutil.copytree(new_internal, staged_internal) - shutil.copy2(new_exe, staged_exe) - - internal_moved = False - try: + if internal.is_dir(): internal.rename(old_internal) - internal_moved = True - staged_internal.rename(internal) - if is_windows: - # Windows can't replace a running executable in place; move it aside first. - current_exe.rename(old_exe) - try: - staged_exe.replace(current_exe) - except Exception: - old_exe.rename(current_exe) - raise - else: - staged_exe.replace(current_exe) - except Exception: - if internal_moved and not internal.exists() and old_internal.exists(): - old_internal.rename(internal) - shutil.rmtree(staged_internal, ignore_errors=True) - staged_exe.unlink(missing_ok=True) - raise + shutil.copytree(new_internal, internal) + + if is_windows: + # Windows can't replace a running executable in place; move it aside first. + current_exe.rename(old_exe) + shutil.copy2(new_exe, current_exe) + else: + staged_exe = current_exe.with_name(current_exe.name + ".new") + shutil.copy2(new_exe, staged_exe) + staged_exe.replace(current_exe) # Best effort: on Windows loaded DLLs/exe may resist deletion until restart. shutil.rmtree(old_internal, ignore_errors=True)