1 // Copyright (c) 2016, 2018 vergen developers
2 //
3 // Licensed under the Apache License, Version 2.0
4 // <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. All files in the project carrying such notice may not be copied,
7 // modified, or distributed except according to those terms.
8 
9 //! Output types
10 use chrono::Utc;
11 use crate::constants::*;
12 use failure::Fallible;
13 use std::collections::HashMap;
14 use std::env;
15 use std::process::Command;
16 
17 pub mod codegen;
18 pub mod envvar;
19 
generate_build_info(flags: ConstantsFlags) -> Fallible<HashMap<VergenKey, String>>20 pub fn generate_build_info(flags: ConstantsFlags) -> Fallible<HashMap<VergenKey, String>> {
21     let mut build_info = HashMap::new();
22     let now = Utc::now();
23 
24     if flags.contains(ConstantsFlags::BUILD_TIMESTAMP) {
25         build_info.insert(VergenKey::BuildTimestamp, now.to_rfc3339());
26     }
27 
28     if flags.contains(ConstantsFlags::BUILD_DATE) {
29         build_info.insert(VergenKey::BuildDate, now.format("%Y-%m-%d").to_string());
30     }
31 
32     if flags.contains(ConstantsFlags::SHA) {
33         let sha = run_command(Command::new("git").args(&["rev-parse", "HEAD"]));
34         build_info.insert(VergenKey::Sha, sha);
35     }
36 
37     if flags.contains(ConstantsFlags::SHA_SHORT) {
38         let sha = run_command(Command::new("git").args(&["rev-parse", "--short", "HEAD"]));
39         build_info.insert(VergenKey::ShortSha, sha);
40     }
41 
42     if flags.contains(ConstantsFlags::COMMIT_DATE) {
43         let commit_date = run_command(Command::new("git").args(&[
44             "log",
45             "--pretty=format:'%ad'",
46             "-n1",
47             "--date=short",
48         ]));
49         build_info.insert(
50             VergenKey::CommitDate,
51             commit_date.trim_matches('\'').to_string(),
52         );
53     }
54 
55     if flags.contains(ConstantsFlags::TARGET_TRIPLE) {
56         let target_triple = env::var("TARGET").unwrap_or_else(|_| "UNKNOWN".to_string());
57         build_info.insert(VergenKey::TargetTriple, target_triple);
58     }
59 
60     if flags.contains(ConstantsFlags::SEMVER) {
61         let describe = run_command(Command::new("git").args(&["describe"]));
62 
63         let semver = if describe.is_empty() {
64             env::var("CARGO_PKG_VERSION")?
65         } else {
66             describe
67         };
68         build_info.insert(VergenKey::Semver, semver);
69     } else if flags.contains(ConstantsFlags::SEMVER_FROM_CARGO_PKG) {
70         build_info.insert(VergenKey::Semver, env::var("CARGO_PKG_VERSION")?);
71     }
72 
73     if flags.contains(ConstantsFlags::SEMVER_LIGHTWEIGHT) {
74         let describe = run_command(Command::new("git").args(&["describe", "--tags"]));
75 
76         let semver = if describe.is_empty() {
77             env::var("CARGO_PKG_VERSION")?
78         } else {
79             describe
80         };
81         build_info.insert(VergenKey::SemverLightweight, semver);
82     }
83 
84     Ok(build_info)
85 }
86 
run_command(command: &mut Command) -> String87 fn run_command(command: &mut Command) -> String {
88     let raw_output = if let Ok(o) = command.output() {
89         String::from_utf8_lossy(&o.stdout).into_owned()
90     } else {
91         "UNKNOWN".to_string()
92     };
93     raw_output.trim().to_string()
94 }
95 
96 /// Build information keys.
97 #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
98 pub enum VergenKey {
99     /// The build timestamp. (VERGEN_BUILD_TIMESTAMP)
100     BuildTimestamp,
101     /// The build date. (VERGEN_BUILD_DATE)
102     BuildDate,
103     /// The latest commit SHA. (VERGEN_SHA)
104     Sha,
105     /// The latest commit short SHA. (VERGEN_SHA_SHORT)
106     ShortSha,
107     /// The commit date. (VERGEN_COMMIT_DATE).
108     CommitDate,
109     /// The target triple. (VERGEN_TARGET_TRIPLE)
110     TargetTriple,
111     /// The semver version from the last git tag. (VERGEN_SEMVER)
112     Semver,
113     /// The semver version from the last git tag, including lightweight.
114     /// (VERGEN_SEMVER_LIGHTWEIGHT)
115     SemverLightweight,
116 }
117 
118 impl VergenKey {
119     /// Get the comment string for the given key.
comment(self) -> &'static str120     pub fn comment(self) -> &'static str {
121         match self {
122             VergenKey::BuildTimestamp => BUILD_TIMESTAMP_COMMENT,
123             VergenKey::BuildDate => BUILD_DATE_COMMENT,
124             VergenKey::Sha => SHA_COMMENT,
125             VergenKey::ShortSha => SHA_SHORT_COMMENT,
126             VergenKey::CommitDate => COMMIT_DATE_COMMENT,
127             VergenKey::TargetTriple => TARGET_TRIPLE_COMMENT,
128             VergenKey::Semver => SEMVER_COMMENT,
129             VergenKey::SemverLightweight => SEMVER_TAGS_COMMENT,
130         }
131     }
132 
133     /// Get the name for the given key.
name(self) -> &'static str134     pub fn name(self) -> &'static str {
135         match self {
136             VergenKey::BuildTimestamp => BUILD_TIMESTAMP_NAME,
137             VergenKey::BuildDate => BUILD_DATE_NAME,
138             VergenKey::Sha => SHA_NAME,
139             VergenKey::ShortSha => SHA_SHORT_NAME,
140             VergenKey::CommitDate => COMMIT_DATE_NAME,
141             VergenKey::TargetTriple => TARGET_TRIPLE_NAME,
142             VergenKey::Semver => SEMVER_NAME,
143             VergenKey::SemverLightweight => SEMVER_TAGS_NAME,
144         }
145     }
146 }
147 
148 #[cfg(test)]
149 mod test {}
150