cargo_x/
config.rs

1use failure::Error;
2use std::collections::HashMap;
3use std::fs::File;
4use std::io::prelude::*;
5use std::path::{Path, PathBuf};
6
7#[derive(Deserialize)]
8struct Cargo {
9    package: Package,
10}
11
12#[derive(Deserialize)]
13struct Package {
14    metadata: Option<Metadata>,
15}
16
17#[derive(Deserialize)]
18struct Metadata {
19    x: Option<Xconf>,
20}
21
22pub type Xconf = HashMap<String, String>;
23
24fn dotx() -> Result<Xconf, Error> {
25    let mut path = match dirs::home_dir() {
26        Some(p) => p,
27        _ => return Err(format_err!("cannot get home dir")),
28    };
29    path.push(".x.toml");
30
31    if !Path::new(&path).exists() {
32        return Ok(HashMap::new());
33    }
34
35    let mut conf_string = String::new();
36    File::open(&path).and_then(|mut f| f.read_to_string(&mut conf_string))?;
37
38    let xconf: Xconf = toml::from_str(&conf_string)?;
39
40    Ok(xconf)
41}
42
43fn x() -> Result<Xconf, Error> {
44    let mut path = PathBuf::new();
45    path.push(super::meta::root()?);
46    path.push("x.toml");
47
48    if !Path::new(&path).exists() {
49        return Ok(HashMap::new());
50    }
51
52    let mut conf_string = String::new();
53    File::open(&path).and_then(|mut f| f.read_to_string(&mut conf_string))?;
54
55    let xconf: Xconf = toml::from_str(&conf_string)?;
56
57    Ok(xconf)
58}
59
60fn cargo() -> Result<Xconf, Error> {
61    let mut path = PathBuf::new();
62    path.push(super::meta::root()?);
63    path.push("Cargo.toml");
64
65    if !Path::new(&path).exists() {
66        return Ok(HashMap::new());
67    }
68
69    let mut conf_string = String::new();
70    File::open(&path).and_then(|mut f| f.read_to_string(&mut conf_string))?;
71
72    let cargo_toml: Cargo = toml::from_str(&conf_string)?;
73
74    Ok(
75        if let Some(Metadata { x: Some(x) }) = cargo_toml.package.metadata {
76            x
77        } else {
78            HashMap::new()
79        },
80    )
81}
82
83pub fn get() -> Result<Xconf, Error> {
84    let x_conf: Xconf =
85        dotx()?.into_iter().chain(x()?).chain(cargo()?).collect();
86
87    for pair in x_conf.clone().into_iter() {
88        match pair {
89            (ref k, _) if k == "x" => {
90                // avoid problem caused by run `cargo-x x` directly
91                return Err(format_err!("command key `x` is reserved"));
92            }
93            _ => {}
94        }
95    }
96
97    Ok(x_conf)
98}