| 1 | //! Various convenience functions for `built` at runtime. |
| 2 | |
| 3 | use std::fmt; |
| 4 | use std::fmt::Write; |
| 5 | |
| 6 | #[cfg (feature = "git2" )] |
| 7 | pub use crate::git::{get_repo_description, get_repo_head}; |
| 8 | |
| 9 | #[cfg (feature = "chrono" )] |
| 10 | pub use crate::krono::strptime; |
| 11 | |
| 12 | /// Parses version-strings with `semver::Version::parse()`. |
| 13 | /// |
| 14 | /// This function is only available if `built` was compiled with the |
| 15 | /// `semver` feature. |
| 16 | /// |
| 17 | /// The function takes a reference to an array of names and version numbers as |
| 18 | /// serialized by `built` and returns an iterator over the unchanged names |
| 19 | /// and parsed version numbers. |
| 20 | /// |
| 21 | /// ``` |
| 22 | /// pub mod build_info { |
| 23 | /// pub static DEPENDENCIES: [(&'static str, &'static str); 1] = [("built", "0.1.0")]; |
| 24 | /// } |
| 25 | /// |
| 26 | /// let deps = build_info::DEPENDENCIES; |
| 27 | /// assert!(built::util::parse_versions(&deps) |
| 28 | /// .any(|(name, ver)| name == "built" && |
| 29 | /// ver >= semver::Version::parse("0.1.0").unwrap())); |
| 30 | /// ``` |
| 31 | /// |
| 32 | /// # Panics |
| 33 | /// If a version can't be parsed by `semver::Version::parse()`. This should never |
| 34 | /// happen with version strings provided by Cargo and `built`. |
| 35 | #[cfg (feature = "semver" )] |
| 36 | pub fn parse_versions<'a, T>( |
| 37 | name_and_versions: T, |
| 38 | ) -> impl Iterator<Item = (&'a str, semver::Version)> |
| 39 | where |
| 40 | T: IntoIterator<Item = &'a (&'a str, &'a str)>, |
| 41 | { |
| 42 | fn parse_version<'a>(t: &'a (&'a str, &'a str)) -> (&'a str, semver::Version) { |
| 43 | (t.0, t.1.parse().unwrap()) |
| 44 | } |
| 45 | name_and_versions.into_iter().map(parse_version) |
| 46 | } |
| 47 | |
| 48 | /// Detect execution on various Continuous Integration platforms. |
| 49 | /// |
| 50 | /// CI-platforms are detected by the presence of known environment variables. |
| 51 | /// This allows to detect specific CI-platform (like `GitLab`); various |
| 52 | /// generic environment variables are also checked, which may result in |
| 53 | /// `CIPlatform::Generic`. |
| 54 | /// |
| 55 | /// Since some platforms have fairly generic environment variables to begin with |
| 56 | /// (e.g. `TASK_ID`), this function may have false positives. |
| 57 | #[must_use ] |
| 58 | pub fn detect_ci() -> Option<super::CIPlatform> { |
| 59 | crate::environment::EnvironmentMap::new().detect_ci() |
| 60 | } |
| 61 | |
| 62 | pub(crate) struct ArrayDisplay<'a, T, F>(pub &'a [T], pub F) |
| 63 | where |
| 64 | F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result; |
| 65 | |
| 66 | impl<T, F> fmt::Display for ArrayDisplay<'_, T, F> |
| 67 | where |
| 68 | F: Fn(&T, &mut fmt::Formatter<'_>) -> fmt::Result, |
| 69 | { |
| 70 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 71 | f.write_char('[' )?; |
| 72 | for (i: usize, v: &T) in self.0.iter().enumerate() { |
| 73 | if i != 0 { |
| 74 | f.write_str(data:", " )?; |
| 75 | } |
| 76 | (self.1)(v, f)?; |
| 77 | } |
| 78 | f.write_char(']' ) |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | #[cfg (feature = "cargo-lock" )] |
| 83 | pub(crate) struct TupleArrayDisplay<'a, T>(pub &'a [(T, T)]); |
| 84 | |
| 85 | #[cfg (feature = "cargo-lock" )] |
| 86 | impl<T> fmt::Display for TupleArrayDisplay<'_, T> |
| 87 | where |
| 88 | T: AsRef<str>, |
| 89 | { |
| 90 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 91 | write!( |
| 92 | f, |
| 93 | "{}" , |
| 94 | ArrayDisplay(self.0, |(a, b), fmt| write!( |
| 95 | fmt, |
| 96 | r#"("{}", "{}")"# , |
| 97 | a.as_ref().escape_default(), |
| 98 | b.as_ref().escape_default() |
| 99 | )) |
| 100 | ) |
| 101 | } |
| 102 | } |
| 103 | |