use crate::SvmError;
use std::{
ffi::OsString,
fs, io,
path::{Path, PathBuf},
sync::OnceLock,
};
pub fn setup_data_dir() -> Result<(), SvmError> {
let data_dir = data_dir();
fs::create_dir_all(data_dir).or_else(|err| match err.kind() {
io::ErrorKind::AlreadyExists => Ok(()),
_ => Err(err),
})?;
if !data_dir.is_dir() {
return Err(SvmError::IoError(io::Error::new(
io::ErrorKind::AlreadyExists,
format!("svm data dir '{}' is not a directory", data_dir.display()),
)));
}
let global_version = global_version_path();
if !global_version.exists() {
fs::File::create(global_version)?;
}
Ok(())
}
pub fn data_dir() -> &'static Path {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(|| {
#[cfg(test)]
{
let dir = tempfile::tempdir().expect("could not create temp directory");
dir.path().join(".svm")
}
#[cfg(not(test))]
{
resolve_data_dir()
}
})
}
fn resolve_data_dir() -> PathBuf {
let home_dir = dirs::home_dir()
.expect("could not detect user home directory")
.join(".svm");
let data_dir = dirs::data_dir().expect("could not detect user data directory");
if !home_dir.exists() && data_dir.exists() {
data_dir.join("svm")
} else {
home_dir
}
}
pub fn global_version_path() -> &'static Path {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(|| data_dir().join(".global-version"))
}
pub fn version_path(version: &str) -> PathBuf {
data_dir().join(version)
}
pub fn version_binary(version: &str) -> PathBuf {
let data_dir = data_dir();
let sep = std::path::MAIN_SEPARATOR_STR;
let cap =
data_dir.as_os_str().len() + sep.len() + version.len() + sep.len() + 5 + version.len();
let mut binary = OsString::with_capacity(cap);
binary.push(data_dir);
debug_assert!(!data_dir.ends_with(sep));
binary.push(sep);
binary.push(version);
binary.push(sep);
binary.push("solc-");
binary.push(version);
PathBuf::from(binary)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_data_dir_resolution() {
let home_dir = dirs::home_dir().unwrap().join(".svm");
let data_dir = dirs::data_dir();
let resolved_dir = resolve_data_dir();
if home_dir.exists() || data_dir.is_none() {
assert_eq!(resolved_dir, home_dir);
} else {
assert_eq!(resolved_dir, data_dir.unwrap().join("svm"));
}
}
}