valor_config/config/
der.rs

1use valkyrie_errors::ValkyrieError;
2
3use super::*;
4
5impl ValorConfig {
6    pub fn load<P: AsRef<Path>>(dir: P) -> ValkyrieResult<ValorConfig> {
7        let dir = match dir.as_ref().canonicalize() {
8            Ok(o) => o,
9            Err(_) => Err(ValkyrieError::runtime_error(format!("Directory `{}` does not exist.", dir.as_ref().display())))?,
10        };
11        let mut config = match try_load_from(&dir)? {
12            (SupportFormat::Toml, s) => toml::from_str::<Self>(&s)?,
13            (SupportFormat::Json, s) => json5::from_str(&s)?,
14            (SupportFormat::Nothing, _) => match try_load_from(&dir.join(".config"))? {
15                (SupportFormat::Toml, s) => toml::from_str(&s)?,
16                (SupportFormat::Json, s) => json5::from_str(&s)?,
17                (SupportFormat::Nothing, _) => {
18                    Err(ValkyrieError::runtime_error(format!("No config file found in {}", dir.display())))?
19                }
20            },
21        };
22        if config.is_workspace() {
23            config.workspace.root = dir;
24        }
25        Ok(config)
26    }
27}
28
29fn try_load_from(dir: &Path) -> ValkyrieResult<(SupportFormat, String)> {
30    for entry in dir.read_dir()? {
31        let file = entry?.path();
32        if !file.is_file() {
33            continue;
34        }
35        match file.file_name().and_then(OsStr::to_str) {
36            Some(s) if s.eq_ignore_ascii_case("valor.toml") => {
37                return Ok((SupportFormat::Toml, read_to_string(&file)?));
38            }
39            Some(s) if s.eq_ignore_ascii_case("valor.json5") => {
40                return Ok((SupportFormat::Json, read_to_string(&file)?));
41            }
42            Some(s) if s.eq_ignore_ascii_case("valor.json") => {
43                return Ok((SupportFormat::Json, read_to_string(&file)?));
44            }
45            _ => continue,
46        }
47    }
48    Ok((SupportFormat::Nothing, String::new()))
49}
50
51bind_writer!(ConfigWriter, ValorConfig);
52
53impl<'i, 'de> Visitor<'de> for ConfigWriter<'i> {
54    type Value = ();
55
56    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
57        formatter.write_str("expecting a dependency object")
58    }
59
60    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
61    where
62        A: MapAccess<'de>,
63    {
64        while let Some(key) = map.next_key::<String>()? {
65            match key.as_str() {
66                "dependencies" => self.ptr.dependencies.visit_map(&mut map, DependencyKind::Normal)?,
67                "dev-dependencies" => self.ptr.dependencies.visit_map(&mut map, DependencyKind::Development)?,
68                "peerDependencies" => self.ptr.dependencies.visit_map(&mut map, DependencyKind::Normal)?,
69                "build-dependencies" => self.ptr.dependencies.visit_map(&mut map, DependencyKind::Build)?,
70                "scripts" => self.ptr.scripts = map.next_value()?,
71                "workspace" => {
72                    self.ptr.workspace = map.next_value()?;
73                    self.ptr.workspace.root = PathBuf::new();
74                }
75                _ => {}
76            }
77        }
78        Ok(())
79    }
80}