assemble_core/
cargo.rs

1//! Provides a wrapper around cargo environment variables set during compilation.
2//!
3//! The available environment variables can be found [here](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates)
4
5use heck::ToShoutySnakeCase;
6
7use std::collections::HashMap;
8use std::env::vars;
9use std::path::PathBuf;
10
11/// Provides access to cargo environment variables. Getting an instance of this struct
12/// guarantees the existence of cargo related variables
13#[derive(Debug)]
14pub struct CargoEnv {
15    vars: HashMap<String, String>,
16}
17
18impl CargoEnv {
19    /// Get an entry by name. The name is automatically converted into upper snake case.
20    ///
21    /// If the key is not immediately available, `CARGO_` is appended to the front and that is also searched.
22    pub fn get_entry<S: AsRef<str>>(&self, key: S) -> Option<&str> {
23        let key = key.as_ref().to_shouty_snake_case();
24        println!("key = {:?}", key);
25        self.vars
26            .get(&key)
27            .or_else(|| self.vars.get(&format!("CARGO_{}", key)))
28            .map(|s| s.as_str())
29    }
30
31    /// Gets the name of the current package
32    pub fn package_name(&self) -> &str {
33        self.get_entry("pkg-name")
34            .expect("Should always be available")
35    }
36
37    /// Gets the manifest directory
38    pub fn manifest_directory(&self) -> PathBuf {
39        PathBuf::from(
40            self.get_entry("manifest-dir")
41                .expect("Should always be available"),
42        )
43    }
44}
45
46/// Gets the cargo environment if available
47pub fn get_cargo_env() -> Option<CargoEnv> {
48    let vars: HashMap<String, String> = HashMap::from_iter(vars());
49    if vars.contains_key("CARGO") {
50        Some(CargoEnv {
51            vars: vars
52                .into_iter()
53                .filter(|(key, _)| key.starts_with("CARGO") || key == "OUT_DIR")
54                .collect(),
55        })
56    } else {
57        None
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use crate::cargo::get_cargo_env;
64
65    #[test]
66    fn can_get_env() {
67        let _ = get_cargo_env().expect("should be available because running tests through cargo");
68    }
69
70    #[test]
71    fn can_get_pkg_name() {
72        let cargo = get_cargo_env().unwrap();
73        let name = cargo
74            .get_entry("pkg-name")
75            .expect("Failed because CARGO_ wasn't appended");
76        assert_eq!(name, "assemble-core");
77    }
78
79    #[test]
80    fn can_get_manifest_dir() {
81        let cargo = get_cargo_env().unwrap();
82        let dir = cargo.manifest_directory();
83        assert!(dir.ends_with("assemble-core"));
84    }
85}