4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
166 lines
4.3 KiB
Python
166 lines
4.3 KiB
Python
from __future__ import annotations
|
|
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from config.constants.paths import OPENSRE_HOME_DIR
|
|
|
|
|
|
def _is_windows() -> bool:
|
|
return sys.platform == "win32"
|
|
|
|
|
|
def _is_binary_install() -> bool:
|
|
return bool(getattr(sys, "frozen", False))
|
|
|
|
|
|
def _remove_path(p: Path) -> tuple[bool, str | None]:
|
|
if not p.exists() and not p.is_symlink():
|
|
return True, None
|
|
try:
|
|
if p.is_dir():
|
|
shutil.rmtree(p)
|
|
else:
|
|
p.unlink()
|
|
return True, None
|
|
except OSError as exc:
|
|
return False, str(exc)
|
|
|
|
|
|
def _pip_uninstall() -> int:
|
|
result = subprocess.run(
|
|
[sys.executable, "-m", "pip", "uninstall", "--yes", "opensre"],
|
|
check=False,
|
|
capture_output=True,
|
|
)
|
|
return result.returncode
|
|
|
|
|
|
def _data_dirs() -> list[Path]:
|
|
return [
|
|
OPENSRE_HOME_DIR,
|
|
Path.home() / ".config" / "opensre",
|
|
]
|
|
|
|
|
|
def _is_onedir_binary(exe_path: Path) -> bool:
|
|
return exe_path.parent.name == ".opensre-app" and (exe_path.parent / "_internal").is_dir()
|
|
|
|
|
|
def _launcher_for_binary(exe_path: Path) -> Path | None:
|
|
launcher = shutil.which("opensre")
|
|
if not launcher:
|
|
return None
|
|
launcher_path = Path(launcher)
|
|
try:
|
|
if launcher_path.resolve() == exe_path.resolve():
|
|
return launcher_path
|
|
except OSError:
|
|
return None
|
|
return None
|
|
|
|
|
|
def _binary_install_paths(exe_path: Path | None = None) -> list[Path]:
|
|
exe = exe_path or Path(sys.executable)
|
|
paths: list[Path] = []
|
|
if launcher := _launcher_for_binary(exe):
|
|
paths.append(launcher)
|
|
if _is_onedir_binary(exe):
|
|
paths.append(exe.parent)
|
|
else:
|
|
paths.append(exe)
|
|
|
|
deduped: list[Path] = []
|
|
seen: set[str] = set()
|
|
for path in paths:
|
|
key = str(path)
|
|
if key in seen:
|
|
continue
|
|
seen.add(key)
|
|
deduped.append(path)
|
|
return deduped
|
|
|
|
|
|
def run_uninstall(*, yes: bool = False) -> int:
|
|
dirs = _data_dirs()
|
|
binary = _is_binary_install()
|
|
binary_paths = _binary_install_paths() if binary else []
|
|
|
|
print()
|
|
print(" The following will be permanently deleted:")
|
|
print()
|
|
for d in dirs:
|
|
tag = "found" if d.exists() else "not found"
|
|
print(f" {d} ({tag})")
|
|
if binary:
|
|
for path in binary_paths:
|
|
print(f" {path} (binary)")
|
|
else:
|
|
print(" pip package: opensre")
|
|
print()
|
|
|
|
if not yes:
|
|
try:
|
|
import questionary
|
|
|
|
confirmed = questionary.confirm(
|
|
" Uninstall opensre from this machine?", default=False
|
|
).ask()
|
|
except (EOFError, KeyboardInterrupt):
|
|
print("\n Aborted.")
|
|
return 1
|
|
if not confirmed:
|
|
print(" Cancelled.")
|
|
return 0
|
|
|
|
print()
|
|
|
|
any_error = False
|
|
|
|
for d in dirs:
|
|
if not d.exists():
|
|
print(f" skipped {d} (not found)")
|
|
continue
|
|
ok, err = _remove_path(d)
|
|
if ok:
|
|
print(f" deleted {d}")
|
|
else:
|
|
print(f" error {d}: {err}", file=sys.stderr)
|
|
any_error = True
|
|
|
|
if binary:
|
|
for path in binary_paths:
|
|
ok, err = _remove_path(path)
|
|
if ok:
|
|
print(f" deleted {path}")
|
|
else:
|
|
print(f" error {path}: {err}", file=sys.stderr)
|
|
any_error = True
|
|
else:
|
|
print(" running pip uninstall opensre")
|
|
rc = _pip_uninstall()
|
|
if rc == 0:
|
|
print(" deleted pip package opensre")
|
|
else:
|
|
print(f" error pip uninstall failed (exit {rc})", file=sys.stderr)
|
|
if _is_windows():
|
|
hint = "pip uninstall opensre"
|
|
else:
|
|
hint = "pip uninstall opensre (or: pipx uninstall opensre)"
|
|
print(f" retry manually: {hint}", file=sys.stderr)
|
|
any_error = True
|
|
|
|
print()
|
|
|
|
if any_error:
|
|
print(" Uninstall finished with errors. See above for details.", file=sys.stderr)
|
|
return 1
|
|
|
|
print(" opensre has been uninstalled.")
|
|
print()
|
|
print(" Your config and data have been removed.")
|
|
print(" To reinstall: curl -fsSL https://install.opensre.com | bash")
|
|
return 0
|