use anyhow::{Context, bail};
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 home = &config.midenup_home;
let shared_network = match requested {
UserChannel::Named(network)
if crate::networks::links(home)
.into_iter()
.any(|(other, linked)| other != network.as_ref() && linked == channel) =>
{
Some(network.as_ref())
},
_ => None,
};
if let Some(network) = shared_network {
let link = paths::network_link(home, network);
crate::trace!("removing {}", link.display());
std::fs::remove_file(link)?;
} else {
let publication = match &installation.publication {
PublicationRef::Managed { id, .. } => Some(id.clone()),
PublicationRef::NeedsReinstall => None,
};
let entry = JournalEntry::uninstall(channel.clone(), publication);
crate::publish::journal::prepare(home, &entry)?;
crate::publish::journal::commit_symlink(home, &entry)?;
crate::publish::journal::finish(home, &entry, state)?;
}
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)?;
crate::info!(
"removed the 'default' override, which named {requested}. Set a new one with:\n \
midenup override <channel>"
);
}
let var = paths::var_dir(home, requested);
if var.is_dir() {
if purge {
crate::trace!("removing {}", var.display());
std::fs::remove_dir_all(&var)
.with_context(|| format!("failed to remove '{}'", var.display()))?;
} else {
crate::info!(
"kept your data for {requested} at {}; remove it with `midenup uninstall \
{requested} --purge`",
var.display()
);
}
}
if shared_network.is_some() {
crate::info!(
"removed network '{requested}'; channel '{channel}' stays installed for the other \
networks that name it"
);
} else {
crate::info!("uninstalled channel '{channel}'");
}
Ok(())
}