1use crate::SvmError;
2use std::{
3 ffi::OsString,
4 fs, io,
5 path::{Path, PathBuf},
6 sync::OnceLock,
7};
8
9pub fn setup_data_dir() -> Result<(), SvmError> {
11 let data_dir = data_dir();
13
14 fs::create_dir_all(data_dir).or_else(|err| match err.kind() {
17 io::ErrorKind::AlreadyExists => Ok(()),
18 _ => Err(err),
19 })?;
20
21 if !data_dir.is_dir() {
23 return Err(SvmError::IoError(io::Error::new(
24 io::ErrorKind::AlreadyExists,
25 format!("svm data dir '{}' is not a directory", data_dir.display()),
26 )));
27 }
28
29 let global_version = global_version_path();
31 if !global_version.exists() {
32 fs::File::create(global_version)?;
33 }
34
35 Ok(())
36}
37
38pub fn data_dir() -> &'static Path {
42 static ONCE: OnceLock<PathBuf> = OnceLock::new();
43 ONCE.get_or_init(|| {
44 #[cfg(test)]
45 {
46 let dir = tempfile::tempdir().expect("could not create temp directory");
47 dir.path().join(".svm")
48 }
49 #[cfg(not(test))]
50 {
51 resolve_data_dir()
52 }
53 })
54}
55
56#[allow(dead_code)]
57fn resolve_data_dir() -> PathBuf {
58 let home_dir = dirs::home_dir()
59 .expect("could not detect user home directory")
60 .join(".svm");
61
62 let data_dir = dirs::data_dir().expect("could not detect user data directory");
63 if !home_dir.exists() && data_dir.exists() {
64 data_dir.join("svm")
65 } else {
66 home_dir
67 }
68}
69
70pub fn global_version_path() -> &'static Path {
72 static ONCE: OnceLock<PathBuf> = OnceLock::new();
73 ONCE.get_or_init(|| data_dir().join(".global-version"))
74}
75
76pub fn version_path(version: &str) -> PathBuf {
83 data_dir().join(version)
84}
85
86pub fn version_binary(version: &str) -> PathBuf {
90 let data_dir = data_dir();
91 let sep = std::path::MAIN_SEPARATOR_STR;
92 let cap =
93 data_dir.as_os_str().len() + sep.len() + version.len() + sep.len() + 5 + version.len();
94 let mut binary = OsString::with_capacity(cap);
95 binary.push(data_dir);
96 debug_assert!(!data_dir.ends_with(sep));
97 binary.push(sep);
98
99 binary.push(version);
100 binary.push(sep);
101
102 binary.push("solc-");
103 binary.push(version);
104 PathBuf::from(binary)
105}