rippy_cli/config/
sources.rs1use std::path::{Path, PathBuf};
2
3use super::loader::home_dir;
4
5pub fn find_project_config(start: &Path) -> Option<PathBuf> {
7 let mut dir = start;
8 loop {
9 let toml = dir.join(".rippy.toml");
10 if toml.is_file() {
11 return Some(toml);
12 }
13 let rippy = dir.join(".rippy");
14 if rippy.is_file() {
15 return Some(rippy);
16 }
17 let dippy = dir.join(".dippy");
18 if dippy.is_file() {
19 return Some(dippy);
20 }
21 dir = dir.parent()?;
22 }
23}
24
25#[derive(Debug, Clone, serde::Serialize)]
27pub struct ConfigSourceInfo {
28 pub tier: &'static str,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub path: Option<PathBuf>,
31}
32
33pub fn enumerate_config_sources(
37 cwd: &Path,
38 config_override: Option<&Path>,
39) -> Vec<ConfigSourceInfo> {
40 let mut sources = vec![ConfigSourceInfo {
41 tier: "stdlib",
42 path: None,
43 }];
44
45 if let Some(home) = home_dir() {
46 for candidate in [
47 home.join(".rippy/config.toml"),
48 home.join(".rippy/config"),
49 home.join(".dippy/config"),
50 ] {
51 if candidate.is_file() {
52 sources.push(ConfigSourceInfo {
53 tier: "global",
54 path: Some(candidate),
55 });
56 break;
57 }
58 }
59 }
60
61 if let Some(override_path) = config_override {
62 sources.push(ConfigSourceInfo {
63 tier: "override",
64 path: Some(override_path.to_owned()),
65 });
66 } else if let Some(project) = find_project_config(cwd) {
67 sources.push(ConfigSourceInfo {
68 tier: "project",
69 path: Some(project),
70 });
71 }
72
73 sources
74}