diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 00000000..14492b84 --- /dev/null +++ b/.clippy.toml @@ -0,0 +1 @@ +max-struct-bools = 6 \ No newline at end of file diff --git a/README.md b/README.md index aec7df47..34459431 100644 --- a/README.md +++ b/README.md @@ -13,37 +13,35 @@ Generate build, git, and rustc related 'cargo:rustc-env' instructions via 'build See the documentation at [docs.rs](https://docs.rs/vergen) for example usage ## Release 4 Breaking Changes -* The main entry point for use has changed from `generate_cargo_keys` to `gen` +* The main entry point for use has changed from `generate_cargo_keys` to `vergen` * There are now 4 features that allow you to control what instructions can be generated (`build`, `cargo`, `git`, and `rustc`). * The `build` feature enables the `VERGEN_BUILD_*` instructions. * The `git` feature enables the `VERGEN_GIT_*` instructions and the `cargo:rerun-if-changed` instructions. * The `rustc` feature enables the `VERGEN_RUSTC_*` instructions. * The `cargo` feature enables the `VERGEN_CARGO_*` instructions. * By default, all features are enabled. - * You can build with all features disabled, which basically make the `gen` function a no-op. - * You can still use `ConstantsFlags` to toggle individual cargo instructions. + * You can build with all features disabled, which basically make the `vergen` function a no-op. + * You can still use `ConstantsFlags` with the `gen` function to toggle individual cargo instructions, but it has been deprecated. * The generated instructions have been normalized. Therefore, you may need to update what env variable you are referring to in code. I've included a list below of the full set of instructions that can be generated for reference. ```text, no_run -cargo:rustc-env=VERGEN_BUILD_DATE=2021-02-12 -cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2021-02-12T01:54:15.134750+00:00 -cargo:rustc-env=VERGEN_GIT_BRANCH=feature/git2 -cargo:rustc-env=VERGEN_GIT_COMMIT_DATE=2021-02-11T20:05:53-05:00 -cargo:rustc-env=VERGEN_GIT_SEMVER=v3.2.0-86-g95fc0f5 -cargo:rustc-env=VERGEN_GIT_SEMVER_LIGHTWEIGHT=blah-33-g95fc0f5 -cargo:rustc-env=VERGEN_GIT_SHA=95fc0f5d066710f16e0c23ce3239d6e040abca0d -cargo:rustc-env=VERGEN_GIT_SHA_SHORT=95fc0f5 +cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2021-02-25T23:28:39.493201+00:00 +cargo:rustc-env=VERGEN_BUILD_SEMVER=4.1.0 +cargo:rustc-env=VERGEN_GIT_BRANCH=feature/datetime-toggles +cargo:rustc-env=VERGEN_GIT_COMMIT_TIMESTAMP=2021-02-24T20:55:21+00:00 +cargo:rustc-env=VERGEN_GIT_SEMVER=4.1.0-2-gf49246c +cargo:rustc-env=VERGEN_GIT_SHA=f49246ce334567bff9f950bfd0f3078184a2738a cargo:rustc-env=VERGEN_RUSTC_CHANNEL=nightly -cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=2021-02-10 -cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=07194ffcd25b0871ce560b9f702e52db27ac9f77 +cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=2021-02-24 +cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=a8486b64b0c87dabd045453b6c81500015d122d6 cargo:rustc-env=VERGEN_RUSTC_HOST_TRIPLE=x86_64-apple-darwin cargo:rustc-env=VERGEN_RUSTC_LLVM_VERSION=11.0 cargo:rustc-env=VERGEN_RUSTC_SEMVER=1.52.0-nightly cargo:rustc-env=VERGEN_CARGO_TARGET_TRIPLE=x86_64-unknown-linux-gnu cargo:rustc-env=VERGEN_CARGO_PROFILE=debug cargo:rustc-env=VERGEN_CARGO_FEATURES=git,build -cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/HEAD -cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/refs/heads/feature/git2 +cargo:rerun-if-changed=/Users/kon8116/projects/rust-lang/vergen/.git/HEAD +cargo:rerun-if-changed=/Users/kon8116/projects/rust-lang/vergen/.git/refs/heads/feature/datetime-toggles ``` * Under the hood, the `Command`s used for git have been removed in lieu of using the `git2` library directly. diff --git a/src/config.rs b/src/config.rs index 73acee95..65873e17 100644 --- a/src/config.rs +++ b/src/config.rs @@ -8,16 +8,27 @@ //! `vergen` configuration +#[cfg(feature = "build")] +use crate::feature::Build; +#[cfg(feature = "cargo")] +use crate::feature::Cargo; +#[cfg(feature = "git")] +use crate::feature::Git; +#[cfg(feature = "rustc")] +use crate::feature::Rustc; use crate::{ constants::{ - ConstantsFlags, BUILD_DATE_NAME, BUILD_TIMESTAMP_NAME, CARGO_FEATURES, CARGO_PROFILE, - CARGO_TARGET_TRIPLE, GIT_BRANCH_NAME, GIT_COMMIT_DATE_NAME, GIT_SEMVER_NAME, - GIT_SEMVER_TAGS_NAME, GIT_SHA_NAME, GIT_SHA_SHORT_NAME, RUSTC_CHANNEL_NAME, - RUSTC_COMMIT_DATE, RUSTC_COMMIT_HASH, RUSTC_HOST_TRIPLE_NAME, RUSTC_LLVM_VERSION, - RUSTC_SEMVER_NAME, + ConstantsFlags, BUILD_DATE_NAME, BUILD_SEMVER_NAME, BUILD_TIMESTAMP_NAME, BUILD_TIME_NAME, + CARGO_FEATURES, CARGO_PROFILE, CARGO_TARGET_TRIPLE, GIT_BRANCH_NAME, GIT_COMMIT_DATE_NAME, + GIT_COMMIT_TIMESTAMP_NAME, GIT_COMMIT_TIME_NAME, GIT_SEMVER_NAME, GIT_SEMVER_TAGS_NAME, + GIT_SHA_NAME, GIT_SHA_SHORT_NAME, RUSTC_CHANNEL_NAME, RUSTC_COMMIT_DATE, RUSTC_COMMIT_HASH, + RUSTC_HOST_TRIPLE_NAME, RUSTC_LLVM_VERSION, RUSTC_SEMVER_NAME, }, error::Result, - feature::{add_build_config, add_cargo_config, add_git_config, add_rustc_config}, + feature::{ + add_build_config, add_cargo_config, add_git_config, add_rustc_config, configure_build, + configure_cargo, configure_git, configure_rustc, + }, }; use enum_iterator::IntoEnumIterator; use getset::{Getters, MutGetters}; @@ -26,17 +37,116 @@ use std::{ path::{Path, PathBuf}, }; +/// Configure `vergen` to produce the `cargo:` instructions you need +/// +/// * See [`Build`](crate::Build) for details on `VERGEN_BUILD_*` instruction configuration +/// * See [`Cargo`](crate::Cargo) for details on `VERGEN_CARGO_*` instruction configuration +/// * See [`Git`](crate::Git) for details on `VERGEN_GIT_*` instruction configuration +/// * See [`Rustc`](crate::Rustc) for details on `VERGEN_RUSTC_*` instruction configuration +/// +/// # Example +/// +/// ``` +/// use vergen::Config; +#[cfg_attr(feature = "git", doc = r##"use vergen::TimeZone;"##)] +/// +/// let mut config = Config::default(); +#[cfg_attr( + feature = "build", + doc = r##" +// Turn off the build semver instruction +*config.build_mut().semver_mut() = false; +"## +)] +#[cfg_attr( + feature = "git", + doc = r##" +// Change the commit timestamp timezone to local +*config.git_mut().commit_timestamp_timezone_mut() = TimeZone::Local; +"## +)] +#[cfg_attr( + feature = "rustc", + doc = r##" +// Turn off the LLVM version instruction +*config.rustc_mut().llvm_version_mut() = false; +"## +)] +#[cfg_attr( + feature = "cargo", + doc = r##" +// Turn off the cargo profile instruction +*config.cargo_mut().profile_mut() = false; +"## +)] +/// ``` +#[derive(Clone, Copy, Debug, Getters, MutGetters)] +#[getset(get = "pub(crate)", get_mut = "pub")] +pub struct Instructions { + /// Use this to modify the [`Build`] feature configuration. + #[cfg(feature = "build")] + build: Build, + /// Use this to modify the [`Cargo`] feature configuration. + #[cfg(feature = "cargo")] + cargo: Cargo, + /// Use this to modify the [`Git`] feature configuration. + #[cfg(feature = "git")] + git: Git, + /// Use this to modify the [`Rustc`] feature configuration. + #[cfg(feature = "rustc")] + rustc: Rustc, +} + +impl Default for Instructions { + fn default() -> Self { + Self { + #[cfg(feature = "build")] + build: Build::default(), + #[cfg(feature = "cargo")] + cargo: Cargo::default(), + #[cfg(feature = "git")] + git: Git::default(), + #[cfg(feature = "rustc")] + rustc: Rustc::default(), + } + } +} + +impl Instructions { + pub(crate) fn config(self, repo_path: Option) -> Result + where + T: AsRef, + { + let mut config = Config::default(); + + configure_build(self, &mut config); + configure_git(self, repo_path, &mut config)?; + configure_rustc(self, &mut config)?; + configure_cargo(self, &mut config); + + Ok(config) + } +} + /// Build information keys. #[derive(Clone, Copy, Debug, IntoEnumIterator, Hash, Eq, Ord, PartialEq, PartialOrd)] pub(crate) enum VergenKey { /// The build date. (VERGEN_BUILD_DATE) BuildDate, + /// The build time. (VERGEN_BUILD_TIME) + BuildTime, /// The build timestamp. (VERGEN_BUILD_TIMESTAMP) BuildTimestamp, + /// The build semver. (VERGEN_BUILD_SEMVER) + BuildSemver, /// The current working branch name (VERGEN_BRANCH) Branch, - /// The commit date. (VERGEN_COMMIT_DATE). + /// The commit date. (VERGEN_COMMIT_DATE) CommitDate, + /// The commit time. (VERGEN_COMMIT_TIME) + CommitTime, + /// The commit timestamp. (VERGEN_COMMIT_TIMESTAMP) + CommitTimestamp, /// The semver version from the last git tag. (VERGEN_SEMVER) Semver, /// The semver version from the last git tag, including lightweight. @@ -71,9 +181,13 @@ impl VergenKey { pub(crate) fn name(self) -> &'static str { match self { VergenKey::BuildDate => BUILD_DATE_NAME, + VergenKey::BuildTime => BUILD_TIME_NAME, VergenKey::BuildTimestamp => BUILD_TIMESTAMP_NAME, + VergenKey::BuildSemver => BUILD_SEMVER_NAME, VergenKey::Branch => GIT_BRANCH_NAME, VergenKey::CommitDate => GIT_COMMIT_DATE_NAME, + VergenKey::CommitTime => GIT_COMMIT_TIME_NAME, + VergenKey::CommitTimestamp => GIT_COMMIT_TIMESTAMP_NAME, VergenKey::Semver => GIT_SEMVER_NAME, VergenKey::SemverLightweight => GIT_SEMVER_TAGS_NAME, VergenKey::Sha => GIT_SHA_NAME, @@ -128,10 +242,80 @@ impl Config { #[cfg(test)] mod test { - use super::Config; + use super::{Config, Instructions}; #[test] - fn default_works() { + fn default_config_works() { assert!(!Config::default().cfg_map().is_empty()); } + + #[cfg(feature = "build")] + fn check_build_config(instructions: &Instructions) { + use crate::{TimeZone, TimestampKind}; + + let config = instructions.build(); + assert!(config.has_enabled()); + assert!(config.timestamp()); + assert_eq!(*config.timezone(), TimeZone::Utc); + assert_eq!(*config.kind(), TimestampKind::Timestamp); + assert!(config.semver()); + } + + #[cfg(not(feature = "build"))] + fn check_build_config(_instructions: &Instructions) {} + + #[cfg(feature = "cargo")] + fn check_cargo_config(instructions: &Instructions) { + let config = instructions.cargo(); + assert!(config.has_enabled()); + assert!(config.features()); + assert!(config.profile()); + assert!(config.target_triple()); + } + + #[cfg(not(feature = "cargo"))] + fn check_cargo_config(_instructions: &Instructions) {} + + #[cfg(feature = "git")] + fn check_git_config(instructions: &Instructions) { + use crate::{SemverKind, ShaKind, TimeZone, TimestampKind}; + + let config = instructions.git(); + assert!(config.has_enabled()); + assert!(config.branch()); + assert!(config.commit_timestamp()); + assert_eq!(*config.commit_timestamp_timezone(), TimeZone::Utc); + assert_eq!(*config.commit_timestamp_kind(), TimestampKind::Timestamp); + assert!(config.rerun_on_head_change()); + assert!(config.semver()); + assert_eq!(*config.semver_kind(), SemverKind::Normal); + assert!(config.sha()); + assert_eq!(*config.sha_kind(), ShaKind::Normal); + } + + #[cfg(not(feature = "git"))] + fn check_git_config(_instructions: &Instructions) {} + + #[cfg(feature = "rustc")] + fn check_rustc_config(instructions: &Instructions) { + let config = instructions.rustc(); + assert!(config.has_enabled()); + assert!(config.channel()); + assert!(config.commit_date()); + assert!(config.host_triple()); + assert!(config.llvm_version()); + assert!(config.sha()); + } + + #[cfg(not(feature = "rustc"))] + fn check_rustc_config(_instructions: &Instructions) {} + + #[test] + fn default_instructions() { + let default = Instructions::default(); + check_build_config(&default); + check_cargo_config(&default); + check_git_config(&default); + check_rustc_config(&default); + } } diff --git a/src/constants.rs b/src/constants.rs index 181da3e2..8c5a345f 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -11,6 +11,11 @@ use bitflags::bitflags; bitflags!( + /// **DEPRECATED** - [`ConstantsFlags`] has been deprecated in favor of [`Config`](crate::config::Instructions). + /// + /// Please make the switch to that instead. [`ConstantsFlags`] will be removed in + /// version 5. + /// /// Flags used to toggle individual `cargo:` instruction generation /// /// Use these to toggle off instructions you don't wish to generate @@ -178,10 +183,14 @@ bitflags!( // Build Constants pub(crate) const BUILD_TIMESTAMP_NAME: &str = "VERGEN_BUILD_TIMESTAMP"; pub(crate) const BUILD_DATE_NAME: &str = "VERGEN_BUILD_DATE"; +pub(crate) const BUILD_TIME_NAME: &str = "VERGEN_BUILD_TIME"; +pub(crate) const BUILD_SEMVER_NAME: &str = "VERGEN_BUILD_SEMVER"; // git Constants pub(crate) const GIT_BRANCH_NAME: &str = "VERGEN_GIT_BRANCH"; pub(crate) const GIT_COMMIT_DATE_NAME: &str = "VERGEN_GIT_COMMIT_DATE"; +pub(crate) const GIT_COMMIT_TIME_NAME: &str = "VERGEN_GIT_COMMIT_TIME"; +pub(crate) const GIT_COMMIT_TIMESTAMP_NAME: &str = "VERGEN_GIT_COMMIT_TIMESTAMP"; pub(crate) const GIT_SEMVER_NAME: &str = "VERGEN_GIT_SEMVER"; pub(crate) const GIT_SEMVER_TAGS_NAME: &str = "VERGEN_GIT_SEMVER_LIGHTWEIGHT"; pub(crate) const GIT_SHA_NAME: &str = "VERGEN_GIT_SHA"; diff --git a/src/feature/build.rs b/src/feature/build.rs index 7f87e474..b447bfaf 100644 --- a/src/feature/build.rs +++ b/src/feature/build.rs @@ -8,32 +8,104 @@ //! `vergen` build feature implementation -use crate::{config::Config, constants::ConstantsFlags}; +use crate::{ + config::{Config, Instructions}, + constants::ConstantsFlags, +}; #[cfg(feature = "build")] use { - crate::{config::VergenKey, feature::add_entry}, - chrono::Utc, + crate::{ + config::VergenKey, + feature::{add_entry, TimeZone, TimestampKind}, + }, + chrono::{DateTime, Local, Utc}, + getset::{Getters, MutGetters}, std::env, }; +/// Configuration for the `VERGEN_BUILD_*` instructions +/// +/// # Instructions +/// The following instructions can be generated: +/// +/// | Instruction | Default | +/// | ----------- | :-----: | +/// | `cargo:rustc-env=VERGEN_BUILD_DATE=2021-02-12` | | +/// | `cargo:rustc-env=VERGEN_BUILD_TIME=11:22:34` | | +/// | `cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2021-02-12T01:54:15.134750+00:00` | * | +/// | `cargo:rustc-env=VERGEN_BUILD_SEMVER=4.2.0` | * | +/// +/// * If the `timestamp` field is false, the date/time instructions will not be generated. +/// * If the `semver` field is false, the semver instruction will not be generated. +/// * **NOTE** - By default, the date/time related instructions will use [`UTC`](TimeZone::Utc). +/// * **NOTE** - The date/time instruction output is determined by the [`kind`](TimestampKind) field and can be any combination of the three. +/// +/// # Example +/// +/// ``` +/// # use vergen::Error; +/// use vergen::{vergen, Config}; +#[cfg_attr(feature = "build", doc = r##"use vergen::{TimestampKind, TimeZone};"##)] +/// +/// # pub fn main() -> Result<(), Error> { +/// let mut config = Config::default(); +#[cfg_attr( + feature = "build", + doc = r##" +// Generate all three date/time instructions +*config.build_mut().kind_mut() = TimestampKind::All; +// Change the date/time instructions to show `Local` time +*config.build_mut().timezone_mut() = TimeZone::Local; + +// Generate the instructions +vergen(config)?; +"## +)] +/// # Ok(()) +/// # } +#[cfg(feature = "build")] +#[derive(Clone, Copy, Debug, Getters, MutGetters)] +#[getset(get = "pub(crate)", get_mut = "pub")] +pub struct Build { + /// Enable/Disable the `VERGEN_BUILD_DATE`, `VERGEN_BUILD_TIME`, and `VERGEN_BUILD_TIMESTAMP` instructions. + timestamp: bool, + /// The timezone to use for the date/time instructions. + timezone: TimeZone, + /// The kind of date/time instructions to output. + kind: TimestampKind, + /// Enable/Disable the `VERGEN_BUILD_SEMVER` instruction. + semver: bool, +} + +#[cfg(feature = "build")] +impl Default for Build { + fn default() -> Self { + Self { + timestamp: true, + timezone: TimeZone::Utc, + kind: TimestampKind::Timestamp, + semver: true, + } + } +} + +#[cfg(feature = "build")] +impl Build { + pub(crate) fn has_enabled(self) -> bool { + self.timestamp || self.semver + } +} + #[cfg(feature = "build")] pub(crate) fn add_build_config(flags: ConstantsFlags, config: &mut Config) { // Setup datetime information let now = Utc::now(); if flags.contains(ConstantsFlags::BUILD_TIMESTAMP) { - add_entry( - config.cfg_map_mut(), - VergenKey::BuildTimestamp, - Some(now.to_rfc3339()), - ); + add_timestamp_entry(config, &now); } if flags.contains(ConstantsFlags::BUILD_DATE) { - add_entry( - config.cfg_map_mut(), - VergenKey::BuildDate, - Some(now.format("%Y-%m-%d").to_string()), - ); + add_date_entry(config, &now); } if flags.contains(ConstantsFlags::SEMVER_FROM_CARGO_PKG) { @@ -45,15 +117,102 @@ pub(crate) fn add_build_config(flags: ConstantsFlags, config: &mut Config) { } } +#[cfg(feature = "build")] +pub(crate) fn configure_build(instructions: Instructions, config: &mut Config) { + let build_config = instructions.build(); + + if build_config.has_enabled() { + if *build_config.timestamp() { + match build_config.timezone() { + TimeZone::Utc => add_config_entries(config, *build_config, &Utc::now()), + TimeZone::Local => add_config_entries(config, *build_config, &Local::now()), + }; + } + + if *build_config.semver() { + add_entry( + config.cfg_map_mut(), + VergenKey::BuildSemver, + env::var("CARGO_PKG_VERSION").ok(), + ); + } + } +} + +#[cfg(feature = "build")] +fn add_config_entries(config: &mut Config, build_config: Build, now: &DateTime) +where + T: chrono::TimeZone, + T::Offset: std::fmt::Display, +{ + match build_config.kind() { + TimestampKind::DateOnly => add_date_entry(config, now), + TimestampKind::TimeOnly => add_time_entry(config, now), + TimestampKind::DateAndTime => { + add_date_entry(config, now); + add_time_entry(config, now); + } + TimestampKind::Timestamp => add_timestamp_entry(config, now), + TimestampKind::All => { + add_date_entry(config, now); + add_time_entry(config, now); + add_timestamp_entry(config, now); + } + } +} + +#[cfg(feature = "build")] +fn add_date_entry(config: &mut Config, now: &DateTime) +where + T: chrono::TimeZone, + T::Offset: std::fmt::Display, +{ + add_entry( + config.cfg_map_mut(), + VergenKey::BuildDate, + Some(now.format("%Y-%m-%d").to_string()), + ); +} + +#[cfg(feature = "build")] +fn add_time_entry(config: &mut Config, now: &DateTime) +where + T: chrono::TimeZone, + T::Offset: std::fmt::Display, +{ + add_entry( + config.cfg_map_mut(), + VergenKey::BuildTime, + Some(now.format("%H:%M:%S").to_string()), + ); +} + +#[cfg(feature = "build")] +fn add_timestamp_entry(config: &mut Config, now: &DateTime) +where + T: chrono::TimeZone, + T::Offset: std::fmt::Display, +{ + add_entry( + config.cfg_map_mut(), + VergenKey::BuildTimestamp, + Some(now.to_rfc3339()), + ); +} + #[cfg(not(feature = "build"))] pub(crate) fn add_build_config(_flags: ConstantsFlags, _config: &mut Config) {} +#[cfg(not(feature = "build"))] +pub(crate) fn configure_build(_instructions: Instructions, _config: &mut Config) {} + #[cfg(all(test, feature = "build"))] mod test { use super::add_build_config; use crate::{ - config::{Config, VergenKey}, + config::{Config, Instructions, VergenKey}, constants::ConstantsFlags, + feature::{TimeZone, TimestampKind}, test::get_map_value, }; use lazy_static::lazy_static; @@ -93,6 +252,16 @@ mod test { check_build_keys(config.cfg_map()); check_build_instructions(config.cfg_map()); } + + #[test] + fn build_config() { + let mut config = Instructions::default(); + assert!(config.build().timestamp()); + assert_eq!(config.build().timezone(), &TimeZone::Utc); + assert_eq!(config.build().kind(), &TimestampKind::Timestamp); + *config.build_mut().kind_mut() = TimestampKind::All; + assert_eq!(config.build().kind(), &TimestampKind::All); + } } #[cfg(all(test, not(feature = "build")))] diff --git a/src/feature/cargo.rs b/src/feature/cargo.rs index 43df8d3c..4c69def4 100644 --- a/src/feature/cargo.rs +++ b/src/feature/cargo.rs @@ -8,13 +8,83 @@ //! `vergen` cargo feature -use crate::{config::Config, constants::ConstantsFlags}; +use crate::{ + config::{Config, Instructions}, + constants::ConstantsFlags, +}; #[cfg(feature = "cargo")] use { crate::{config::VergenKey, feature::add_entry}, + getset::{Getters, MutGetters}, std::env, }; +/// Configuration for the `VERGEN_CARGO_*` instructions +/// +/// # Instructions +/// The following instructions can be generated: +/// +/// | Instruction | Default | +/// | ----------- | :-----: | +/// | `cargo:rustc-env=VERGEN_CARGO_TARGET_TRIPLE=x86_64-unknown-linux-gnu` | * | +/// | `cargo:rustc-env=VERGEN_CARGO_PROFILE=debug` | * | +/// | `cargo:rustc-env=VERGEN_CARGO_FEATURES=git,build` | * | +/// +/// * If the `features` field is false, the features instruction will not be generated. +/// * If the `profile` field is false, the profile instruction will not be generated. +/// * If the `target_triple` field is false, the target triple instruction will not be generated. +/// * **NOTE** - the `target_triple` instruction can differ from the `host_triple` instruction, i.e. during cross compilation +/// +/// # Example +/// +/// ``` +/// # use vergen::Error; +/// use vergen::{vergen, Config}; +/// +/// # pub fn main() -> Result<(), Error> { +/// let mut config = Config::default(); +#[cfg_attr( + feature = "cargo", + doc = r##" +// Turn off the features instruction +*config.cargo_mut().features_mut() = false; + +// Generate the instructions +vergen(config)?; +"## +)] +/// # Ok(()) +/// # } +#[cfg(feature = "cargo")] +#[derive(Clone, Copy, Debug, Getters, MutGetters)] +#[getset(get = "pub(crate)", get_mut = "pub")] +pub struct Cargo { + /// Enable/Disable the `VERGEN_CARGO_FEATURES` instruction + features: bool, + /// Enable/Disable the `VERGEN_CARGO_PROFILE` instruction + profile: bool, + /// Enable/Disable the `VERGEN_CARGO_TARGET_TRIPLE` instruction + target_triple: bool, +} + +#[cfg(feature = "cargo")] +impl Default for Cargo { + fn default() -> Self { + Self { + features: true, + profile: true, + target_triple: true, + } + } +} + +#[cfg(feature = "cargo")] +impl Cargo { + pub(crate) fn has_enabled(self) -> bool { + self.features || self.profile || self.target_triple + } +} + #[cfg(feature = "cargo")] pub(crate) fn add_cargo_config(flags: ConstantsFlags, config: &mut Config) { if flags.intersects( @@ -62,11 +132,48 @@ fn is_cargo_feature(var: (String, String)) -> Option { #[cfg(not(feature = "cargo"))] pub(crate) fn add_cargo_config(_flags: ConstantsFlags, _config: &mut Config) {} +#[cfg(feature = "cargo")] +pub(crate) fn configure_cargo(instructions: Instructions, config: &mut Config) { + let cargo_config = instructions.cargo(); + + if cargo_config.has_enabled() { + if *cargo_config.target_triple() { + add_entry( + config.cfg_map_mut(), + VergenKey::CargoTargetTriple, + env::var("TARGET").ok(), + ); + } + + if *cargo_config.profile() { + add_entry( + config.cfg_map_mut(), + VergenKey::CargoProfile, + env::var("PROFILE").ok(), + ); + } + + if *cargo_config.features() { + let features: Vec = env::vars().filter_map(is_cargo_feature).collect(); + let feature_str = features.as_slice().join(","); + let value = if feature_str.is_empty() { + Some("default".to_string()) + } else { + Some(feature_str) + }; + add_entry(config.cfg_map_mut(), VergenKey::CargoFeatures, value); + } + } +} + +#[cfg(not(feature = "cargo"))] +pub(crate) fn configure_cargo(_instructions: Instructions, _config: &mut Config) {} + #[cfg(all(test, feature = "cargo"))] mod test { use super::add_cargo_config; use crate::{ - config::{Config, VergenKey}, + config::{Config, Instructions, VergenKey}, constants::ConstantsFlags, test::get_map_value, testutils::{setup, teardown}, @@ -120,6 +227,34 @@ mod test { check_cargo_instructions(config.cfg_map()); teardown(); } + + #[test] + #[serial_test::serial] + fn cargo_config() { + setup(); + let mut config = Instructions::default(); + assert!(config.cargo().features); + assert!(config.cargo().profile); + assert!(config.cargo().target_triple); + config.cargo_mut().features = false; + assert!(!config.cargo().features); + teardown(); + } + + #[test] + #[serial_test::serial] + fn config_default_feature_works() { + setup(); + env::remove_var("CARGO_FEATURE_GIT"); + env::remove_var("CARGO_FEATURE_BUILD"); + let mut config = Instructions::default(); + assert!(config.cargo().features); + assert!(config.cargo().profile); + assert!(config.cargo().target_triple); + config.cargo_mut().features = false; + assert!(!config.cargo().features); + teardown(); + } } #[cfg(all(test, not(feature = "cargo")))] diff --git a/src/feature/git.rs b/src/feature/git.rs index 7a4a05f7..9c2daf42 100644 --- a/src/feature/git.rs +++ b/src/feature/git.rs @@ -8,16 +8,149 @@ //! `vergen` git feature implementation -use crate::{config::Config, constants::ConstantsFlags, error::Result}; +use crate::{ + config::{Config, Instructions}, + constants::ConstantsFlags, + error::Result, +}; use std::path::Path; #[cfg(feature = "git")] use { - crate::{config::VergenKey, error::Error, feature::add_entry}, - chrono::{FixedOffset, TimeZone}, + crate::{ + config::VergenKey, + error::Error, + feature::{self, add_entry, TimestampKind}, + }, + chrono::{DateTime, FixedOffset, Local, TimeZone, Utc}, + getset::{Getters, MutGetters}, git2::{BranchType, DescribeOptions, Repository}, std::env, }; +/// The semver kind to output +#[cfg(feature = "git")] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum SemverKind { + /// Output the `git describe` kind + Normal, + /// Output the `git describe` kind including lightweight tags + Lightweight, +} + +/// The SHA kind to output +#[cfg(feature = "git")] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum ShaKind { + /// Output the normal 40 digit SHA + Normal, + /// Output the short 7 digit SHA + Short, +} + +/// Configuration for the `VERGEN_GIT_*` instructions +/// +/// # Instructions +/// The following instructions can be generated: +/// +/// | Instruction | Default | +/// | ----------- | :-----: | +/// | `cargo:rustc-env=VERGEN_GIT_BRANCH=feature/git2` | * | +/// | `cargo:rustc-env=VERGEN_GIT_COMMIT_DATE=2021-02-12` | | +/// | `cargo:rustc-env=VERGEN_GIT_COMMIT_TIME=01:54:15` | | +/// | `cargo:rustc-env=VERGEN_GIT_COMMIT_TIMESTAMP=2021-02-12T01:54:15.134750+00:00` | * | +/// | `cargo:rustc-env=VERGEN_GIT_SEMVER=v3.2.0-86-g95fc0f5d` | * | +/// | `cargo:rustc-env=VERGEN_GIT_SHA=95fc0f5d066710f16e0c23ce3239d6e040abca0d` | * | +/// | `cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/HEAD` | * | +/// | `cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/refs/heads/feature/git2` | * | +/// +/// * If the `branch` field is false, the `VERGEN_GIT_BRANCH` instruction will not be generated. +/// * If the `commit_timestamp` field is false, the date/time instructions will not be generated. +/// * If the `rerun_on_head_changed` field is false, the `cargo:rerun-if-changed` instructions will not be generated. +/// * If the `semver` field is false, the `VERGEN_GIT_SEMVER` instruction will not be generated. +/// * If the `sha` field is fale, the `VERGEN_GIT_SHA` instruction will not be generated. +/// * **NOTE** - The SHA defaults to the [`Normal`](ShaKind::Normal) variant, but can be changed via the `sha_kind` field. +/// * **NOTE** - The [SemVer] defaults to the [`Normal`](SemverKind::Normal) variant, but can be changed via the `semver_kind` field. +/// * **NOTE** - The [SemVer] is only useful if you have tags on your repository. If your repository has no tags, this will default to [`CARGO_PKG_VERSION`]. +/// * **NOTE** - The [`Lightweight`](SemverKind::Lightweight) variant will only differ from the [`Normal`](SemverKind::Normal) variant if you use [lightweight] tags in your repository. +/// * **NOTE** - By default, the date/time related instructions will use [`UTC`](crate::TimeZone::Utc). +/// * **NOTE** - The date/time instruction output is determined by the [`kind`](crate::TimestampKind) field and can be any combination of the three. +/// * **NOTE** - If the `rerun_on_head_chaged` instructions are enabled, cargo` will re-run the build script when either `<gitpath>/HEAD` or the file that `<gitpath>/HEAD` points at changes. +/// +/// # Example +/// +/// ``` +/// # use vergen::Error; +/// use vergen::{vergen, Config}; +#[cfg_attr(feature = "git", doc = r##"use vergen::ShaKind;"##)] +/// +/// # pub fn main() -> Result<(), Error> { +/// let mut config = Config::default(); +#[cfg_attr( + feature = "git", + doc = r##" +// Change the SHA output to the short variant +*config.git_mut().sha_kind_mut() = ShaKind::Short; + +// Generate the instructions +vergen(config)?; +"## +)] +/// # Ok(()) +/// # } +/// ``` +/// +/// [SemVer]: https://semver.org/ +/// [lightweight]: https://git-scm.com/book/en/v2/Git-Basics-Tagging +/// [`CARGO_PKG_VERSION`]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates +/// +#[cfg(feature = "git")] +#[derive(Clone, Copy, Debug, Getters, MutGetters)] +#[getset(get = "pub(crate)", get_mut = "pub")] +pub struct Git { + /// Enable/Disable the `VERGEN_GIT_BRANCH` instruction + branch: bool, + /// Enable/Disable the `VERGEN_GIT_COMMIT_DATE`, `VERGEN_GIT_COMMIT_TIME`, and `VERGEN_GIT_COMMIT_TIMESTAMP` instructions + commit_timestamp: bool, + /// The timezone to use for the date/time instructions. + commit_timestamp_timezone: feature::TimeZone, + /// The kind of date/time instructions to output. + commit_timestamp_kind: TimestampKind, + /// Enable/Disable the `cargo:rerun-if-changed` instructions + rerun_on_head_change: bool, + /// Enable/Disable the `VERGEN_GIT_SEMVER` instruction + semver: bool, + /// The kind of semver instruction to output. + semver_kind: SemverKind, + /// Enable/Disable the `VERGEN_GIT_SHA` instruction + sha: bool, + /// The kind of SHA instruction to output. + sha_kind: ShaKind, +} + +#[cfg(feature = "git")] +impl Default for Git { + fn default() -> Self { + Self { + branch: true, + commit_timestamp: true, + commit_timestamp_timezone: feature::TimeZone::Utc, + commit_timestamp_kind: TimestampKind::Timestamp, + rerun_on_head_change: true, + semver: true, + semver_kind: SemverKind::Normal, + sha: true, + sha_kind: ShaKind::Normal, + } + } +} + +#[cfg(feature = "git")] +impl Git { + pub(crate) fn has_enabled(&self) -> bool { + self.branch || self.commit_timestamp || self.rerun_on_head_change || self.semver || self.sha + } +} + #[cfg(not(feature = "git"))] pub(crate) fn add_git_config( _flags: ConstantsFlags, @@ -30,6 +163,18 @@ where Ok(()) } +#[cfg(not(feature = "git"))] +pub(crate) fn configure_git( + _instructions: Instructions, + _repo: Option, + _config: &mut Config, +) -> Result<()> +where + T: AsRef, +{ + Ok(()) +} + #[cfg(feature = "git")] pub(crate) fn add_git_config( flags: ConstantsFlags, @@ -60,8 +205,13 @@ where let commit = ref_head.peel_to_commit()?; if flags.contains(ConstantsFlags::COMMIT_DATE) { - let offset = FixedOffset::east(commit.time().offset_minutes() * 60) - .timestamp(commit.time().seconds(), 0); + let offset = if commit.time().sign() == '-' { + FixedOffset::west(commit.time().offset_minutes() * 60) + .timestamp(commit.time().seconds(), 0) + } else { + FixedOffset::east(commit.time().offset_minutes() * 60) + .timestamp(commit.time().seconds(), 0) + }; add_entry( config.cfg_map_mut(), VergenKey::CommitDate, @@ -110,6 +260,155 @@ where Ok(()) } +#[cfg(feature = "git")] +pub(crate) fn configure_git( + instructions: Instructions, + repo_path_opt: Option, + config: &mut Config, +) -> Result<()> +where + T: AsRef, +{ + if let Some(repo_path) = repo_path_opt { + let git_config = instructions.git(); + if git_config.has_enabled() { + let repo = Repository::discover(repo_path)?; + let ref_head = repo.find_reference("HEAD")?; + let repo_path = repo.path().to_path_buf(); + + if *git_config.branch() { + add_branch_name(&repo, config)?; + } + + if *git_config.commit_timestamp() || *git_config.sha() { + let commit = ref_head.peel_to_commit()?; + + if *git_config.commit_timestamp() { + let offset = if commit.time().sign() == '-' { + FixedOffset::west(commit.time().offset_minutes() * 60) + .timestamp(commit.time().seconds(), 0) + } else { + FixedOffset::east(commit.time().offset_minutes() * 60) + .timestamp(commit.time().seconds(), 0) + }; + + match git_config.commit_timestamp_timezone() { + crate::TimeZone::Utc => { + add_config_entries(config, *git_config, &offset.with_timezone(&Utc)) + } + crate::TimeZone::Local => { + add_config_entries(config, *git_config, &offset.with_timezone(&Local)) + } + } + } + + if *git_config.sha() { + match git_config.sha_kind() { + crate::ShaKind::Normal => { + add_entry( + config.cfg_map_mut(), + VergenKey::Sha, + Some(commit.id().to_string()), + ); + } + crate::ShaKind::Short => { + let obj = repo.revparse_single("HEAD")?; + add_entry( + config.cfg_map_mut(), + VergenKey::ShortSha, + obj.short_id()?.as_str().map(str::to_string), + ); + } + } + } + } + + if *git_config.semver() { + match *git_config.semver_kind() { + crate::SemverKind::Normal => { + add_semver(&repo, &DescribeOptions::new(), false, config) + } + crate::SemverKind::Lightweight => { + let mut opts = DescribeOptions::new(); + let _ = opts.describe_tags(); + + add_semver(&repo, &opts, true, config); + } + } + } + + if let Ok(resolved) = ref_head.resolve() { + if let Some(name) = resolved.name() { + *config.ref_path_mut() = Some(repo_path.join(name)); + } + } + *config.head_path_mut() = Some(repo_path.join("HEAD")); + } + } + Ok(()) +} + +#[cfg(feature = "git")] +fn add_config_entries(config: &mut Config, git_config: Git, now: &DateTime) +where + T: TimeZone, + T::Offset: std::fmt::Display, +{ + match git_config.commit_timestamp_kind() { + TimestampKind::DateOnly => add_date_entry(config, now), + TimestampKind::TimeOnly => add_time_entry(config, now), + TimestampKind::DateAndTime => { + add_date_entry(config, now); + add_time_entry(config, now); + } + TimestampKind::Timestamp => add_timestamp_entry(config, now), + TimestampKind::All => { + add_date_entry(config, now); + add_time_entry(config, now); + add_timestamp_entry(config, now); + } + } +} + +#[cfg(feature = "git")] +fn add_date_entry(config: &mut Config, now: &DateTime) +where + T: TimeZone, + T::Offset: std::fmt::Display, +{ + add_entry( + config.cfg_map_mut(), + VergenKey::CommitDate, + Some(now.format("%Y-%m-%d").to_string()), + ); +} + +#[cfg(feature = "git")] +fn add_time_entry(config: &mut Config, now: &DateTime) +where + T: TimeZone, + T::Offset: std::fmt::Display, +{ + add_entry( + config.cfg_map_mut(), + VergenKey::CommitTime, + Some(now.format("%H:%M:%S").to_string()), + ); +} + +#[cfg(feature = "git")] +fn add_timestamp_entry(config: &mut Config, now: &DateTime) +where + T: TimeZone, + T::Offset: std::fmt::Display, +{ + add_entry( + config.cfg_map_mut(), + VergenKey::CommitTimestamp, + Some(now.to_rfc3339()), + ); +} + #[cfg(feature = "git")] fn add_branch_name(repo: &Repository, config: &mut Config) -> Result<()> { if repo.head_detached()? { @@ -154,11 +453,12 @@ fn add_semver(repo: &Repository, opts: &DescribeOptions, lw: bool, config: &mut #[cfg(all(test, feature = "git"))] mod test { - use super::add_git_config; + use super::{add_git_config, SemverKind, ShaKind}; use crate::{ - config::{Config, VergenKey}, + config::{Config, Instructions, VergenKey}, constants::ConstantsFlags, error::Result, + feature::{TimeZone, TimestampKind}, test::get_map_value, }; use lazy_static::lazy_static; @@ -245,6 +545,22 @@ mod test { assert!(get_map_value(VergenKey::BuildDate, config.cfg_map()).is_empty()); Ok(()) } + + #[test] + fn git_config() { + let mut config = Instructions::default(); + assert!(config.git().branch); + assert!(config.git().commit_timestamp); + assert_eq!(config.git().commit_timestamp_timezone, TimeZone::Utc); + assert_eq!(config.git().commit_timestamp_kind, TimestampKind::Timestamp); + assert!(config.git().rerun_on_head_change); + assert!(config.git().semver); + assert_eq!(config.git().semver_kind, SemverKind::Normal); + assert!(config.git().sha); + assert_eq!(config.git().sha_kind, ShaKind::Normal); + config.git_mut().commit_timestamp_kind = TimestampKind::All; + assert_eq!(config.git().commit_timestamp_kind, TimestampKind::All); + } } #[cfg(all(test, not(feature = "git")))] diff --git a/src/feature/mod.rs b/src/feature/mod.rs index 9c185c19..605cb9b0 100644 --- a/src/feature/mod.rs +++ b/src/feature/mod.rs @@ -21,10 +21,18 @@ mod cargo; mod git; mod rustc; -pub(crate) use build::add_build_config; -pub(crate) use cargo::add_cargo_config; -pub(crate) use git::add_git_config; -pub(crate) use rustc::add_rustc_config; +#[cfg(feature = "build")] +pub use build::Build; +pub(crate) use build::{add_build_config, configure_build}; +#[cfg(feature = "cargo")] +pub use cargo::Cargo; +pub(crate) use cargo::{add_cargo_config, configure_cargo}; +pub(crate) use git::{add_git_config, configure_git}; +#[cfg(feature = "git")] +pub use git::{Git, SemverKind, ShaKind}; +#[cfg(feature = "rustc")] +pub use rustc::Rustc; +pub(crate) use rustc::{add_rustc_config, configure_rustc}; #[cfg(any( feature = "build", @@ -40,6 +48,32 @@ pub(crate) fn add_entry( *map.entry(key).or_insert_with(Option::default) = value; } +/// The timezone kind to use with date information +#[cfg(any(feature = "git", feature = "build"))] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum TimeZone { + /// UTC + Utc, + /// Local + Local, +} + +/// The timestamp kind to output +#[cfg(any(feature = "git", feature = "build"))] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum TimestampKind { + /// Output the date only + DateOnly, + /// Output the time only + TimeOnly, + /// Output the date and time only + DateAndTime, + /// Output the timestamp only + Timestamp, + /// Output all formats + All, +} + #[cfg(all( test, any( diff --git a/src/feature/rustc.rs b/src/feature/rustc.rs index 544431ad..11e7802e 100644 --- a/src/feature/rustc.rs +++ b/src/feature/rustc.rs @@ -8,13 +8,100 @@ //! `vergen` rustc feature implementation -use crate::{config::Config, constants::ConstantsFlags, error::Result}; +use crate::{ + config::{Config, Instructions}, + constants::ConstantsFlags, + error::Result, +}; #[cfg(feature = "rustc")] use { crate::{config::VergenKey, feature::add_entry}, + getset::{Getters, MutGetters}, rustc_version::{version_meta, Channel}, }; +/// Configuration for the `VERGEN_RUSTC_*` instructions +/// +/// # Instructions +/// The following instructions can be generated: +/// +/// | Instruction | Default | +/// | ----------- | :-----: | +/// | `cargo:rustc-env=VERGEN_RUSTC_CHANNEL=nightly` | * | +/// | `cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=2021-02-10` | * | +/// | `cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=07194ffcd25b0871ce560b9f702e52db27ac9f77` | * | +/// | `cargo:rustc-env=VERGEN_RUSTC_HOST_TRIPLE=x86_64-apple-darwin` | * | +/// | `cargo:rustc-env=VERGEN_RUSTC_LLVM_VERSION=11.0` | * | +/// | `cargo:rustc-env=VERGEN_RUSTC_SEMVER=1.52.0-nightly` | * | +/// +/// * If the `channel` field is false, the `VERGEN_RUSTC_CHANNEL` instruction will not be generated. +/// * If the `commit_date` field is false, the `VERGEN_RUSTC_COMMIT_DATE` instruction will not be generated. +/// * If the `host_triple` field is false, the `VERGEN_RUSTC_HOST_TRIPLE` instruction will not be generated. +/// * If the `llvm_version` field is false, the `VERGEN_RUSTC_LLVM_VERSION` instruction will not be generated. +/// * If the `semver` field is false, the `VERGEN_RUSTC_SEMVER` instruction will not be generated. +/// * If the `sha` field is false, the `VERGEN_RUSTC_COMMIT_HASH` instruction will not be generated. +/// * **NOTE** - The `commit_date` filed is only a date, as we are restricted to the output from `rustc_version` +/// * **NOTE** - The `VERGEN_RUSTC_LLVM_VERSION` instruction will only be generated on the `nightly` channel, regardless of the `llvm_version` field. +/// +/// # Example +/// +/// ``` +/// # use vergen::Error; +/// use vergen::{vergen, Config}; +/// +/// # pub fn main() -> Result<(), Error> { +/// let mut config = Config::default(); +#[cfg_attr( + feature = "rustc", + doc = r##" +// Turn off the LLVM instruction +*config.rustc_mut().llvm_version_mut() = false; + +// Generate the instructions +vergen(config)?; +"## +)] +/// # Ok(()) +/// # } +#[cfg(feature = "rustc")] +#[derive(Clone, Copy, Debug, Getters, MutGetters)] +#[getset(get = "pub(crate)", get_mut = "pub")] +pub struct Rustc { + /// Enable/Disable the `VERGEN_RUSTC_CHANNEL` instruction + channel: bool, + /// Enable/Disable the `VERGEN_RUSTC_COMMIT_DATE` instruction + commit_date: bool, + /// Enable/Disable the `VERGEN_RUSTC_HOST_TRIPLE` instruction + host_triple: bool, + /// Enable/Disable the `VERGEN_RUSTC_LLVM_VERSION` instruction + llvm_version: bool, + /// Enable/Disable the `VERGEN_RUSTC_SEMVER` instruction + semver: bool, + /// Enable/Disable the `VERGEN_RUSTC_COMMIT_HASH` instruction + sha: bool, +} + +#[cfg(feature = "rustc")] +impl Default for Rustc { + fn default() -> Self { + Self { + channel: true, + commit_date: true, + host_triple: true, + llvm_version: true, + semver: true, + sha: true, + } + } +} + +#[cfg(feature = "rustc")] +impl Rustc { + pub(crate) fn has_enabled(self) -> bool { + self.channel || self.commit_date || self.host_triple || self.llvm_version || self.sha + } +} + #[cfg(feature = "rustc")] pub(crate) fn add_rustc_config(flags: ConstantsFlags, config: &mut Config) -> Result<()> { if flags.intersects( @@ -93,11 +180,83 @@ pub(crate) fn add_rustc_config(_flags: ConstantsFlags, _config: &mut Config) -> Ok(()) } +#[cfg(feature = "rustc")] +pub(crate) fn configure_rustc(instructions: Instructions, config: &mut Config) -> Result<()> { + let rustc_config = instructions.rustc(); + if rustc_config.has_enabled() { + let rustc = version_meta()?; + + if *rustc_config.channel() { + add_entry( + config.cfg_map_mut(), + VergenKey::RustcChannel, + Some( + match rustc.channel { + Channel::Dev => "dev", + Channel::Nightly => "nightly", + Channel::Beta => "beta", + Channel::Stable => "stable", + } + .to_string(), + ), + ); + } + + if *rustc_config.host_triple() { + add_entry( + config.cfg_map_mut(), + VergenKey::RustcHostTriple, + Some(rustc.host), + ); + } + + if *rustc_config.semver() { + add_entry( + config.cfg_map_mut(), + VergenKey::RustcSemver, + Some(format!("{}", rustc.semver)), + ); + } + + if *rustc_config.sha() { + add_entry( + config.cfg_map_mut(), + VergenKey::RustcCommitHash, + rustc.commit_hash, + ); + } + + if *rustc_config.commit_date() { + add_entry( + config.cfg_map_mut(), + VergenKey::RustcCommitDate, + rustc.commit_date, + ); + } + + if *rustc_config.llvm_version() { + if let Some(llvmver) = rustc.llvm_version { + add_entry( + config.cfg_map_mut(), + VergenKey::RustcLlvmVersion, + Some(format!("{}", llvmver)), + ); + } + } + } + Ok(()) +} + +#[cfg(not(feature = "rustc"))] +pub(crate) fn configure_rustc(_instructions: Instructions, _config: &mut Config) -> Result<()> { + Ok(()) +} + #[cfg(all(test, feature = "rustc"))] mod test { use super::add_rustc_config; use crate::{ - config::{Config, VergenKey}, + config::{Config, Instructions, VergenKey}, constants::ConstantsFlags, error::Result, test::get_map_value, @@ -165,6 +324,18 @@ mod test { check_rustc_instructions(config.cfg_map()); Ok(()) } + + #[test] + fn rustc_config() { + let mut config = Instructions::default(); + assert!(config.rustc().channel); + assert!(config.rustc().commit_date); + assert!(config.rustc().host_triple); + assert!(config.rustc().llvm_version); + assert!(config.rustc().sha); + config.rustc_mut().host_triple = false; + assert!(!config.rustc().host_triple); + } } #[cfg(all(test, not(feature = "rustc")))] diff --git a/src/gen.rs b/src/gen.rs index bee9ae07..68b655ba 100644 --- a/src/gen.rs +++ b/src/gen.rs @@ -9,7 +9,7 @@ //! `vergen` cargo instruction generation use crate::{ - config::{Config, VergenKey}, + config::{Config, Instructions, VergenKey}, constants::ConstantsFlags, error::Result, }; @@ -22,13 +22,49 @@ use std::{ /// /// # Errors /// -/// Any generated errors will be wrapped in [vergen::Error](crate::error::Error) +/// Any generated errors will be wrapped in [`vergen::Error`](crate::error::Error) +/// +/// # Usage /// +/// ``` +/// # use vergen::{ConstantsFlags, Error, gen}; +/// # +/// # fn main() -> std::result::Result<(), Error> { +/// // Generate the default 'cargo:' instruction output +/// gen(ConstantsFlags::all())?; +/// # Ok(()) +/// # } +/// ``` #[cfg(not(feature = "git"))] +#[deprecated(since = "4.2.0", note = "Please use the `vergen` function instead")] pub fn gen(flags: ConstantsFlags) -> Result<()> { // This is here to help with type inference let no_repo: Option<&'static str> = None; - gen_cargo_instructions(flags, no_repo, &mut io::stdout(), &mut io::stderr()) + config_from_flags(flags, no_repo, &mut io::stdout()) +} + +/// Generate the `cargo:` instructions +/// +/// # Errors +/// +/// Any generated errors will be wrapped in [`vergen::Error`](crate::error::Error) +/// +/// # Usage +/// +/// ``` +/// # use vergen::{Config, Error, vergen}; +/// # +/// # fn main() -> std::result::Result<(), Error> { +/// // Generate the default 'cargo:' instruction output +/// vergen(Config::default())?; +/// # Ok(()) +/// # } +/// ``` +#[cfg(not(feature = "git"))] +pub fn vergen(config: crate::Config) -> Result<()> { + // This is here to help with type inference + let no_repo: Option<&'static str> = None; + config_from_instructions(config, no_repo, &mut io::stdout()) } /// Generate the `cargo:` instructions @@ -40,47 +76,79 @@ pub fn gen(flags: ConstantsFlags) -> Result<()> { /// # Usage /// /// ``` -/// # use vergen::{ConstantsFlags, gen}; +/// # use vergen::{ConstantsFlags, Error, gen}; /// # -/// # fn main() { -/// // Generate the 'cargo:' instruction output -/// gen(ConstantsFlags::all()).expect("Unable to generate the cargo keys!"); +/// # fn main() -> std::result::Result<(), Error> { +/// // Generate the default 'cargo:' instruction output +/// gen(ConstantsFlags::all())?; +/// # Ok(()) /// # } /// ``` #[cfg(feature = "git")] +#[deprecated(since = "4.2.0", note = "Please use the `vergen` function instead")] pub fn gen(flags: ConstantsFlags) -> Result<()> { - gen_cargo_instructions(flags, Some("."), &mut io::stdout(), &mut io::stderr()) + config_from_flags(flags, Some("."), &mut io::stdout()) +} + +/// Generate the `cargo:` instructions +/// +/// # Errors +/// +/// Any generated errors will be wrapped in [`vergen::Error`](crate::error::Error) +/// +/// # Usage +/// +/// ``` +/// # use vergen::{Config, Error, vergen}; +/// # +/// # fn main() -> std::result::Result<(), Error> { +/// // Generate the default 'cargo:' instruction output +/// vergen(Config::default())?; +/// # Ok(()) +/// # } +/// ``` +#[cfg(feature = "git")] +pub fn vergen(config: crate::Config) -> Result<()> { + config_from_instructions(config, Some("."), &mut io::stdout()) } -fn gen_cargo_instructions( - flags: ConstantsFlags, - repo: Option, +fn config_from_flags(flags: ConstantsFlags, repo: Option, stdout: &mut T) -> Result<()> +where + T: Write, + U: AsRef, +{ + output_cargo_instructions(&Config::build(flags, repo)?, stdout) +} + +fn config_from_instructions( + instructions: Instructions, + repo: Option, stdout: &mut T, - _stderr: &mut U, ) -> Result<()> where T: Write, - U: Write, - V: AsRef, + U: AsRef, { - // Generate the config to drive 'cargo:' instruction output - let config = Config::build(flags, repo)?; + output_cargo_instructions(&instructions.config(repo)?, stdout) +} +fn output_cargo_instructions(config: &Config, stdout: &mut T) -> Result<()> +where + T: Write, +{ // Generate the 'cargo:' instruction output for (k, v) in config.cfg_map().iter().filter_map(some_vals) { writeln!(stdout, "cargo:rustc-env={}={}", k.name(), v)?; } - if flags.contains(ConstantsFlags::REBUILD_ON_HEAD_CHANGE) { - // Add the HEAD path to cargo:rerun-if-changed - if let Some(head_path) = config.head_path() { - writeln!(stdout, "cargo:rerun-if-changed={}", head_path.display())?; - } + // Add the HEAD path to cargo:rerun-if-changed + if let Some(head_path) = config.head_path() { + writeln!(stdout, "cargo:rerun-if-changed={}", head_path.display())?; + } - // Add the resolved ref path to cargo:rerun-if-changed - if let Some(ref_path) = config.ref_path() { - writeln!(stdout, "cargo:rerun-if-changed={}", ref_path.display())?; - } + // Add the resolved ref path to cargo:rerun-if-changed + if let Some(ref_path) = config.ref_path() { + writeln!(stdout, "cargo:rerun-if-changed={}", ref_path.display())?; } Ok(()) @@ -96,8 +164,11 @@ fn some_vals<'a>(tuple: (&'a VergenKey, &'a Option)) -> Option<(&VergenK #[cfg(test)] mod test { - use super::{gen, gen_cargo_instructions}; + #[allow(deprecated)] + use super::gen; + use super::{config_from_flags, vergen}; use crate::{ + config::Instructions, constants::ConstantsFlags, error::Result, testutils::{setup, teardown}, @@ -219,6 +290,7 @@ mod test { #[test] #[serial_test::serial] + #[allow(deprecated)] fn gen_works() -> Result<()> { setup(); assert!(gen(ConstantsFlags::all()).is_ok()); @@ -226,42 +298,37 @@ mod test { Ok(()) } + #[test] + #[serial_test::serial] + fn vergen_works() -> Result<()> { + setup(); + assert!(vergen(Instructions::default()).is_ok()); + teardown(); + Ok(()) + } + #[test] fn describe_falls_back() -> Result<()> { let no_tags_path = PathBuf::from("testdata").join("notagsrepo"); - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(no_tags_path), - &mut io::sink(), - &mut io::sink(), - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(no_tags_path), &mut io::sink(),).is_ok() + ); Ok(()) } #[test] fn describe() -> Result<()> { let no_tags_path = PathBuf::from("testdata").join("tagsrepo"); - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(no_tags_path), - &mut io::sink(), - &mut io::sink(), - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(no_tags_path), &mut io::sink(),).is_ok() + ); Ok(()) } #[test] fn detached_head() -> Result<()> { let dh_path = PathBuf::from("testdata").join("detachedhead"); - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(dh_path), - &mut io::sink(), - &mut io::sink(), - ) - .is_ok()); + assert!(config_from_flags(ConstantsFlags::all(), Some(dh_path), &mut io::sink(),).is_ok()); Ok(()) } @@ -273,10 +340,7 @@ mod test { flags.toggle(ConstantsFlags::BUILD_DATE); let mut stdout_buf = vec![]; - let mut stderr = vec![]; - assert!( - gen_cargo_instructions(flags, Some(repo_path), &mut stdout_buf, &mut stderr).is_ok() - ); + assert!(config_from_flags(flags, Some(repo_path), &mut stdout_buf).is_ok()); let stdout = String::from_utf8_lossy(&stdout_buf); assert!(!VBD_REGEX.is_match(&stdout)); Ok(()) @@ -292,16 +356,10 @@ mod test { fn no_features_no_output() { let repo_path = PathBuf::from("."); let mut stdout_buf = vec![]; - let mut stderr_buf = vec![]; - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(repo_path), - &mut stdout_buf, - &mut stderr_buf - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(repo_path), &mut stdout_buf,).is_ok() + ); assert!(stdout_buf.is_empty()); - assert!(stderr_buf.is_empty()); } #[cfg(all(feature = "build", not(feature = "git")))] @@ -309,16 +367,10 @@ mod test { fn contains_only_build_output() { let repo_path = PathBuf::from("."); let mut stdout_buf = vec![]; - let mut stderr_buf = vec![]; - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(repo_path), - &mut stdout_buf, - &mut stderr_buf - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(repo_path), &mut stdout_buf,).is_ok() + ); assert!(BUILD_CARGO_REGEX.is_match(&String::from_utf8_lossy(&stdout_buf))); - assert!(stderr_buf.is_empty()); } #[cfg(all(feature = "build", feature = "git"))] @@ -326,16 +378,10 @@ mod test { fn contains_build_output() { let repo_path = PathBuf::from("."); let mut stdout_buf = vec![]; - let mut stderr_buf = vec![]; - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(repo_path), - &mut stdout_buf, - &mut stderr_buf - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(repo_path), &mut stdout_buf,).is_ok() + ); assert!(BUILD_REGEX.is_match(&String::from_utf8_lossy(&stdout_buf))); - assert!(stderr_buf.is_empty()); } #[cfg(feature = "cargo")] @@ -345,16 +391,10 @@ mod test { setup(); let repo_path = PathBuf::from("."); let mut stdout_buf = vec![]; - let mut stderr_buf = vec![]; - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(repo_path), - &mut stdout_buf, - &mut stderr_buf - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(repo_path), &mut stdout_buf,).is_ok() + ); assert!(CARGO_REGEX.is_match(&String::from_utf8_lossy(&stdout_buf))); - assert!(stderr_buf.is_empty()); teardown(); } @@ -363,17 +403,11 @@ mod test { fn contains_git_output() { let repo_path = PathBuf::from("."); let mut stdout_buf = vec![]; - let mut stderr_buf = vec![]; - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(repo_path), - &mut stdout_buf, - &mut stderr_buf - ) - .is_ok()); + assert!( + config_from_flags(ConstantsFlags::all(), Some(repo_path), &mut stdout_buf,).is_ok() + ); assert!(GIT_REGEX.is_match(&String::from_utf8_lossy(&stdout_buf))); assert!(GIT_RIC_REGEX.is_match(&String::from_utf8_lossy(&stdout_buf))); - assert!(stderr_buf.is_empty()); } #[cfg(feature = "rustc")] @@ -381,37 +415,185 @@ mod test { fn contains_rustc_output() { let repo_path = PathBuf::from("."); let mut stdout_buf = vec![]; - let mut stderr_buf = vec![]; - assert!(gen_cargo_instructions( - ConstantsFlags::all(), - Some(repo_path), - &mut stdout_buf, - &mut stderr_buf - ) - .is_ok()); - check_rustc_output(&stdout_buf, &stderr_buf); + assert!( + config_from_flags(ConstantsFlags::all(), Some(repo_path), &mut stdout_buf,).is_ok() + ); + check_rustc_output(&stdout_buf); } #[cfg(feature = "rustc")] #[rustversion::nightly] - fn check_rustc_output(stdout: &[u8], stderr: &[u8]) { + fn check_rustc_output(stdout: &[u8]) { assert!(RUSTC_NIGHTLY_REGEX.is_match(&String::from_utf8_lossy(&stdout))); - assert!(stderr.is_empty()); } // TODO: Check this on new beta releases, the regex was causing a panic // outside of my control #[cfg(feature = "rustc")] #[rustversion::beta] - fn check_rustc_output(stdout: &[u8], stderr: &[u8]) { + fn check_rustc_output(stdout: &[u8]) { assert!(!stdout.is_empty()); - assert!(stderr.is_empty()); } #[cfg(feature = "rustc")] #[rustversion::stable] - fn check_rustc_output(stdout: &[u8], stderr: &[u8]) { + fn check_rustc_output(stdout: &[u8]) { assert!(RUSTC_REGEX.is_match(&String::from_utf8_lossy(&stdout))); - assert!(stderr.is_empty()); + } + + #[cfg(feature = "build")] + #[test] + fn build_local_timezone() { + use super::config_from_instructions; + use crate::TimeZone; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.build_mut().timezone_mut() = TimeZone::Local; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn git_local_timezone() { + use super::config_from_instructions; + use crate::TimeZone; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().commit_timestamp_timezone_mut() = TimeZone::Local; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "build")] + #[test] + fn build_time_only() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.build_mut().kind_mut() = TimestampKind::TimeOnly; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn git_time_only() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().commit_timestamp_kind_mut() = TimestampKind::TimeOnly; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "build")] + #[test] + fn build_date_only() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.build_mut().kind_mut() = TimestampKind::DateOnly; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn git_date_only() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().commit_timestamp_kind_mut() = TimestampKind::DateOnly; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "build")] + #[test] + fn build_date_and_time() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.build_mut().kind_mut() = TimestampKind::DateAndTime; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn git_date_and_time() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().commit_timestamp_kind_mut() = TimestampKind::DateAndTime; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "build")] + #[test] + fn build_all_kind() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.build_mut().kind_mut() = TimestampKind::All; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn git_all_kind() { + use super::config_from_instructions; + use crate::TimestampKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().commit_timestamp_kind_mut() = TimestampKind::All; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn sha_kind() { + use super::config_from_instructions; + use crate::ShaKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().sha_kind_mut() = ShaKind::Short; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); + } + + #[cfg(feature = "git")] + #[test] + fn semver_kind() { + use super::config_from_instructions; + use crate::SemverKind; + + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + let mut config = Instructions::default(); + *config.git_mut().semver_kind_mut() = SemverKind::Lightweight; + assert!(config_from_instructions(config, Some(repo_path), &mut stdout_buf,).is_ok()); } } diff --git a/src/lib.rs b/src/lib.rs index fce1fa1a..527a9479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,21 +66,20 @@ //! **NOTE** - All four features are enabled by default. //! //! ## Sample Output -//! If all features are enabled and all flags are toggled on the build script will generate instructions for cargo similar to below. -//! Please see [`ConstantsFlags`](crate::constants::ConstantsFlags) for more details on instruction generation. +//! If all features are enabled and the default [`Config`] is used the build script will generate instructions for cargo similar to below. +//! +//! Please see [`Config`](crate::Config) for more details on instruction generation. //! //! ```text, no_run -//! cargo:rustc-env=VERGEN_BUILD_DATE=2021-02-12 -//! cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2021-02-12T01:54:15.134750+00:00 -//! cargo:rustc-env=VERGEN_GIT_BRANCH=feature/git2 -//! cargo:rustc-env=VERGEN_GIT_COMMIT_DATE=2021-02-11T20:05:53-05:00 -//! cargo:rustc-env=VERGEN_GIT_SEMVER=v3.2.0-86-g95fc0f5 -//! cargo:rustc-env=VERGEN_GIT_SEMVER_LIGHTWEIGHT=blah-33-g95fc0f5 -//! cargo:rustc-env=VERGEN_GIT_SHA=95fc0f5d066710f16e0c23ce3239d6e040abca0d -//! cargo:rustc-env=VERGEN_GIT_SHA_SHORT=95fc0f5 +//! cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=2021-02-25T23:28:39.493201+00:00 +//! cargo:rustc-env=VERGEN_BUILD_SEMVER=4.1.0 +//! cargo:rustc-env=VERGEN_GIT_BRANCH=feature/fun +//! cargo:rustc-env=VERGEN_GIT_COMMIT_TIMESTAMP=2021-02-24T20:55:21+00:00 +//! cargo:rustc-env=VERGEN_GIT_SEMVER=4.1.0-2-gf49246c +//! cargo:rustc-env=VERGEN_GIT_SHA=f49246ce334567bff9f950bfd0f3078184a2738a //! cargo:rustc-env=VERGEN_RUSTC_CHANNEL=nightly -//! cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=2021-02-10 -//! cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=07194ffcd25b0871ce560b9f702e52db27ac9f77 +//! cargo:rustc-env=VERGEN_RUSTC_COMMIT_DATE=2021-02-24 +//! cargo:rustc-env=VERGEN_RUSTC_COMMIT_HASH=a8486b64b0c87dabd045453b6c81500015d122d6 //! cargo:rustc-env=VERGEN_RUSTC_HOST_TRIPLE=x86_64-apple-darwin //! cargo:rustc-env=VERGEN_RUSTC_LLVM_VERSION=11.0 //! cargo:rustc-env=VERGEN_RUSTC_SEMVER=1.52.0-nightly @@ -88,7 +87,7 @@ //! cargo:rustc-env=VERGEN_CARGO_PROFILE=debug //! cargo:rustc-env=VERGEN_CARGO_FEATURES=git,build //! cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/HEAD -//! cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/refs/heads/feature/git2 +//! cargo:rerun-if-changed=/Users/yoda/projects/rust-lang/vergen/.git/refs/heads/feature/fun //! ``` //! //! ## Usage @@ -115,20 +114,13 @@ //! ``` //! //! ### build.rs -//! **NOTE** - Individual instruction generation can be toggled on or off via [`ConstantsFlags`](crate::constants::ConstantsFlags) +//! **NOTE** - Individual instruction generation can be toggled on or off via [`Config`](crate::Config) //! ``` -//! use vergen::{ConstantsFlags, Error, gen}; +//! use vergen::{Config, Error, vergen}; //! //! fn main() -> Result<(), Box> { -//! // Setup the flags, toggling off unused instructions -//! let mut flags = ConstantsFlags::all(); -//! flags.toggle(ConstantsFlags::SEMVER_FROM_CARGO_PKG); -//! flags.toggle(ConstantsFlags::SEMVER_LIGHTWEIGHT); -//! flags.toggle(ConstantsFlags::SHA_SHORT); -//! flags.toggle(ConstantsFlags::BUILD_DATE); -//! -//! // Generate the 'cargo:' instruction output -//! gen(flags).map_err(Error::into) +//! // Generate the default 'cargo:' instruction output +//! vergen(Config::default()).map_err(Error::into) //! } //! ``` //! @@ -138,35 +130,16 @@ //! println!("git semver: {}", env!("VERGEN_GIT_SEMVER")); //! ``` //! -//! ### Note on `VERGEN_SEMVER` and `VERGEN_SEMVER_LIGHTWEIGHT` -//! `VERGEN_SEMVER` and `VERGEN_SEMVER_LIGHTWEIGHT` can be generated via two methods -//! 1. [`git2::Repository::describe`] -//! 2. [`CARGO_PKG_VERSION`] -//! -//! By default, if the `git` feature is enabled semver generation will use the first method. -//! If the `git` feature is disabled or method one errors, generation falls back to the second method. -//! Note that the `git describe` method is only useful if you have tags on your repository. -//! I recommend [`SemVer`] tags, but this will work with any tag format. -//! If your repository has no tags, this method will always fall back to [`CARGO_PKG_VERSION`]. -//! Also worth noting, `VERGEN_SEMVER` and `VERGEN_SEMVER_LIGHTWEIGHT` will only differ if you use [lightweight] tags in your repository. -//! -//! If you wish to force method two even if the `git` feature is enabled you may toggle off [`SEMVER`] and toggle on [`SEMVER_FROM_CARGO_PKG`]. -//! -//! ### Note on `REBUILD_ON_HEAD_CHANGE` -//! `vergen` can also be configured to instruct `cargo` to re-run the build script when either `/HEAD` or the file that `/HEAD` points at changes. -//! -//! This can behavior can be toggled on or off with the [`REBUILD_ON_HEAD_CHANGE`] flag. -//! -//! [`SEMVER`]: crate::constants::ConstantsFlags::SEMVER -//! [`SEMVER_FROM_CARGO_PKG`]: crate::constants::ConstantsFlags::SEMVER_FROM_CARGO_PKG -//! [`REBUILD_ON_HEAD_CHANGE`]: crate::constants::ConstantsFlags::REBUILD_ON_HEAD_CHANGE -//! [git describe]: git2::Repository::describe -//! [`CARGO_PKG_VERSION`]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates //! [build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html //! [cargo:rustc-env]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-env //! [cargo:rerun-if-changed]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed -//! [lightweight]: https://git-scm.com/book/en/v2/Git-Basics-Tagging -//! [SemVer]: https://semver.org/ +//! +//! ## Deprecation Warning +//! The [`gen`](gen()) function and [`ConstantsFlags`](crate::ConstantsFlags) have been deprecated. They will be removed when version 5 is released. +//! +//! Please switch to using the [`vergen`](vergen()) function with [`Config`](crate::Config) instead. +//! +//! This change was made because the [`ConstantsFlags`](crate::ConstantsFlags) were growing bloated. //! #![deny( absolute_paths_not_starting_with_crate, @@ -188,7 +161,7 @@ const_item_mutation, dead_code, deprecated, - deprecated_in_future, + // deprecated_in_future, drop_bounds, elided_lifetimes_in_paths, ellipsis_inclusive_range_patterns, @@ -211,7 +184,7 @@ missing_copy_implementations, missing_crate_level_docs, missing_debug_implementations, - missing_doc_code_examples, + // missing_doc_code_examples, missing_docs, mixed_script_confusables, mutable_borrow_reservation_conflict, @@ -283,9 +256,29 @@ mod error; mod feature; mod gen; +pub use crate::config::Instructions as Config; +#[deprecated(since = "4.2.0", note = "Please use `Config` instead")] pub use crate::constants::ConstantsFlags; pub use crate::error::Error; +#[cfg(feature = "build")] +pub use crate::feature::Build; +#[cfg(feature = "cargo")] +pub use crate::feature::Cargo; +#[cfg(feature = "git")] +pub use crate::feature::Git; +#[cfg(feature = "rustc")] +pub use crate::feature::Rustc; +#[cfg(feature = "git")] +pub use crate::feature::SemverKind; +#[cfg(feature = "git")] +pub use crate::feature::ShaKind; +#[cfg(any(feature = "git", feature = "build"))] +pub use crate::feature::TimeZone; +#[cfg(any(feature = "git", feature = "build"))] +pub use crate::feature::TimestampKind; +#[allow(deprecated)] pub use crate::gen::gen; +pub use crate::gen::vergen; #[cfg(all(test, not(feature = "rustc")))] use rustversion as _;