Skip to main content

nils_common/provider_runtime/
paths.rs

1use std::env;
2use std::path::{Path, PathBuf};
3
4use super::profile::{HomePathSelection, ProviderProfile};
5
6pub fn resolve_secret_dir(profile: &ProviderProfile) -> Option<PathBuf> {
7    if let Some(dir) = resolve_secret_dir_from_env(profile) {
8        return Some(dir);
9    }
10
11    if let Some(home) = home_dir() {
12        return Some(resolve_home_path(&home, profile.paths.secret_dir_home));
13    }
14
15    let feature_dir = resolve_feature_dir(profile)?;
16    if feature_dir.join("init.zsh").is_file()
17        || feature_dir
18            .join(profile.paths.feature_tool_script)
19            .is_file()
20    {
21        return Some(feature_dir.join("secrets"));
22    }
23    Some(feature_dir)
24}
25
26pub fn resolve_secret_dir_from_env(profile: &ProviderProfile) -> Option<PathBuf> {
27    env_path(profile.env.secret_dir)
28}
29
30pub fn resolve_auth_file(profile: &ProviderProfile) -> Option<PathBuf> {
31    if let Some(path) = env_path(profile.env.auth_file) {
32        return Some(path);
33    }
34
35    let home = home_dir()?;
36    Some(resolve_home_path(&home, profile.paths.auth_file_home))
37}
38
39pub fn resolve_secret_cache_dir(profile: &ProviderProfile) -> Option<PathBuf> {
40    if let Some(path) = env_path(profile.env.secret_cache_dir) {
41        return Some(path);
42    }
43
44    if let Some(path) = env_path("ZSH_CACHE_DIR") {
45        return Some(path.join(profile.paths.feature_name).join("secrets"));
46    }
47
48    if let Some(home_segments) = profile.paths.secret_cache_home
49        && let Some(home) = home_dir()
50    {
51        return Some(join_segments(home, home_segments));
52    }
53
54    Some(
55        resolve_zdotdir()?
56            .join("cache")
57            .join(profile.paths.feature_name)
58            .join("secrets"),
59    )
60}
61
62pub fn resolve_feature_dir(profile: &ProviderProfile) -> Option<PathBuf> {
63    let script_dir = resolve_script_dir()?;
64    let feature_dir = script_dir
65        .join("_features")
66        .join(profile.paths.feature_name);
67    if feature_dir.is_dir() {
68        Some(feature_dir)
69    } else {
70        None
71    }
72}
73
74pub fn resolve_script_dir() -> Option<PathBuf> {
75    if let Some(path) = env_path("ZSH_SCRIPT_DIR") {
76        return Some(path);
77    }
78    Some(resolve_zdotdir()?.join("scripts"))
79}
80
81pub fn resolve_zdotdir() -> Option<PathBuf> {
82    if let Some(path) = env_path("ZDOTDIR") {
83        return Some(path);
84    }
85
86    if let Some(preload) = env_path("_ZSH_BOOTSTRAP_PRELOAD_PATH")
87        && let Some(parent) = parent_dir(&preload, 2)
88    {
89        return Some(parent);
90    }
91
92    let home = home_dir()?;
93    Some(home.join(".config").join("zsh"))
94}
95
96fn resolve_home_path(home: &Path, selection: HomePathSelection) -> PathBuf {
97    match selection {
98        HomePathSelection::ModernOnly(segments) => join_segments(home.to_path_buf(), segments),
99    }
100}
101
102fn join_segments(mut base: PathBuf, segments: &[&str]) -> PathBuf {
103    for segment in segments {
104        base.push(segment);
105    }
106    base
107}
108
109fn env_path(key: &str) -> Option<PathBuf> {
110    let raw = env::var_os(key)?;
111    if raw.is_empty() {
112        return None;
113    }
114    Some(PathBuf::from(raw))
115}
116
117fn home_dir() -> Option<PathBuf> {
118    env_path("HOME")
119}
120
121fn parent_dir(path: &Path, levels: usize) -> Option<PathBuf> {
122    let mut current = path;
123    for _ in 0..levels {
124        current = current.parent()?;
125    }
126    Some(current.to_path_buf())
127}