1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2016, 2018 vergen developers
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

//! Geneer
//! the `include!` macro within your project.
use crate::constants::{ConstantsFlags, CONST_PREFIX, CONST_TYPE};
use crate::output::generate_build_info;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use super::Result;

fn gen_const<W: Write>(f: &mut W, comment: &str, name: &str, value: &str) -> Result<()> {
    writeln!(
        f,
        "{}\n{}{}{}\"{}\";",
        comment, CONST_PREFIX, name, CONST_TYPE, value
    )?;
    Ok(())
}

/// Create a `version.rs` file in `OUT_DIR` and write the toggled on constants
/// to the file.
///
/// # Errors
/// * File related problems can throw errors
/// * Can throw the other errors from `generate_build_info`
///
/// # Example build.rs
/// ```
/// # extern crate vergen;
/// #
/// # use std::env;
/// # use vergen::{ConstantsFlags, generate_version_rs};
/// #
/// fn main() {
/// #   env::set_var("OUT_DIR", "target");
///     let mut flags = ConstantsFlags::all();
///     flags.toggle(ConstantsFlags::BUILD_TIMESTAMP);
///     generate_version_rs(flags).expect("Unable to generate constants!");
/// }
/// ```
///
/// # Example Output (All Flags Enabled)
/// ```
/// /// Build Timestamp (UTC)
/// pub const VERGEN_BUILD_TIMESTAMP: &str = "2018-08-09T15:15:57.282334589+00:00";
///
/// /// Build Date - Short (UTC)
/// pub const VERGEN_BUILD_DATE: &str = "2018-08-09";
///
/// /// Commit SHA
/// pub const VERGEN_SHA: &str = "75b390dc6c05a6a4aa2791cc7b3934591803bc22";
///
/// /// Commit SHA - Short
/// pub const VERGEN_SHA_SHORT: &str = "75b390d";
///
/// /// Commit Date
/// pub const VERGEN_COMMIT_DATE: &str = "'2018-08-08'";
///
/// /// Target Triple
/// pub const VERGEN_TARGET_TRIPLE: &str = "x86_64-unknown-linux-gnu";
///
/// /// Semver
/// pub const VERGEN_SEMVER: &str = "v0.1.0-pre.0";
///
/// /// Semver (Lightweight)
/// pub const VERGEN_SEMVER_LIGHTWEIGHT: &str = "v0.1.0-pre.0";
///
/// /// Branch
/// pub const VERGEN_BRANCH: &str ="master";
/// ```
///
/// ## Include the constants in your code (Version 1.x.x only)
/// ```ignore
/// include!(concat!(env!("OUT_DIR"), "/version.rs"));
///
/// format!("{} {} blah {}", VERGEN_BUILD_TIMESTAMP, VERGEN_SHA, VERGEN_SEMVER)
/// ```
#[deprecated(since = "2.0.0", note = "Please use `generate_cargo_keys` instead")]
pub fn generate_version_rs(flags: ConstantsFlags) -> Result<()> {
    let dst = PathBuf::from(env::var("OUT_DIR")?);
    let mut f = File::create(&dst.join("version.rs"))?;
    let build_info = generate_build_info(flags)?;

    for (k, v) in build_info {
        gen_const(&mut f, k.comment(), k.name(), &v)?;
        writeln!(f)?;
    }

    Ok(())
}

#[cfg(test)]
mod test {
    use super::gen_const;
    use crate::constants::ConstantsFlags;
    use crate::output::generate_build_info;
    use lazy_static::lazy_static;
    use regex::Regex;
    use std::io::Cursor;

    lazy_static! {
        static ref CONST_RE: Regex =
            Regex::new(r#"^/// .*[\r\n]+pub const [A-Z_]+: \&str = ".*";[\r\n]+$"#)
                .expect("Unable to create const regex");
    }

    #[test]
    fn gen_const_output() {
        let flags = ConstantsFlags::all();
        let build_info = generate_build_info(flags).expect("Unable to generate build_info map!");

        for (k, v) in build_info {
            let buffer = Vec::new();
            let mut cursor = Cursor::new(buffer);
            gen_const(&mut cursor, k.comment(), k.name(), &v)
                .expect("Unable to generate const string");
            let const_str = String::from_utf8_lossy(&cursor.get_ref());
            assert!(CONST_RE.is_match(&const_str));
        }
    }
}