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 | |