use anyhow::{Context, Result};
use colored::Colorize;
use crate::{config::Config, toolchain, user_version::VersionSpec};
pub fn run(config: &Config, spec_str: &str) -> Result<()> {
let spec = VersionSpec::parse(spec_str)?;
let tag = spec_to_tag(&spec);
if !matches!(spec, VersionSpec::Latest) {
if let Ok(v) = crate::version::GoVersion::parse(&tag) {
if !toolchain::is_installed(config, &v) {
println!(
"{} Go {} is not installed yet. Run {} first.",
"!".yellow(),
tag.bold(),
format!("gvsn install {tag}").cyan()
);
}
}
}
std::fs::write(".go-version", &tag).context("Failed to write .go-version")?;
println!(
"{} Local Go version set to {} (.go-version)",
"✓".green(),
tag.bold()
);
Ok(())
}
fn spec_to_tag(spec: &VersionSpec) -> String {
match spec {
VersionSpec::Latest => "latest".to_string(),
VersionSpec::Partial { major, minor } => format!("go{major}.{minor}"),
VersionSpec::Exact {
major,
minor,
patch,
} => format!("go{major}.{minor}.{patch}"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn spec_to_tag_latest_is_literal() {
assert_eq!(spec_to_tag(&VersionSpec::Latest), "latest");
}
#[test]
fn spec_to_tag_partial_omits_patch() {
let spec = VersionSpec::Partial {
major: 1,
minor: 22,
};
assert_eq!(spec_to_tag(&spec), "go1.22");
}
#[test]
fn spec_to_tag_exact_includes_patch() {
let spec = VersionSpec::Exact {
major: 1,
minor: 22,
patch: 4,
};
assert_eq!(spec_to_tag(&spec), "go1.22.4");
}
}