commit_wizard/engine/constants/
paths.rs1use crate::engine::{
2 constants::{
3 CACHE_DIR_NAME, CONFIG_DIR_NAME, CONFIG_FILE_NAME, PROJECT_CONFIG_FILE_NAME,
4 PROJECT_CONFIG_FILE_NAME_HIDDEN, RULES_FILE_NAME, STATE_DIR_NAME,
5 },
6 error::{ErrorCode, Result},
7};
8use std::{
9 env,
10 path::{Path, PathBuf},
11};
12
13pub fn resolve_repo_config_path(cwd: &Path) -> PathBuf {
14 let hidden = cwd.join(PROJECT_CONFIG_FILE_NAME_HIDDEN);
15 let visible = cwd.join(PROJECT_CONFIG_FILE_NAME);
16
17 if hidden.exists() {
18 hidden
19 } else if visible.exists() {
20 visible
21 } else {
22 hidden
23 }
24}
25
26pub fn resolve_new_repo_config_path(cwd: &Path, hidden: bool) -> PathBuf {
27 if hidden {
28 cwd.join(PROJECT_CONFIG_FILE_NAME_HIDDEN) } else {
30 cwd.join(PROJECT_CONFIG_FILE_NAME) }
32}
33
34pub fn resolve_global_config_path() -> Result<PathBuf> {
35 Ok(app_config_dir()?.join(CONFIG_FILE_NAME))
36}
37
38pub fn resolve_global_rules_path() -> Result<PathBuf> {
39 Ok(app_config_dir()?.join(RULES_FILE_NAME))
40}
41
42pub fn app_config_dir() -> Result<PathBuf> {
43 #[cfg(target_os = "windows")]
44 {
45 env::var_os("APPDATA")
46 .map(PathBuf::from)
47 .map(|p| p.join(CONFIG_DIR_NAME))
48 .ok_or_else(|| {
49 ErrorCode::ConfigInvalid
50 .error()
51 .with_context("reason", "APPDATA is not set")
52 })
53 }
54
55 #[cfg(not(target_os = "windows"))]
56 {
57 if let Some(xdg_config_home) = env::var_os("XDG_CONFIG_HOME") {
58 return Ok(PathBuf::from(xdg_config_home).join(CONFIG_DIR_NAME));
59 }
60
61 env::var_os("HOME")
62 .map(PathBuf::from)
63 .map(|p| p.join(".config").join(CONFIG_DIR_NAME))
64 .ok_or_else(|| {
65 ErrorCode::ConfigInvalid
66 .error()
67 .with_context("reason", "neither XDG_CONFIG_HOME nor HOME is set")
68 })
69 }
70}
71
72pub fn app_state_dir() -> Result<PathBuf> {
73 #[cfg(target_os = "windows")]
74 {
75 env::var_os("LOCALAPPDATA")
76 .map(PathBuf::from)
77 .map(|p| p.join(STATE_DIR_NAME))
78 .ok_or_else(|| {
79 ErrorCode::ConfigInvalid
80 .error()
81 .with_context("reason", "LOCALAPPDATA is not set")
82 })
83 }
84
85 #[cfg(not(target_os = "windows"))]
86 {
87 if let Some(xdg_state_home) = env::var_os("XDG_STATE_HOME") {
88 return Ok(PathBuf::from(xdg_state_home).join(STATE_DIR_NAME));
89 }
90
91 env::var_os("HOME")
92 .map(PathBuf::from)
93 .map(|p| p.join(".local").join("state").join(STATE_DIR_NAME))
94 .ok_or_else(|| {
95 ErrorCode::ConfigInvalid
96 .error()
97 .with_context("reason", "neither XDG_STATE_HOME nor HOME is set")
98 })
99 }
100}
101
102pub fn app_cache_dir() -> Result<PathBuf> {
103 #[cfg(target_os = "windows")]
104 {
105 env::var_os("LOCALAPPDATA")
106 .map(PathBuf::from)
107 .map(|p| p.join(CACHE_DIR_NAME))
108 .ok_or_else(|| {
109 ErrorCode::ConfigInvalid
110 .error()
111 .with_context("reason", "LOCALAPPDATA is not set")
112 })
113 }
114
115 #[cfg(not(target_os = "windows"))]
116 {
117 if let Some(xdg_cache_home) = env::var_os("XDG_CACHE_HOME") {
118 return Ok(PathBuf::from(xdg_cache_home).join(CACHE_DIR_NAME));
119 }
120
121 env::var_os("HOME")
122 .map(PathBuf::from)
123 .map(|p| p.join(".cache").join(CACHE_DIR_NAME))
124 .ok_or_else(|| {
125 ErrorCode::ConfigInvalid
126 .error()
127 .with_context("reason", "neither XDG_CACHE_HOME nor HOME is set")
128 })
129 }
130}
131
132pub fn resolve_project_config_path(
133 cwd: &Path,
134 repo_root: Option<&Path>,
135 in_git_repo: bool,
136 explicit_config_path: Option<&Path>,
137) -> Option<PathBuf> {
138 if let Some(path) = explicit_config_path {
139 return Some(path.to_path_buf());
140 }
141
142 if let Some(path) = find_project_config_in_dir(cwd) {
144 return Some(path);
145 }
146
147 if in_git_repo
149 && let Some(root) = repo_root
150 && root != cwd
151 && let Some(path) = find_project_config_in_dir(root)
152 {
153 return Some(path);
154 }
155
156 None
157}
158
159pub fn resolve_new_project_config_path(
160 cwd: &Path,
161 repo_root: Option<&Path>,
162 in_git_repo: bool,
163 explicit_config_path: Option<&Path>,
164 hidden: bool,
165) -> PathBuf {
166 if let Some(path) = explicit_config_path {
167 return path.to_path_buf();
168 }
169
170 let base_dir = if in_git_repo {
171 repo_root.unwrap_or(cwd)
172 } else {
173 cwd
174 };
175
176 base_dir.join(if hidden {
177 PROJECT_CONFIG_FILE_NAME_HIDDEN
178 } else {
179 PROJECT_CONFIG_FILE_NAME
180 })
181}
182
183fn find_project_config_in_dir(dir: &Path) -> Option<PathBuf> {
184 let hidden = dir.join(PROJECT_CONFIG_FILE_NAME_HIDDEN);
185 if hidden.exists() {
186 return Some(hidden);
187 }
188
189 let visible = dir.join(PROJECT_CONFIG_FILE_NAME);
190 if visible.exists() {
191 return Some(visible);
192 }
193
194 None
195}