diff --git a/scripts/install.sh b/scripts/install.sh index 5e2e8a71..4689c812 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -111,20 +111,8 @@ check_existing_installation() { continue fi - if [[ -n "$path" ]]; then - echo -e "${MUTED}Found existing strix at: ${NC}$path" - - if [[ "$path" == *".local/bin"* ]]; then - echo -e "${MUTED}Removing old pipx installation...${NC}" - if command -v pipx >/dev/null 2>&1; then - pipx uninstall strix-agent 2>/dev/null || true - fi - rm -f "$path" 2>/dev/null || true - elif [[ -L "$path" || -f "$path" ]]; then - echo -e "${MUTED}Removing old installation...${NC}" - rm -f "$path" 2>/dev/null || true - fi - fi + echo -e "${YELLOW}Found another strix executable at: ${NC}$path" + echo -e "${MUTED}Leaving it unchanged; this installer only manages $INSTALL_DIR.${NC}" done fi } @@ -297,14 +285,7 @@ verify_installation() { if [[ "$which_strix" != "$INSTALL_DIR/strix" && "$which_strix" != "$INSTALL_DIR/strix.exe" ]]; then if [[ -n "$which_strix" ]]; then echo -e "${YELLOW}⚠ Found conflicting strix at: ${NC}$which_strix" - echo -e "${MUTED}Attempting to remove...${NC}" - - if rm -f "$which_strix" 2>/dev/null; then - echo -e "${GREEN}✓ Removed conflicting installation${NC}" - else - echo -e "${YELLOW}Could not remove automatically.${NC}" - echo -e "${MUTED}Please remove manually: ${NC}rm $which_strix" - fi + echo -e "${MUTED}Leaving it unchanged. Put $INSTALL_DIR first in PATH to use this installation.${NC}" fi fi diff --git a/tests/test_install_script.py b/tests/test_install_script.py index 67ca4843..f95acc22 100644 --- a/tests/test_install_script.py +++ b/tests/test_install_script.py @@ -136,6 +136,81 @@ def test_installer_downloads_and_runs_linux_arm64_release(tmp_path: Path) -> Non assert installed_result.stdout.strip() == f"strix {RELEASE_VERSION}" +def test_installer_leaves_unmanaged_executables_unchanged(tmp_path: Path) -> None: + repository_root = Path(__file__).resolve().parents[1] + archive_path = _create_release_archive(tmp_path) + mock_bin = _create_mock_commands(tmp_path, machine="aarch64") + environment, home_path, _ = _create_installer_environment( + tmp_path, + archive_path, + mock_bin, + ) + + unmanaged_path = mock_bin / "strix" + unmanaged_content = "#!/bin/sh\nprintf 'unmanaged strix\\n'\n" + _write_executable(unmanaged_path, unmanaged_content) + + local_bin = home_path / ".local" / "bin" + local_bin.mkdir(parents=True) + pipx_path = local_bin / "strix" + pipx_content = "#!/bin/sh\nprintf 'pipx strix\\n'\n" + _write_executable(pipx_path, pipx_content) + environment["PATH"] = f"{mock_bin}:{local_bin}:/usr/bin:/bin" + + pipx_log_path = tmp_path / "pipx.log" + environment["STRIX_TEST_PIPX_LOG"] = str(pipx_log_path) + _write_executable( + mock_bin / "pipx", + '#!/bin/sh\nprintf \'%s\\n\' "$*" >> "$STRIX_TEST_PIPX_LOG"\n', + ) + + result = _run_installer(repository_root, environment) + + assert result.returncode == 0, result.stderr + assert unmanaged_path.read_text(encoding="utf-8") == unmanaged_content + assert pipx_path.read_text(encoding="utf-8") == pipx_content + assert not pipx_log_path.exists() + assert result.stdout.count("Found another strix executable at:") == 2 + assert str(unmanaged_path) in result.stdout + assert str(pipx_path) in result.stdout + assert (home_path / ".strix/bin/strix").is_file() + + +def test_installer_does_not_remove_conflict_found_during_verification( + tmp_path: Path, +) -> None: + repository_root = Path(__file__).resolve().parents[1] + archive_path = _create_release_archive(tmp_path) + mock_bin = _create_mock_commands(tmp_path, machine="aarch64") + environment, home_path, _ = _create_installer_environment( + tmp_path, + archive_path, + mock_bin, + ) + + unmanaged_path = tmp_path / "other-bin" / "strix" + unmanaged_path.parent.mkdir() + unmanaged_content = "#!/bin/sh\nprintf 'unmanaged strix\\n'\n" + _write_executable(unmanaged_path, unmanaged_content) + environment["STRIX_TEST_UNMANAGED_PATH"] = str(unmanaged_path) + _write_executable( + mock_bin / "which", + """#!/bin/sh +if [ -x "$HOME/.strix/bin/strix" ]; then + printf '%s\\n' "$STRIX_TEST_UNMANAGED_PATH" +fi +""", + ) + + result = _run_installer(repository_root, environment) + + assert result.returncode == 0, result.stderr + assert unmanaged_path.read_text(encoding="utf-8") == unmanaged_content + assert "Found conflicting strix at:" in result.stdout + assert str(unmanaged_path) in result.stdout + assert (home_path / ".strix/bin/strix").is_file() + + def test_installer_rejects_unsupported_architecture(tmp_path: Path) -> None: repository_root = Path(__file__).resolve().parents[1] archive_path = _create_release_archive(tmp_path)