Skip to main content

sql_cli/utils/
app_paths.rs

1use std::error::Error;
2use std::fs;
3use std::path::PathBuf;
4
5pub struct AppPaths;
6
7impl AppPaths {
8    /// Env var that overrides the base directory for all app paths. When set,
9    /// both data and cache resolve under it instead of the OS default. This is
10    /// the only reliable way to relocate the paths on Windows: `dirs::data_dir`
11    /// there resolves via the Win32 known-folder API and ignores `APPDATA` /
12    /// `LOCALAPPDATA` env vars, so tests can't sandbox it by setting those.
13    const BASE_DIR_ENV: &'static str = "SQL_CLI_DATA_DIR";
14
15    fn base_override() -> Option<PathBuf> {
16        std::env::var_os(Self::BASE_DIR_ENV)
17            .filter(|v| !v.is_empty())
18            .map(PathBuf::from)
19    }
20
21    pub fn data_dir() -> Result<PathBuf, Box<dyn Error>> {
22        let base = match Self::base_override() {
23            Some(base) => base,
24            None => dirs::data_dir().ok_or("Cannot determine data directory")?,
25        };
26        let data_dir = base.join("sql-cli");
27
28        fs::create_dir_all(&data_dir)?;
29        Ok(data_dir)
30    }
31
32    pub fn cache_dir() -> Result<PathBuf, Box<dyn Error>> {
33        let base = match Self::base_override() {
34            Some(base) => base,
35            None => dirs::cache_dir().ok_or("Cannot determine cache directory")?,
36        };
37        let cache_dir = base.join("sql-cli");
38
39        fs::create_dir_all(&cache_dir)?;
40        Ok(cache_dir)
41    }
42
43    pub fn history_file() -> Result<PathBuf, Box<dyn Error>> {
44        Ok(Self::data_dir()?.join("history.json"))
45    }
46
47    pub fn schemas_file() -> Result<PathBuf, Box<dyn Error>> {
48        Ok(Self::data_dir()?.join("schemas.json"))
49    }
50
51    pub fn cache_metadata_file() -> Result<PathBuf, Box<dyn Error>> {
52        Ok(Self::cache_dir()?.join("metadata.json"))
53    }
54
55    pub fn cache_data_dir() -> Result<PathBuf, Box<dyn Error>> {
56        let data_dir = Self::cache_dir()?.join("data");
57        fs::create_dir_all(&data_dir)?;
58        Ok(data_dir)
59    }
60}