#!/usr/bin/env bash set -u TARGET="berity" ASSUME_YES=0 DRY_RUN=0 REMOVED_ANY=0 usage() { cat <<'EOF' Usage: uninstall-berity.sh [--yes] [--dry-run] [target_name] Examples: ./uninstall-berity.sh ./uninstall-berity.sh --yes ./uninstall-berity.sh --dry-run berity EOF } log() { printf '%s\n' "$*" } run() { if [ "$DRY_RUN" -eq 1 ]; then printf '[DRY-RUN] %q ' "$@" printf '\n' return 0 fi "$@" } run_root() { if [ "$(id -u)" -eq 0 ]; then run "$@" else run sudo "$@" fi } is_cmd() { command -v "$1" >/dev/null 2>&1 } parse_args() { while [ "$#" -gt 0 ]; do case "$1" in --yes|-y) ASSUME_YES=1 ;; --dry-run|-n) DRY_RUN=1 ;; --help|-h) usage exit 0 ;; *) TARGET="$1" ;; esac shift done } confirm() { if [ "$ASSUME_YES" -eq 1 ]; then return 0 fi printf 'This will uninstall "%s" and clean common leftovers. Continue? [y/N] ' "$TARGET" read -r answer case "$answer" in y|Y|yes|YES) return 0 ;; *) return 1 ;; esac } remove_file_if_exists() { local path="$1" if [ -e "$path" ] || [ -L "$path" ]; then log "[remove] $path" run_root rm -rf "$path" && REMOVED_ANY=1 fi } uninstall_apt() { is_cmd apt-get || return 0 local pkg for pkg in "$@"; do if dpkg -s "$pkg" >/dev/null 2>&1; then log "[apt] removing $pkg" run_root apt-get remove --purge -y "$pkg" && REMOVED_ANY=1 fi done } uninstall_dnf_or_yum() { local pkg mgr if is_cmd dnf; then mgr="dnf" elif is_cmd yum; then mgr="yum" else return 0 fi for pkg in "$@"; do if is_cmd rpm && rpm -q "$pkg" >/dev/null 2>&1; then log "[$mgr] removing $pkg" run_root "$mgr" remove -y "$pkg" && REMOVED_ANY=1 fi done } uninstall_pacman() { is_cmd pacman || return 0 local pkg for pkg in "$@"; do if pacman -Q "$pkg" >/dev/null 2>&1; then log "[pacman] removing $pkg" run_root pacman -Rns --noconfirm "$pkg" && REMOVED_ANY=1 fi done } uninstall_zypper() { is_cmd zypper || return 0 local pkg for pkg in "$@"; do if is_cmd rpm && rpm -q "$pkg" >/dev/null 2>&1; then log "[zypper] removing $pkg" run_root zypper --non-interactive rm "$pkg" && REMOVED_ANY=1 fi done } uninstall_snap() { is_cmd snap || return 0 local pkg for pkg in "$@"; do if snap list 2>/dev/null | awk '{print $1}' | grep -Fxq "$pkg"; then log "[snap] removing $pkg" run_root snap remove "$pkg" && REMOVED_ANY=1 fi done } uninstall_flatpak() { is_cmd flatpak || return 0 local pkg for pkg in "$@"; do if flatpak list --app --columns=application 2>/dev/null | grep -Fxq "$pkg"; then log "[flatpak user] removing $pkg" run flatpak uninstall -y "$pkg" && REMOVED_ANY=1 fi if flatpak list --system --app --columns=application 2>/dev/null | grep -Fxq "$pkg"; then log "[flatpak system] removing $pkg" run_root flatpak uninstall --system -y "$pkg" && REMOVED_ANY=1 fi done } uninstall_pip() { local pkg if is_cmd pip3; then for pkg in "$@"; do if pip3 show "$pkg" >/dev/null 2>&1; then log "[pip3] removing $pkg" run pip3 uninstall -y "$pkg" && REMOVED_ANY=1 fi done fi if is_cmd python3; then for pkg in "$@"; do if python3 -m pip show "$pkg" >/dev/null 2>&1; then log "[python3 -m pip] removing $pkg" run python3 -m pip uninstall -y "$pkg" && REMOVED_ANY=1 fi done fi } uninstall_npm() { is_cmd npm || return 0 local pkg for pkg in "$@"; do if npm -g ls --depth=0 "$pkg" >/dev/null 2>&1; then log "[npm global] removing $pkg" run npm -g uninstall "$pkg" && REMOVED_ANY=1 fi done } remove_systemd_units() { is_cmd systemctl || return 0 local unit for unit in "$@"; do if systemctl list-unit-files 2>/dev/null | awk '{print $1}' | grep -Fxq "$unit"; then log "[systemd] disabling/stopping $unit" run_root systemctl disable --now "$unit" || true REMOVED_ANY=1 fi done } main() { parse_args "$@" local packages=( "$TARGET" "${TARGET}-cli" "${TARGET}-agent" "${TARGET}-desktop" "com.${TARGET}.app" ) local units=( "${TARGET}.service" "${TARGET}-agent.service" "${TARGET}-server.service" ) if ! confirm; then log "Cancelled." exit 1 fi uninstall_apt "${packages[@]}" uninstall_dnf_or_yum "${packages[@]}" uninstall_pacman "${packages[@]}" uninstall_zypper "${packages[@]}" uninstall_snap "${packages[@]}" uninstall_flatpak "${packages[@]}" uninstall_pip "${packages[@]}" uninstall_npm "${packages[@]}" remove_systemd_units "${units[@]}" remove_file_if_exists "/usr/local/bin/$TARGET" remove_file_if_exists "/usr/bin/$TARGET" remove_file_if_exists "$HOME/.local/bin/$TARGET" remove_file_if_exists "/etc/systemd/system/${TARGET}.service" remove_file_if_exists "/etc/systemd/system/${TARGET}-agent.service" remove_file_if_exists "/opt/$TARGET" remove_file_if_exists "/etc/$TARGET" remove_file_if_exists "/var/lib/$TARGET" remove_file_if_exists "/var/log/$TARGET" remove_file_if_exists "$HOME/.${TARGET}" remove_file_if_exists "$HOME/.config/$TARGET" remove_file_if_exists "$HOME/.cache/$TARGET" remove_file_if_exists "$HOME/.local/share/$TARGET" if is_cmd systemctl; then run_root systemctl daemon-reload || true fi if command -v "$TARGET" >/dev/null 2>&1; then log log "Uninstall attempted, but '$TARGET' is still on PATH: $(command -v "$TARGET")" exit 2 fi if [ "$REMOVED_ANY" -eq 1 ]; then log log "Uninstall completed for target '$TARGET'." else log log "Nothing found to remove for target '$TARGET'." fi } main "$@"