diff --git a/README.md b/README.md index def262f..28b94cf 100644 --- a/README.md +++ b/README.md @@ -116,17 +116,21 @@ More information about the shell integration can be found in the [shell integrat ## Uninstallation -To uninstall the Aikido Safe Chain, you can run the following command: +To uninstall the Aikido Safe Chain, use our one-line uninstaller: -1. **Remove all aliases from your shell** by running: - ```shell - safe-chain teardown - ``` -2. **Uninstall the Aikido Safe Chain package** using npm: - ```shell - npm uninstall -g @aikidosec/safe-chain - ``` -3. **❗Restart your terminal** to remove the aliases. +### Unix/Linux/macOS + +```shell +curl -fsSL https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/uninstall-safe-chain.sh | sh +``` + +### Windows (PowerShell) + +```powershell +iex (iwr "https://raw.githubusercontent.com/AikidoSec/safe-chain/main/install-scripts/uninstall-safe-chain.ps1" -UseBasicParsing) +``` + +**❗Restart your terminal** after uninstalling to ensure all aliases are removed. # Configuration diff --git a/install-scripts/uninstall-safe-chain.ps1 b/install-scripts/uninstall-safe-chain.ps1 new file mode 100644 index 0000000..f1e1ff7 --- /dev/null +++ b/install-scripts/uninstall-safe-chain.ps1 @@ -0,0 +1,165 @@ +# Uninstalls safe-chain from Windows +# +# Usage with "iex (iwr {url} -UseBasicParsing)" --> See README.md + +# Use HOME on Unix, USERPROFILE on Windows (PowerShell Core is cross-platform) +$HomeDir = if ($env:HOME) { $env:HOME } else { $env:USERPROFILE } +$InstallDir = Join-Path $HomeDir ".safe-chain/bin" + +# Helper functions +function Write-Info { + param([string]$Message) + Write-Host "[INFO] $Message" -ForegroundColor Green +} + +function Write-Warn { + param([string]$Message) + Write-Host "[WARN] $Message" -ForegroundColor Yellow +} + +function Write-Error-Custom { + param([string]$Message) + Write-Host "[ERROR] $Message" -ForegroundColor Red + exit 1 +} + +# Check and uninstall npm global package if present +function Remove-NpmInstallation { + # Check if npm is available + if (-not (Get-Command npm -ErrorAction SilentlyContinue)) { + return + } + + # Check if safe-chain is installed as an npm global package + npm list -g @aikidosec/safe-chain 2>&1 | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Info "Detected npm global installation of @aikidosec/safe-chain" + Write-Info "Uninstalling npm version before installing binary version..." + + npm uninstall -g @aikidosec/safe-chain 2>&1 | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Info "Successfully uninstalled npm version" + } + else { + Write-Warn "Failed to uninstall npm version automatically" + Write-Warn "Please run: npm uninstall -g @aikidosec/safe-chain" + } + } +} + +# Check and uninstall Volta-managed package if present +function Remove-VoltaInstallation { + # Check if Volta is available + if (-not (Get-Command volta -ErrorAction SilentlyContinue)) { + return + } + + # Volta manages global packages in its own directory + # Check if safe-chain is installed via Volta + volta list safe-chain 2>&1 | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Info "Detected Volta installation of @aikidosec/safe-chain" + Write-Info "Uninstalling Volta version before installing binary version..." + + volta uninstall @aikidosec/safe-chain 2>&1 | Out-Null + if ($LASTEXITCODE -eq 0) { + Write-Info "Successfully uninstalled Volta version" + } + else { + Write-Warn "Failed to uninstall Volta version automatically" + Write-Warn "Please run: volta uninstall @aikidosec/safe-chain" + } + } +} + +# Main uninstallation +function Uninstall-SafeChain { + Write-Info "Uninstalling safe-chain..." + + # Run teardown if safe-chain is available + # Check for both safe-chain.exe (Windows) and safe-chain (Unix) since PowerShell Core runs on all platforms + $safeChainExe = Join-Path $InstallDir "safe-chain.exe" + $safeChainBin = Join-Path $InstallDir "safe-chain" + + $safeChainPath = $null + if (Test-Path $safeChainExe) { + $safeChainPath = $safeChainExe + } + elseif (Test-Path $safeChainBin) { + $safeChainPath = $safeChainBin + } + + if ($safeChainPath) { + Write-Info "Running safe-chain teardown..." + try { + & $safeChainPath teardown + if ($LASTEXITCODE -ne 0) { + Write-Warn "safe-chain teardown encountered issues, continuing with uninstallation..." + } + } + catch { + Write-Warn "safe-chain teardown encountered issues: $_" + Write-Warn "Continuing with uninstallation..." + } + } + elseif (Get-Command safe-chain -ErrorAction SilentlyContinue) { + Write-Info "Running safe-chain teardown..." + try { + safe-chain teardown + if ($LASTEXITCODE -ne 0) { + Write-Warn "safe-chain teardown encountered issues, continuing with uninstallation..." + } + } + catch { + Write-Warn "safe-chain teardown encountered issues: $_" + Write-Warn "Continuing with uninstallation..." + } + } + else { + Write-Warn "safe-chain command not found. Proceeding with uninstallation." + } + + # Remove npm and Volta installations + Remove-NpmInstallation + Remove-VoltaInstallation + + # Remove installation directory + if (Test-Path $InstallDir) { + Write-Info "Removing installation directory: $InstallDir" + try { + Remove-Item -Path $InstallDir -Recurse -Force + Write-Info "Successfully removed installation directory" + } + catch { + Write-Error-Custom "Failed to remove $InstallDir : $_" + } + } + else { + Write-Info "Installation directory $InstallDir does not exist. Nothing to remove." + } + + # Also try to remove the parent .safe-chain directory if it's empty + $parentDir = Split-Path $InstallDir -Parent + if (Test-Path $parentDir) { + $items = Get-ChildItem -Path $parentDir -Force + if ($items.Count -eq 0) { + Write-Info "Removing empty parent directory: $parentDir" + try { + Remove-Item -Path $parentDir -Force + } + catch { + Write-Warn "Could not remove empty parent directory: $_" + } + } + } + + Write-Info "safe-chain has been uninstalled successfully!" +} + +# Run uninstallation +try { + Uninstall-SafeChain +} +catch { + Write-Error-Custom "Uninstallation failed: $_" +} diff --git a/install-scripts/uninstall-safe-chain.sh b/install-scripts/uninstall-safe-chain.sh new file mode 100755 index 0000000..4b2d7ec --- /dev/null +++ b/install-scripts/uninstall-safe-chain.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +# Downloads and installs safe-chain, depending on the operating system and architecture +# +# Usage with "curl -fsSL {url} | sh" --> See README.md + +set -e # Exit on error + +# Configuration +INSTALL_DIR="${HOME}/.safe-chain/bin" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Helper functions +info() { + printf "${GREEN}[INFO]${NC} %s\n" "$1" +} + +warn() { + printf "${YELLOW}[WARN]${NC} %s\n" "$1" +} + +error() { + printf "${RED}[ERROR]${NC} %s\n" "$1" >&2 + exit 1 +} + +# Check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Check and uninstall npm global package if present +remove_npm_installation() { + if ! command_exists npm; then + return + fi + + # Check if safe-chain is installed as an npm global package + if npm list -g @aikidosec/safe-chain >/dev/null 2>&1; then + info "Detected npm global installation of @aikidosec/safe-chain" + info "Uninstalling npm version before installing binary version..." + + if npm uninstall -g @aikidosec/safe-chain >/dev/null 2>&1; then + info "Successfully uninstalled npm version" + else + warn "Failed to uninstall npm version automatically" + warn "Please run: npm uninstall -g @aikidosec/safe-chain" + fi + fi +} + +# Check and uninstall Volta-managed package if present +remove_volta_installation() { + if ! command_exists volta; then + return + fi + + # Volta manages global packages in its own directory + # Check if safe-chain is installed via Volta + if volta list safe-chain >/dev/null 2>&1; then + info "Detected Volta installation of @aikidosec/safe-chain" + info "Uninstalling Volta version before installing binary version..." + + if volta uninstall @aikidosec/safe-chain >/dev/null 2>&1; then + info "Successfully uninstalled Volta version" + else + warn "Failed to uninstall Volta version automatically" + warn "Please run: volta uninstall @aikidosec/safe-chain" + fi + fi +} + +# Main uninstallation +main() { + SAFE_CHAIN_LOCATION="$INSTALL_DIR/safe-chain" + + if [ -x "$SAFE_CHAIN_LOCATION" ]; then + info "Running safe-chain teardown..." + "$SAFE_CHAIN_LOCATION" teardown || warn "safe-chain teardown encountered issues, continuing with uninstallation..." + elif command_exists safe-chain; then + info "Running safe-chain teardown..." + safe-chain teardown || warn "safe-chain teardown encountered issues, continuing with uninstallation..." + else + warn "safe-chain command not found. Proceeding with uninstallation." + fi + + remove_npm_installation + remove_volta_installation + + # Remove install dir recursively if it exists + if [ -d "$INSTALL_DIR" ]; then + info "Removing installation directory $INSTALL_DIR" + rm -rf "$INSTALL_DIR" || error "Failed to remove $INSTALL_DIR" + else + info "Installation directory $INSTALL_DIR does not exist. Nothing to remove." + fi +} + +main "$@"