/ crates / acdc / src / commands / uninstall.rs
uninstall.rs
  1  //! Uninstall command.
  2  
  3  use acdc_core::{Config, Paths};
  4  use acdc_service::control;
  5  use acdc_tui::{output, prompt};
  6  use anyhow::Result;
  7  use std::fs;
  8  use std::path::PathBuf;
  9  
 10  /// Uninstall AC/DC components.
 11  pub async fn run(purge: bool, yes: bool) -> Result<()> {
 12      output::section("Uninstall AC/DC");
 13  
 14      if !yes {
 15          println!();
 16          output::warning("This will:");
 17          println!("  - Stop all running node services");
 18          println!("  - Remove installed binaries (adnet, alphaos, deltaos)");
 19          if purge {
 20              println!("  - Delete all configuration files");
 21              println!("  - Delete all data (blockchain data, logs)");
 22              output::warning("PURGE MODE: All data will be permanently deleted!");
 23          }
 24          println!();
 25  
 26          if !prompt::confirm("Proceed with uninstall?") {
 27              output::info("Cancelled", "No changes made");
 28              return Ok(());
 29          }
 30      }
 31  
 32      // Stop all services first
 33      output::status("Stopping services...");
 34      let config = Config::load_default().ok();
 35      if let Some(cfg) = &config {
 36          for node in &cfg.nodes.instances {
 37              let _ = control::stop(&node.id).await;
 38          }
 39      }
 40      output::success("Services stopped");
 41  
 42      // Remove installed binaries
 43      output::status("Removing binaries...");
 44      let binaries = ["adnet", "alphaos", "deltaos"];
 45      let bin_paths = ["/usr/local/bin", "/opt/ac-dc/bin"];
 46  
 47      for bin in &binaries {
 48          for dir in &bin_paths {
 49              let path = PathBuf::from(dir).join(bin);
 50              if path.exists() {
 51                  if let Err(e) = fs::remove_file(&path) {
 52                      output::warning(&format!("Could not remove {}: {}", path.display(), e));
 53                  } else {
 54                      output::success(&format!("Removed {}", path.display()));
 55                  }
 56              }
 57          }
 58      }
 59  
 60      // Remove systemd services
 61      output::status("Removing systemd services...");
 62      let systemd_dir = PathBuf::from("/etc/systemd/system");
 63      if let Ok(entries) = fs::read_dir(&systemd_dir) {
 64          for entry in entries.flatten() {
 65              let name = entry.file_name().to_string_lossy().to_string();
 66              if name.starts_with("ac-dc-") && name.ends_with(".service") {
 67                  let path = entry.path();
 68                  if let Err(e) = fs::remove_file(&path) {
 69                      output::warning(&format!("Could not remove {}: {}", path.display(), e));
 70                  }
 71              }
 72          }
 73      }
 74  
 75      if purge {
 76          output::status("Purging data and configuration...");
 77          let paths = Paths::default();
 78  
 79          // Remove config directory
 80          if paths.config_dir.exists() {
 81              if let Err(e) = fs::remove_dir_all(&paths.config_dir) {
 82                  output::warning(&format!(
 83                      "Could not remove config dir {}: {}",
 84                      paths.config_dir.display(),
 85                      e
 86                  ));
 87              } else {
 88                  output::success(&format!("Removed {}", paths.config_dir.display()));
 89              }
 90          }
 91  
 92          // Remove data directory
 93          if paths.data_dir.exists() {
 94              if let Err(e) = fs::remove_dir_all(&paths.data_dir) {
 95                  output::warning(&format!(
 96                      "Could not remove data dir {}: {}",
 97                      paths.data_dir.display(),
 98                      e
 99                  ));
100              } else {
101                  output::success(&format!("Removed {}", paths.data_dir.display()));
102              }
103          }
104      }
105  
106      println!();
107      output::success("Uninstall complete");
108  
109      if !purge {
110          println!();
111          output::info(
112              "Note",
113              "Configuration and data were preserved. Use --purge to remove everything.",
114          );
115      }
116  
117      println!();
118      output::info(
119          "ac-dc binary",
120          "The ac-dc binary itself was not removed. To remove it:",
121      );
122      println!("  sudo rm /usr/local/bin/ac-dc");
123  
124      Ok(())
125  }