use anyhow::Result;
use crate::{
config::Config,
shell::{self, EnvContext},
toolchain,
toolchain::VersionSource,
};
pub fn run(config: &Config, shell_str: Option<&str>) -> Result<()> {
let shell = match shell_str {
Some(s) => shell::from_str(s)?,
None => shell::detect()
.ok_or_else(|| anyhow::anyhow!("Could not detect shell. Use --shell <name>."))?,
};
let (active_bin, active_root) = match toolchain::active_version(config) {
Ok((v, src)) => match toolchain::version_bin_path(config, &v) {
Ok(bin) => (Some(bin), Some(config.version_dir(&v.tag()))),
Err(_) => {
if src == VersionSource::Local {
eprintln!(
"gvsn: Go {} (from .go-version or .tool-versions) is not installed. Run: gvsn install {}",
v, v
);
}
(None, None)
}
},
Err(_) => (None, None),
};
let ctx = EnvContext {
gvsn_dir: &config.root,
active_bin: active_bin.as_deref(),
active_root: active_root.as_deref(),
};
print!("{}", shell.env_script(&ctx));
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn run_succeeds_with_explicit_shell_and_no_active_version() {
let dir = tempdir().unwrap();
let config = Config {
root: dir.path().to_path_buf(),
};
run(&config, Some("bash")).unwrap();
}
#[test]
fn run_errors_on_unknown_shell() {
let dir = tempdir().unwrap();
let config = Config {
root: dir.path().to_path_buf(),
};
assert!(run(&config, Some("not-a-real-shell")).is_err());
}
#[test]
fn run_uses_global_version_when_installed() {
let dir = tempdir().unwrap();
let config = Config {
root: dir.path().to_path_buf(),
};
let tag = "go1.22.4";
std::fs::create_dir_all(config.version_bin_dir(tag)).unwrap();
let go_name = if cfg!(windows) { "go.exe" } else { "go" };
std::fs::write(config.version_bin_dir(tag).join(go_name), b"").unwrap();
std::fs::write(config.version_file(), tag).unwrap();
run(&config, Some("bash")).unwrap();
}
}