use crate::error::{CjvError, Result};
use std::path::{Path, PathBuf};
pub fn current_platform() -> Result<String> {
let os = std::env::consts::OS;
let arch = std::env::consts::ARCH;
let goos = match os {
"linux" => "linux",
"macos" | "darwin" => "darwin",
"windows" => "windows",
_ => return Err(CjvError::UnsupportedPlatform(os.to_string())),
};
let goarch = match arch {
"x86_64" => "amd64",
"aarch64" | "arm64" => "arm64",
_ => return Err(CjvError::UnsupportedPlatform(arch.to_string())),
};
Ok(format!("{}-{}", goos, goarch))
}
pub fn cjv_home() -> PathBuf {
if let Ok(val) = std::env::var("CJV_HOME") {
return PathBuf::from(val);
}
let settings_path = settings_file();
if settings_path.exists() {
if let Ok(content) = std::fs::read_to_string(&settings_path) {
if let Ok(settings) = content.parse::<toml::Value>() {
if let Some(home) = settings.get("home").and_then(|v| v.as_str()) {
return PathBuf::from(home);
}
}
}
}
dirs::home_dir()
.map(|h| h.join(".cjv"))
.unwrap_or_else(|| PathBuf::from(".cjv"))
}
pub fn settings_file() -> PathBuf {
if let Ok(val) = std::env::var("CJV_HOME") {
return PathBuf::from(val).join("settings.toml");
}
dirs::home_dir()
.map(|h| h.join(".cjv").join("settings.toml"))
.unwrap_or_else(|| PathBuf::from(".cjv/settings.toml"))
}
pub fn ensure_dir(path: &Path) -> Result<()> {
std::fs::create_dir_all(path).map_err(|e| {
CjvError::Other(format!(
"Failed to create directory {}: {}",
path.display(),
e
))
})
}
pub fn create_symlink(target: &Path, link: &Path) -> Result<()> {
#[cfg(unix)]
{
std::os::unix::fs::symlink(target, link)?;
}
#[cfg(windows)]
{
if target.is_dir() {
std::os::windows::fs::symlink_dir(target, link)?;
} else {
std::os::windows::fs::symlink_file(target, link)?;
}
}
Ok(())
}
pub fn is_valid_channel(name: &str) -> bool {
matches!(name, "lts" | "sts" | "nightly")
}
pub fn is_reserved_name(name: &str) -> bool {
is_valid_channel(name)
|| name.starts_with("lts-")
|| name.starts_with("sts-")
|| name.starts_with("nightly-")
}