1use std::path::PathBuf;
16
17use color_eyre::eyre::{ContextCompat, Result};
18
19pub fn appdata_dir() -> Result<PathBuf> {
20 if let Some(portable) = portable_data_dir() {
21 return Ok(portable);
22 }
23 if let Some(v) = std::env::var_os("BITWARDENCLI_APPDATA_DIR")
24 && !v.is_empty()
25 {
26 return Ok(PathBuf::from(v));
27 }
28 default_appdata_dir()
29}
30
31fn portable_data_dir() -> Option<PathBuf> {
32 let exe = std::env::current_exe().ok()?;
33 let candidate = exe.parent()?.join("bw-data");
34 candidate.is_dir().then_some(candidate)
35}
36
37fn default_appdata_dir() -> Result<PathBuf> {
38 let parent = if cfg!(target_os = "windows") {
39 let appdata =
40 std::env::var_os("APPDATA").context("APPDATA environment variable is not set")?;
41 PathBuf::from(appdata)
42 } else if cfg!(target_os = "macos") {
43 let home = std::env::var_os("HOME").context("HOME environment variable is not set")?;
44 PathBuf::from(home)
45 .join("Library")
46 .join("Application Support")
47 } else {
48 match std::env::var_os("XDG_CONFIG_HOME") {
49 Some(v) if !v.is_empty() => PathBuf::from(v),
50 _ => {
51 let home =
52 std::env::var_os("HOME").context("HOME environment variable is not set")?;
53 PathBuf::from(home).join(".config")
54 }
55 }
56 };
57 Ok(parent.join("Bitwarden CLI"))
58}