Created
February 6, 2026 10:29
-
-
Save mikestreety/07d531b346ab8ce9c62ec655dd4274a4 to your computer and use it in GitHub Desktop.
Completely remove DDEV from your system. Note: Generated with assistance from AI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| ################################################################################ | |
| # DDEV System Removal Script | |
| # | |
| # Safely removes DDEV and all associated system-level resources from macOS | |
| # while preserving project-level .ddev directories | |
| # | |
| # Version: 1.0.0 | |
| # Platform: macOS (Darwin) | |
| # Usage: ./remove-ddev.sh [OPTIONS] | |
| # | |
| # Options: | |
| # --backup Create backup of global config before deletion | |
| # --keep-docker Keep Docker images/volumes (faster reinstall) | |
| # --keep-ssl Keep mkcert SSL certificates | |
| # --yes, -y Skip confirmation prompts | |
| # --dry-run Show what would be removed without doing it | |
| # --help, -h Show help message | |
| ################################################################################ | |
| set -euo pipefail | |
| # Script metadata | |
| readonly SCRIPT_VERSION="1.0.0" | |
| readonly SCRIPT_NAME="$(basename "$0")" | |
| # Color codes for output | |
| readonly RED='\033[0;31m' | |
| readonly GREEN='\033[0;32m' | |
| readonly YELLOW='\033[1;33m' | |
| readonly BLUE='\033[0;34m' | |
| readonly BOLD='\033[1m' | |
| readonly RESET='\033[0m' | |
| # Configuration | |
| BACKUP_ENABLED=false | |
| KEEP_DOCKER=false | |
| KEEP_SSL=false | |
| SKIP_CONFIRMATIONS=false | |
| DRY_RUN=false | |
| SHOW_HELP=false | |
| # State tracking | |
| CONTAINERS_REMOVED=0 | |
| IMAGES_REMOVED=0 | |
| VOLUMES_REMOVED=0 | |
| BYTES_FREED=0 | |
| ERRORS_ENCOUNTERED=0 | |
| BACKUP_CREATED=false | |
| BACKUP_DIR="" | |
| # Paths | |
| readonly HOME_DIR="$HOME" | |
| readonly DDEV_GLOBAL_CONFIG="$HOME_DIR/.ddev" | |
| readonly MKCERT_DIR="$HOME_DIR/Library/Application Support/mkcert" | |
| readonly BREW_PREFIX="${BREW_PREFIX:-/opt/homebrew}" | |
| ################################################################################ | |
| # Utility Functions | |
| ################################################################################ | |
| print_section() { | |
| echo -e "\n${BLUE}${BOLD}▶ $1${RESET}" | |
| } | |
| print_success() { | |
| echo -e " ${GREEN}✓${RESET} $1" | |
| } | |
| print_warning() { | |
| echo -e " ${YELLOW}⚠${RESET} $1" | |
| } | |
| print_error() { | |
| echo -e " ${RED}✗${RESET} $1" >&2 | |
| } | |
| print_info() { | |
| echo -e " $1" | |
| } | |
| track_error() { | |
| print_error "$1" | |
| ((ERRORS_ENCOUNTERED++)) | |
| } | |
| confirm() { | |
| local prompt="$1" | |
| local response | |
| if [[ "$SKIP_CONFIRMATIONS" == "true" ]]; then | |
| return 0 | |
| fi | |
| while true; do | |
| read -r -p "$(echo -e ${YELLOW}$prompt${RESET}) (y/n) " response | |
| case "$response" in | |
| [yY][eE][sS]|[yY]) | |
| return 0 | |
| ;; | |
| [nN][oO]|[nN]) | |
| return 1 | |
| ;; | |
| *) | |
| echo "Please answer yes or no." | |
| ;; | |
| esac | |
| done | |
| } | |
| confirm_typed() { | |
| local prompt="$1" | |
| local required_text="$2" | |
| local response | |
| if [[ "$SKIP_CONFIRMATIONS" == "true" ]]; then | |
| return 0 | |
| fi | |
| read -r -p "$(echo -e ${YELLOW}$prompt${RESET})" response | |
| [[ "$response" == "$required_text" ]] | |
| } | |
| execute_cmd() { | |
| local cmd="$1" | |
| if [[ "$DRY_RUN" == "true" ]]; then | |
| echo "[DRY-RUN] $cmd" | |
| return 0 | |
| else | |
| eval "$cmd" | |
| fi | |
| } | |
| ################################################################################ | |
| # Pre-flight Checks | |
| ################################################################################ | |
| check_prerequisites() { | |
| print_section "Checking Prerequisites" | |
| # Check macOS | |
| if [[ "$(uname -s)" != "Darwin" ]]; then | |
| print_error "This script is designed for macOS only" | |
| return 1 | |
| fi | |
| print_success "Running on macOS" | |
| # Check Docker | |
| if ! command -v docker &>/dev/null; then | |
| print_error "Docker is not installed or not in PATH" | |
| return 1 | |
| fi | |
| print_success "Docker found: $(docker --version)" | |
| # Check if Docker is running | |
| if ! docker ps &>/dev/null 2>&1; then | |
| print_error "Docker is not running. Please start Docker Desktop" | |
| return 1 | |
| fi | |
| print_success "Docker is running" | |
| # Check Homebrew | |
| if ! command -v brew &>/dev/null; then | |
| print_error "Homebrew is not installed" | |
| return 1 | |
| fi | |
| print_success "Homebrew found: $(brew --version | head -1)" | |
| # Check if DDEV is installed | |
| if ! command -v ddev &>/dev/null; then | |
| print_warning "DDEV is not installed (nothing to remove)" | |
| return 1 | |
| fi | |
| print_success "DDEV found: $(ddev version)" | |
| return 0 | |
| } | |
| show_removal_plan() { | |
| print_section "DDEV Removal Plan" | |
| # Count existing resources | |
| local container_count | |
| local image_count | |
| local volume_count | |
| container_count=$(docker ps -a --filter "name=ddev-" --format "{{.Names}}" | wc -l 2>/dev/null || echo 0) | |
| image_count=$(docker images --filter "reference=ddev/*" --format "{{.Repository}}:{{.Tag}}" | wc -l 2>/dev/null || echo 0) | |
| volume_count=$(docker volume ls --filter "name=ddev-" --format "{{.Name}}" | wc -l 2>/dev/null || echo 0) | |
| # Calculate size | |
| local config_size=0 | |
| if [[ -d "$DDEV_GLOBAL_CONFIG" ]]; then | |
| config_size=$(du -sk "$DDEV_GLOBAL_CONFIG" 2>/dev/null | awk '{print $1 * 1024}' || echo 0) | |
| fi | |
| echo "" | |
| echo "Will remove:" | |
| echo " • DDEV binary and Homebrew formula" | |
| echo " • Global configuration directory (~/.ddev)" | |
| [[ $container_count -gt 0 ]] && echo " • $container_count Docker container(s)" | |
| [[ $image_count -gt 0 ]] && echo " • $image_count Docker image(s)" | |
| [[ $volume_count -gt 0 ]] && echo " • $volume_count Docker volume(s)" | |
| [[ $KEEP_SSL != "true" ]] && echo " • mkcert SSL certificates" | |
| echo "" | |
| echo "Will preserve:" | |
| echo " • All project-level .ddev directories in ~/Sites" | |
| [[ $KEEP_DOCKER == "true" ]] && echo " • Docker images and volumes" | |
| [[ $KEEP_SSL == "true" ]] && echo " • mkcert SSL certificates" | |
| echo "" | |
| } | |
| ################################################################################ | |
| # Removal Functions | |
| ################################################################################ | |
| stop_ddev_services() { | |
| print_section "Stopping DDEV Services" | |
| # Try graceful shutdown | |
| if ddev poweroff 2>/dev/null; then | |
| print_success "DDEV poweroff completed" | |
| else | |
| print_warning "DDEV poweroff failed or already stopped" | |
| fi | |
| # Wait a bit for graceful shutdown | |
| sleep 2 | |
| # Check for remaining containers and stop them | |
| local remaining | |
| remaining=$(docker ps --filter "name=ddev-" --format "{{.Names}}" | tr '\n' ' ') | |
| if [[ -n "$remaining" ]]; then | |
| print_info "Stopping remaining containers..." | |
| for container in $remaining; do | |
| print_info "Stopping $container..." | |
| execute_cmd "docker stop -t 10 '$container' 2>/dev/null || docker kill '$container' 2>/dev/null || true" | |
| print_success "Stopped $container" | |
| done | |
| else | |
| print_success "All DDEV services stopped" | |
| fi | |
| } | |
| remove_docker_containers() { | |
| print_section "Removing Docker Containers" | |
| local containers | |
| containers=$(docker ps -a --filter "name=ddev-" --format "{{.Names}}") | |
| if [[ -z "$containers" ]]; then | |
| print_success "No DDEV containers found" | |
| return 0 | |
| fi | |
| local container_count=0 | |
| while IFS= read -r container; do | |
| [[ -z "$container" ]] && continue | |
| print_info "Removing container: $container" | |
| execute_cmd "docker rm -f '$container' 2>/dev/null" || true | |
| print_success "Removed $container" | |
| ((container_count++)) | |
| CONTAINERS_REMOVED=$container_count | |
| done <<< "$containers" | |
| print_success "Removed $container_count container(s)" | |
| } | |
| remove_docker_images() { | |
| print_section "Removing Docker Images" | |
| if [[ "$KEEP_DOCKER" == "true" ]]; then | |
| print_warning "Skipped (--keep-docker enabled)" | |
| return 0 | |
| fi | |
| local images | |
| images=$(docker images --filter "reference=ddev/*" --format "{{.Repository}}:{{.Tag}}") | |
| if [[ -z "$images" ]]; then | |
| print_success "No DDEV images found" | |
| return 0 | |
| fi | |
| local image_count=0 | |
| while IFS= read -r image; do | |
| [[ -z "$image" ]] && continue | |
| print_info "Removing image: $image" | |
| execute_cmd "docker rmi -f '$image' 2>/dev/null" || track_error "Failed to remove $image" | |
| print_success "Removed $image" | |
| ((image_count++)) | |
| IMAGES_REMOVED=$image_count | |
| done <<< "$images" | |
| print_success "Removed $image_count image(s)" | |
| } | |
| remove_docker_volumes() { | |
| print_section "Removing Docker Volumes" | |
| if [[ "$KEEP_DOCKER" == "true" ]]; then | |
| print_warning "Skipped (--keep-docker enabled)" | |
| return 0 | |
| fi | |
| local volumes | |
| volumes=$(docker volume ls --filter "name=ddev-" --format "{{.Name}}") | |
| if [[ -z "$volumes" ]]; then | |
| print_success "No DDEV volumes found" | |
| return 0 | |
| fi | |
| print_warning "This will permanently delete database snapshots" | |
| if ! confirm "Continue removing volumes?"; then | |
| print_warning "Skipped volume removal" | |
| return 0 | |
| fi | |
| local volume_count=0 | |
| while IFS= read -r volume; do | |
| [[ -z "$volume" ]] && continue | |
| print_info "Removing volume: $volume" | |
| execute_cmd "docker volume rm '$volume' 2>/dev/null" || track_error "Failed to remove $volume" | |
| print_success "Removed $volume" | |
| ((volume_count++)) | |
| VOLUMES_REMOVED=$volume_count | |
| done <<< "$volumes" | |
| print_success "Removed $volume_count volume(s)" | |
| } | |
| remove_docker_networks() { | |
| print_section "Removing Docker Networks" | |
| local network | |
| network=$(docker network ls --filter "name=ddev_default" --format "{{.Name}}") | |
| if [[ -z "$network" ]]; then | |
| print_success "No DDEV network found" | |
| return 0 | |
| fi | |
| print_info "Removing network: ddev_default" | |
| execute_cmd "docker network rm ddev_default 2>/dev/null" || true | |
| print_success "Removed ddev_default network" | |
| } | |
| create_backup() { | |
| print_section "Creating Backup" | |
| if [[ ! -d "$DDEV_GLOBAL_CONFIG" ]]; then | |
| print_warning "Global config not found, nothing to backup" | |
| return 0 | |
| fi | |
| local timestamp | |
| timestamp=$(date +%Y%m%d-%H%M%S) | |
| BACKUP_DIR="$HOME_DIR/ddev-backup-$timestamp" | |
| print_info "Creating backup to: $BACKUP_DIR" | |
| if execute_cmd "mkdir -p '$BACKUP_DIR'"; then | |
| if execute_cmd "cp -r '$DDEV_GLOBAL_CONFIG' '$BACKUP_DIR/global'"; then | |
| # Also copy project list if exists | |
| if [[ -f "$DDEV_GLOBAL_CONFIG/project_list.yaml" ]]; then | |
| execute_cmd "cp '$DDEV_GLOBAL_CONFIG/project_list.yaml' '$BACKUP_DIR/project_list.yaml'" | |
| fi | |
| # Create tar archive | |
| print_info "Archiving backup..." | |
| execute_cmd "tar -czf '$HOME_DIR/ddev-backup-$timestamp.tar.gz' -C '$HOME_DIR' 'ddev-backup-$timestamp'" || true | |
| BACKUP_CREATED=true | |
| print_success "Backup created: $BACKUP_DIR" | |
| else | |
| track_error "Failed to copy config to backup" | |
| fi | |
| else | |
| track_error "Failed to create backup directory" | |
| fi | |
| } | |
| remove_global_config() { | |
| print_section "Removing Global Configuration" | |
| if [[ ! -d "$DDEV_GLOBAL_CONFIG" ]]; then | |
| print_success "No global config found" | |
| return 0 | |
| fi | |
| if ! confirm "Remove ~/.ddev directory?"; then | |
| print_warning "Skipped global config removal" | |
| return 0 | |
| fi | |
| print_info "Removing $DDEV_GLOBAL_CONFIG" | |
| execute_cmd "rm -rf '$DDEV_GLOBAL_CONFIG'" | |
| print_success "Removed global configuration" | |
| } | |
| remove_ssl_certificates() { | |
| print_section "Removing SSL Certificates" | |
| if [[ "$KEEP_SSL" == "true" ]]; then | |
| print_warning "Skipped (--keep-ssl enabled)" | |
| return 0 | |
| fi | |
| if [[ ! -d "$MKCERT_DIR" ]]; then | |
| print_success "No mkcert certificates found" | |
| return 0 | |
| fi | |
| print_warning "This removes mkcert SSL certificates from your system" | |
| print_warning "If other tools use mkcert, use --keep-ssl instead" | |
| if ! confirm "Continue removing SSL certificates?"; then | |
| print_warning "Skipped SSL certificate removal" | |
| return 0 | |
| fi | |
| # Uninstall from system trust store | |
| print_info "Uninstalling mkcert from system trust store..." | |
| execute_cmd "mkcert -uninstall 2>/dev/null || true" | |
| # Remove certificate directory | |
| print_info "Removing certificate directory..." | |
| execute_cmd "rm -rf '$MKCERT_DIR'" | |
| print_success "Removed SSL certificates" | |
| } | |
| remove_homebrew_formula() { | |
| print_section "Uninstalling Homebrew Formula" | |
| if ! command -v ddev &>/dev/null; then | |
| print_success "DDEV binary not found" | |
| return 0 | |
| fi | |
| # Find the actual formula name (might be 'ddev', 'ddev/ddev/ddev', or versioned) | |
| local formula_name | |
| formula_name=$(brew list --formula 2>/dev/null | grep -E '^ddev(@|$|/)' | head -1) | |
| if [[ -z "$formula_name" ]]; then | |
| # Try alternative detection | |
| formula_name=$(brew list --formula 2>/dev/null | grep ddev | head -1) | |
| fi | |
| if [[ -z "$formula_name" ]]; then | |
| print_warning "Could not determine DDEV formula name, trying 'ddev'..." | |
| formula_name="ddev" | |
| fi | |
| print_info "Uninstalling DDEV ($formula_name)..." | |
| execute_cmd "brew uninstall -f '$formula_name'" || track_error "Failed to uninstall DDEV" | |
| print_success "Uninstalled DDEV" | |
| # Fallback: directly remove binary if still present | |
| if command -v ddev &>/dev/null; then | |
| local ddev_path | |
| ddev_path=$(command -v ddev) | |
| print_warning "DDEV binary still present, removing directly: $ddev_path" | |
| # Remove both symlinks and the actual file | |
| execute_cmd "rm -f '$ddev_path'" || track_error "Failed to remove binary" | |
| # Also try removing from standard locations | |
| execute_cmd "rm -f /opt/homebrew/bin/ddev /usr/local/bin/ddev" || true | |
| print_success "Removed DDEV binary" | |
| fi | |
| # Clean Homebrew cache | |
| print_info "Cleaning Homebrew cache..." | |
| execute_cmd "brew cleanup -s 2>/dev/null || true" | |
| print_success "Homebrew cleanup completed" | |
| } | |
| ################################################################################ | |
| # Verification | |
| ################################################################################ | |
| verify_removal() { | |
| print_section "Verifying Removal" | |
| local issues=0 | |
| # Check DDEV binary | |
| # Clear shell's command cache first | |
| hash -r 2>/dev/null || true | |
| # Check if binary exists in standard locations or PATH | |
| local ddev_exists=false | |
| if [[ -f /opt/homebrew/bin/ddev ]] || [[ -f /usr/local/bin/ddev ]]; then | |
| ddev_exists=true | |
| elif command -v ddev &>/dev/null 2>&1; then | |
| # Double-check the path exists | |
| if [[ -f "$(command -v ddev)" ]]; then | |
| ddev_exists=true | |
| fi | |
| fi | |
| if [[ "$ddev_exists" == "true" ]]; then | |
| print_warning "DDEV binary still present" | |
| ((issues++)) | |
| else | |
| print_success "DDEV binary removed" | |
| fi | |
| # Check global config | |
| if [[ -d "$DDEV_GLOBAL_CONFIG" ]]; then | |
| print_warning "Global config still present: $DDEV_GLOBAL_CONFIG" | |
| ((issues++)) | |
| else | |
| print_success "Global config removed" | |
| fi | |
| # Check Docker containers | |
| local remaining_containers | |
| remaining_containers=$(docker ps -a --filter "name=ddev-" --format "{{.Names}}" | wc -l) | |
| if [[ $remaining_containers -gt 0 ]]; then | |
| print_warning "$remaining_containers DDEV container(s) still present" | |
| ((issues++)) | |
| else | |
| print_success "All DDEV containers removed" | |
| fi | |
| # Check Docker images (unless kept) | |
| if [[ "$KEEP_DOCKER" != "true" ]]; then | |
| local remaining_images | |
| remaining_images=$(docker images --filter "reference=ddev/*" --format "{{.Repository}}" | wc -l) | |
| if [[ $remaining_images -gt 0 ]]; then | |
| print_warning "$remaining_images DDEV image(s) still present" | |
| ((issues++)) | |
| else | |
| print_success "All DDEV images removed" | |
| fi | |
| fi | |
| # Check projects are intact | |
| local projects_found | |
| projects_found=$(find "$HOME_DIR/Sites" -maxdepth 2 -type d -name ".ddev" 2>/dev/null | wc -l) | |
| if [[ $projects_found -gt 0 ]]; then | |
| print_success "Project .ddev directories preserved ($projects_found found)" | |
| else | |
| print_warning "No project .ddev directories found (expected to exist)" | |
| fi | |
| echo "" | |
| if [[ $issues -eq 0 ]]; then | |
| echo -e "${GREEN}${BOLD}✓ DDEV completely removed from system${RESET}" | |
| return 0 | |
| else | |
| echo -e "${YELLOW}${BOLD}⚠ Removal verification found $issues issue(s)${RESET}" | |
| return 1 | |
| fi | |
| } | |
| print_removal_summary() { | |
| print_section "Removal Summary" | |
| echo "" | |
| echo "Resources Removed:" | |
| echo " • Docker containers: $CONTAINERS_REMOVED" | |
| echo " • Docker images: $IMAGES_REMOVED" | |
| echo " • Docker volumes: $VOLUMES_REMOVED" | |
| echo " • DDEV binary: Yes" | |
| echo " • Global configuration: Yes" | |
| echo " • SSL certificates: $([ "$KEEP_SSL" == "true" ] && echo 'No (kept)' || echo 'Yes')" | |
| echo "" | |
| if [[ "$BACKUP_CREATED" == "true" ]]; then | |
| echo -e "${GREEN}Backup created:${RESET}" | |
| echo " • Directory: $BACKUP_DIR" | |
| echo " • Archive: $HOME_DIR/ddev-backup-$(basename $BACKUP_DIR).tar.gz" | |
| fi | |
| echo "" | |
| echo "Suggested cleanup:" | |
| echo " docker system prune -a --volumes" | |
| echo " brew cleanup" | |
| if [[ $ERRORS_ENCOUNTERED -gt 0 ]]; then | |
| echo "" | |
| echo -e "${YELLOW}⚠ Encountered $ERRORS_ENCOUNTERED error(s) during removal${RESET}" | |
| fi | |
| echo "" | |
| } | |
| ################################################################################ | |
| # Help and Information | |
| ################################################################################ | |
| show_help() { | |
| echo -e "" | |
| echo -e "${BOLD}DDEV System Removal Script${RESET}" | |
| echo -e "" | |
| echo -e "${BOLD}Usage:${RESET}" | |
| echo -e " $SCRIPT_NAME [OPTIONS]" | |
| echo -e "" | |
| echo -e "${BOLD}Options:${RESET}" | |
| echo -e " --backup Create backup of global config before deletion" | |
| echo -e " --keep-docker Keep Docker images/volumes (faster reinstall)" | |
| echo -e " --keep-ssl Keep mkcert SSL certificates" | |
| echo -e " --yes, -y Skip confirmation prompts" | |
| echo -e " --dry-run Show what would be removed without doing it" | |
| echo -e " --help, -h Show this help message" | |
| echo -e "" | |
| echo -e "${BOLD}Examples:${RESET}" | |
| echo -e " # Full removal with backup (recommended)" | |
| echo -e " $SCRIPT_NAME --backup" | |
| echo -e "" | |
| echo -e " # Preview what will be removed" | |
| echo -e " $SCRIPT_NAME --dry-run" | |
| echo -e "" | |
| echo -e " # Quick removal keeping Docker resources" | |
| echo -e " $SCRIPT_NAME --keep-docker" | |
| echo -e "" | |
| echo -e " # Automated removal" | |
| echo -e " $SCRIPT_NAME --yes" | |
| echo -e "" | |
| echo -e "${BOLD}Notes:${RESET}" | |
| echo -e " • Project-level .ddev directories are always preserved" | |
| echo -e " • SSL certificates affect system-wide mkcert installation" | |
| echo -e " • Use --backup to create a backup before full removal" | |
| echo -e " • Use --dry-run to preview changes without making them" | |
| echo -e "" | |
| } | |
| ################################################################################ | |
| # Argument Parsing | |
| ################################################################################ | |
| parse_arguments() { | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --backup) | |
| BACKUP_ENABLED=true | |
| shift | |
| ;; | |
| --keep-docker) | |
| KEEP_DOCKER=true | |
| shift | |
| ;; | |
| --keep-ssl) | |
| KEEP_SSL=true | |
| shift | |
| ;; | |
| --yes|-y) | |
| SKIP_CONFIRMATIONS=true | |
| shift | |
| ;; | |
| --dry-run) | |
| DRY_RUN=true | |
| shift | |
| ;; | |
| --help|-h) | |
| SHOW_HELP=true | |
| shift | |
| ;; | |
| *) | |
| print_error "Unknown option: $1" | |
| exit 2 | |
| ;; | |
| esac | |
| done | |
| } | |
| ################################################################################ | |
| # Error Handling | |
| ################################################################################ | |
| cleanup_on_exit() { | |
| if [[ "$DRY_RUN" != "true" ]]; then | |
| # Clean up any temporary backup directory if creation failed | |
| if [[ -n "${BACKUP_DIR:-}" && ! "$BACKUP_CREATED" == "true" && -d "$BACKUP_DIR" ]]; then | |
| rm -rf "$BACKUP_DIR" 2>/dev/null || true | |
| fi | |
| fi | |
| } | |
| trap cleanup_on_exit EXIT | |
| ################################################################################ | |
| # Main Execution | |
| ################################################################################ | |
| main() { | |
| # Show help if requested | |
| if [[ "$SHOW_HELP" == "true" ]]; then | |
| show_help | |
| exit 0 | |
| fi | |
| # Print header | |
| echo "" | |
| echo -e "${BLUE}${BOLD}═══════════════════════════════════════════════════════════${RESET}" | |
| echo -e "${BLUE}${BOLD} DDEV System Removal Script v$SCRIPT_VERSION${RESET}" | |
| echo -e "${BLUE}${BOLD}═══════════════════════════════════════════════════════════${RESET}" | |
| echo "" | |
| # Show mode | |
| if [[ "$DRY_RUN" == "true" ]]; then | |
| echo -e "${YELLOW}${BOLD}⚠ DRY-RUN MODE - No changes will be made${RESET}" | |
| echo "" | |
| fi | |
| # Check prerequisites | |
| if ! check_prerequisites; then | |
| print_error "Prerequisites check failed" | |
| exit 1 | |
| fi | |
| # Show removal plan | |
| show_removal_plan | |
| # Final confirmation | |
| if ! confirm "Do you want to proceed with DDEV removal?"; then | |
| echo "" | |
| echo "Removal cancelled." | |
| exit 1 | |
| fi | |
| # Execute removal phases | |
| stop_ddev_services | |
| remove_docker_containers | |
| remove_docker_images | |
| remove_docker_volumes | |
| remove_docker_networks | |
| if [[ "$BACKUP_ENABLED" == "true" ]]; then | |
| create_backup | |
| fi | |
| remove_global_config | |
| remove_ssl_certificates | |
| remove_homebrew_formula | |
| # Verify and report | |
| verify_removal | |
| print_removal_summary | |
| echo -e "${GREEN}${BOLD}Done!${RESET}" | |
| echo "" | |
| exit 0 | |
| } | |
| # Run main function | |
| parse_arguments "$@" | |
| main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment