use anyhow::{Context, bail};
use colored::Colorize;
use crate::{
channel::UserChannel,
config::Config,
paths,
publish::JournalEntry,
state::{LocalState, PublicationRef},
};
pub fn uninstall(
config: &Config,
requested: &UserChannel,
state: &mut LocalState,
purge: bool,
) -> anyhow::Result<()> {
let installed = config.local_channel(requested).and_then(|version| state.get(&version));
let Some(installation) = installed else {
bail!("channel {requested} is not installed, nothing to uninstall");
};
let channel = installation.channel.clone();
let publication = match &installation.publication {
PublicationRef::Managed { id, .. } => Some(id.clone()),
PublicationRef::NeedsReinstall => None,
};
let home = &config.midenup_home;
let entry = JournalEntry::uninstall(channel.clone(), publication);
crate::publish::journal::prepare(home, &entry)?;
{
let channel_name = channel.to_string();
if let Ok(entries) = std::fs::read_dir(paths::toolchains_dir(home)) {
for dir_entry in entries.flatten() {
let Ok(target) = std::fs::read_link(dir_entry.path()) else {
continue;
};
if target == std::path::Path::new(&channel_name) {
std::fs::remove_file(dir_entry.path())?;
}
}
}
}
crate::publish::journal::commit_symlink(home, &entry)?;
let default = paths::toolchains_dir(home).join("default");
if std::fs::symlink_metadata(&default).is_ok() && default.canonicalize().is_err() {
std::fs::remove_file(&default)?;
println!(
"{}: removed the 'default' override, which named {channel}. Set a new one with:\n \
midenup override <channel>",
"info".white().bold()
);
}
crate::publish::journal::finish(home, &entry, state)?;
let var = paths::var_dir(home, requested);
if var.is_dir() {
if purge {
std::fs::remove_dir_all(&var)
.with_context(|| format!("failed to remove '{}'", var.display()))?;
} else {
println!(
"kept your data for {requested} at {}; remove it with `midenup uninstall \
{requested} --purge`",
var.display()
);
}
}
Ok(())
}