use anyhow::{Context, bail};
use crate::{
channel::UserChannel,
commands,
config::Config,
state::LocalState,
toolchain::{Toolchain, ToolchainJustification},
utils,
};
pub fn r#override(
config: &Config,
_state: &LocalState,
channel: &UserChannel,
) -> anyhow::Result<()> {
commands::setup_midenup(config)?;
let (active, justification) = Toolchain::current(config, None)?;
let toolchains_dir = config.midenup_home.join("toolchains");
let channel_dir = match channel {
UserChannel::Named(name) => {
let link = crate::paths::network_link(&config.midenup_home, name.as_ref());
match config.upstream_manifest() {
Ok(manifest) => {
if !manifest.network_names().any(|network| network == name.as_ref()) {
bail!(
"unknown channel '{name}'; known networks are {}",
manifest.network_names().collect::<Vec<_>>().join(", ")
);
}
},
Err(err) if link.symlink_metadata().is_err() => {
return Err(err.context(format!(
"cannot check whether '{name}' is a known network, and no \
toolchains/{name} link exists locally"
)));
},
Err(_) => {},
}
link
},
UserChannel::Version(_) => {
let inner_channel = config.upstream_manifest()?.get_channel(channel).context(
"failed to set {channel} as the system default. Try installing it:
midenup install {channel}",
)?;
inner_channel.get_channel_dir(config)
},
};
let default_path = toolchains_dir.join("default");
if std::fs::symlink_metadata(&default_path).is_ok() {
std::fs::remove_file(&default_path)
.context("failed to remove 'default' toolchain symlink")?;
}
crate::info!("setting {channel} as the new default toolchain");
if let ToolchainJustification::MidenToolchainFile { path } = justification {
crate::warn!(
"there is a toolchain file present in {}, which sets the current active toolchain to \
be {}.
This will take prescedence over the configuration done by `midenup override`.",
path.display(),
active.channel
);
};
utils::fs::symlink(&default_path, &channel_dir)?;
Ok(())
}