use crate::{versions::Version, warning};
use anyhow::Result;
use directories::UserDirs;
use std::{
env,
fs::{self, File},
io::{self, Read, Write},
path::{Path, PathBuf},
};
const CURRENT_VERSION_FILE: &str = ".current_version";
pub fn get_home_dir() -> Result<PathBuf> {
UserDirs::new()
.ok_or_else(|| anyhow::anyhow!("could not find user directories"))
.map(|dirs| dirs.home_dir().to_path_buf())
}
pub fn get_work_dir() -> Result<PathBuf> {
get_home_dir().map(|dir| dir.join(".local").join("goup"))
}
pub fn get_installations_dir() -> Result<PathBuf> {
get_work_dir().map(|dir| dir.join("installations"))
}
pub fn get_current_link_dir() -> Result<PathBuf> {
get_work_dir().map(|dir| dir.join("current"))
}
pub fn get_current_install_dir() -> Result<PathBuf> {
get_current_link_dir().map(|dir| dir.join("go"))
}
pub fn get_current_bin_dir() -> Result<PathBuf> {
get_current_install_dir().map(|dir| dir.join("bin"))
}
pub fn get_version_installation_dir(version: &Version) -> Result<PathBuf> {
get_installations_dir().map(|v| v.join(version.to_string()))
}
pub fn ensure_dir<P: AsRef<Path>>(path: P) -> Result<()> {
if !path.as_ref().exists() {
fs::create_dir_all(path)?;
}
Ok(())
}
pub fn get_current_version() -> Result<Option<Version>> {
let vfile_path = get_work_dir()?.join(CURRENT_VERSION_FILE);
let mut vfile = match File::open(vfile_path) {
Ok(f) => f,
Err(err) => {
if matches!(err.kind(), std::io::ErrorKind::NotFound) {
return Ok(None);
} else {
return Err(err.into());
}
}
};
let mut ver = String::new();
vfile.read_to_string(&mut ver)?;
let v = ver.parse()?;
Ok(Some(v))
}
pub fn get_installed_versions() -> Result<Vec<Version>> {
let dir = match get_installations_dir()?.read_dir() {
Ok(v) => v,
Err(err) if matches!(err.kind(), io::ErrorKind::NotFound) => return Ok(vec![]),
Err(err) => return Err(err.into()),
};
let dir: Result<Vec<_>, _> = dir.collect();
let versions: Result<Vec<Version>, _> = dir?
.iter()
.map(|v| v.file_name().to_string_lossy().parse())
.collect();
versions
}
pub fn write_current_version(version: Option<&Version>) -> Result<()> {
let vfile_path = get_work_dir()?.join(CURRENT_VERSION_FILE);
match version {
Some(v) => File::create(vfile_path)?.write_all(v.to_string().as_bytes())?,
None => fs::remove_file(vfile_path)?,
}
Ok(())
}
pub fn drop_version(version: &Version) -> Result<()> {
let dir = get_version_installation_dir(version)?;
fs::remove_dir_all(dir)?;
Ok(())
}
pub fn drop_install_dir() -> Result<()> {
let dir = get_installations_dir()?;
fs::remove_dir_all(dir)?;
Ok(())
}
pub fn is_env_applied() -> Result<bool> {
let current_install_dir = get_current_install_dir()?;
let current_install_dir = current_install_dir.to_string_lossy();
let set_install_dir = env::var("GOROOT").unwrap_or_default();
Ok(set_install_dir == current_install_dir)
}
pub fn check_env_applied() -> Result<()> {
if !is_env_applied()? {
warning!(
"Seems like necessary environment variables have not been applied. \
This results in the selected SDK version not being available in the terminal.\n\
Please see `goup help env` to setup required environment variables.\n"
);
}
Ok(())
}