From 022e804dcdcd4eb763e8dc0da09fa6ede223e7e0 Mon Sep 17 00:00:00 2001 From: Jason Ozias Date: Sat, 1 Jul 2023 17:17:33 -0400 Subject: [PATCH] Custom build.rs path support, local time offset support, updated gix dep (#223) * added support for specifying custom build.rs path, updated gix dep * version bump for next release * added custom build.rs test * added support for local time offset output * test using local, which fails on unix * Fixed for linux/non-linux * Added local test to git_output * fixed linux test * fixed non-linux tests --------- Co-authored-by: Jason Ozias --- vergen/Cargo.toml | 7 +-- vergen/src/emitter.rs | 81 +++++++++++++++++++++++++++++----- vergen/src/feature/build.rs | 15 ++++++- vergen/src/feature/git/cmd.rs | 18 +++++++- vergen/src/feature/git/git2.rs | 23 +++++++--- vergen/src/feature/git/gix.rs | 23 +++++++--- vergen/tests/build_output.rs | 48 ++++++++++++++++++++ vergen/tests/git_output.rs | 29 ++++++++++++ 8 files changed, 216 insertions(+), 28 deletions(-) diff --git a/vergen/Cargo.toml b/vergen/Cargo.toml index 11515eae..e8fc221c 100644 --- a/vergen/Cargo.toml +++ b/vergen/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT OR Apache-2.0" name = "vergen" readme = "README.md" repository = "https://github.com/rustyhorde/vergen" -version = "8.2.2" +version = "8.2.3" [package.metadata.cargo-all-features] denylist = [ @@ -41,11 +41,12 @@ si = ["sysinfo"] [dependencies] anyhow = "1.0.70" git2-rs = { version = "0.17.1", package = "git2", optional = true, default-features = false } -gix = { version = "0.47.0", optional = true, default-features = false } +gix = { version = "0.48.0", optional = true, default-features = false } rustc_version = { version = "0.4.0", optional = true } sysinfo = { version = "0.29.0", optional = true, default-features = false } time = { version = "0.3.20", features = [ "formatting", + "local-offset", "parsing", ], optional = true } @@ -53,7 +54,7 @@ time = { version = "0.3.20", features = [ rustversion = "1.0.12" [dev-dependencies] -gix = { version = "0.47.0", default-features = false, features = [ +gix = { version = "0.48.0", default-features = false, features = [ "blocking-network-client", ] } lazy_static = "1.4.0" diff --git a/vergen/src/emitter.rs b/vergen/src/emitter.rs index 1eb9556c..0a3642c3 100644 --- a/vergen/src/emitter.rs +++ b/vergen/src/emitter.rs @@ -11,6 +11,7 @@ use std::{ env, io::{self, Write}, }; + #[cfg(any( feature = "build", feature = "cargo", @@ -230,11 +231,16 @@ impl Emitter { )] fn add_si_entries(&mut self, _builder: &EmitBuilder) {} - fn emit_output(&self, quiet: bool, stdout: &mut T) -> Result<()> + fn emit_output( + &self, + quiet: bool, + custom_buildrs: Option<&'static str>, + stdout: &mut T, + ) -> Result<()> where T: Write, { - self.emit_instructions(quiet, stdout) + self.emit_instructions(quiet, custom_buildrs, stdout) } #[cfg(not(any( @@ -245,7 +251,12 @@ impl Emitter { feature = "si" )))] #[allow(clippy::unused_self, clippy::unnecessary_wraps)] - fn emit_instructions(&self, _quiet: bool, _stdout: &mut T) -> Result<()> + fn emit_instructions( + &self, + _quiet: bool, + _custom_buildrs: Option<&'static str>, + _stdout: &mut T, + ) -> Result<()> where T: Write, { @@ -259,7 +270,12 @@ impl Emitter { feature = "rustc", feature = "si" ))] - fn emit_instructions(&self, quiet: bool, stdout: &mut T) -> Result<()> + fn emit_instructions( + &self, + quiet: bool, + custom_buildrs: Option<&'static str>, + stdout: &mut T, + ) -> Result<()> where T: Write, { @@ -282,7 +298,12 @@ impl Emitter { // Emit the 'cargo:rerun-if-changed' instructions if !self.cargo_rustc_env_map.is_empty() || !self.warnings.is_empty() { - writeln!(stdout, "cargo:rerun-if-changed=build.rs")?; + let buildrs = if let Some(path) = custom_buildrs { + path + } else { + "build.rs" + }; + writeln!(stdout, "cargo:rerun-if-changed={buildrs}")?; writeln!(stdout, "cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT")?; writeln!(stdout, "cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH")?; } @@ -298,6 +319,7 @@ pub struct EmitBuilder { idempotent: bool, fail_on_error: bool, quiet: bool, + custom_buildrs: Option<&'static str>, #[cfg(feature = "build")] disable_build: bool, #[cfg(feature = "build")] @@ -335,6 +357,7 @@ impl EmitBuilder { idempotent, fail_on_error: false, quiet: false, + custom_buildrs: None, #[cfg(feature = "build")] disable_build: false, #[cfg(feature = "build")] @@ -449,6 +472,33 @@ EmitBuilder::builder().fail_on_error().all_build().emit()?; self } + /// Set a custom build.rs path if you are using a non-standard path + /// + /// By default `vergen` will use `build.rs` as the build path for the + /// `cargo:rerun-if-changed` emit. You can specify a custom `build.rs` + /// path here if you have changed this default + /// + /// # Example + /// + /// ``` + /// # use anyhow::Result; + /// # use vergen::EmitBuilder; + /// # + /// # fn main() -> Result<()> { + #[cfg_attr( + feature = "build", + doc = r##" +EmitBuilder::builder().custom_build_rs("my/custom/build.rs").all_build().emit()?; +"## + )] + /// # Ok(()) + /// # } + /// ``` + pub fn custom_build_rs(&mut self, path: &'static str) -> &mut Self { + self.custom_buildrs = Some(path); + self + } + /// Enable the quiet feature /// /// Suppress the emission of the `cargo:warning` instructions. @@ -698,7 +748,7 @@ EmitBuilder::builder() /// pub fn emit(self) -> Result<()> { self.inner_emit(None) - .and_then(|x| x.emit_output(self.quiet, &mut io::stdout())) + .and_then(|x| x.emit_output(self.quiet, self.custom_buildrs, &mut io::stdout())) } /// Emit cargo instructions from your build script and set environment variables for use in `build.rs` @@ -765,7 +815,10 @@ EmitBuilder::builder() ))] pub fn emit_and_set(self) -> Result<()> { self.inner_emit(None) - .and_then(|x| x.emit_output(self.quiet, &mut io::stdout()).map(|_| x)) + .and_then(|x| { + x.emit_output(self.quiet, self.custom_buildrs, &mut io::stdout()) + .map(|_| x) + }) .map(|x| { for (k, v) in &x.cargo_rustc_env_map { if env::var(k.name()).is_err() { @@ -786,7 +839,7 @@ EmitBuilder::builder() ))] pub fn emit_at(self, repo_path: PathBuf) -> Result<()> { self.inner_emit(Some(repo_path)) - .and_then(|x| x.emit_output(self.quiet, &mut io::stdout())) + .and_then(|x| x.emit_output(self.quiet, self.custom_buildrs, &mut io::stdout())) } #[cfg(all( @@ -830,8 +883,10 @@ EmitBuilder::builder() where T: Write, { - self.inner_emit(None) - .and_then(|x| x.emit_output(self.quiet, stdout).map(|_| x.failed)) + self.inner_emit(None).and_then(|x| { + x.emit_output(self.quiet, self.custom_buildrs, stdout) + .map(|_| x.failed) + }) } #[doc(hidden)] @@ -848,8 +903,10 @@ EmitBuilder::builder() where T: Write, { - self.inner_emit(path) - .and_then(|x| x.emit_output(self.quiet, stdout).map(|_| x.failed)) + self.inner_emit(path).and_then(|x| { + x.emit_output(self.quiet, self.custom_buildrs, stdout) + .map(|_| x.failed) + }) } fn inner_emit(self, path: Option) -> Result { diff --git a/vergen/src/feature/build.rs b/vergen/src/feature/build.rs index 9d7f274b..ce97328d 100644 --- a/vergen/src/feature/build.rs +++ b/vergen/src/feature/build.rs @@ -15,6 +15,7 @@ use time::{ pub(crate) struct Config { pub(crate) build_date: bool, pub(crate) build_timestamp: bool, + use_local: bool, } impl Config { @@ -155,6 +156,12 @@ impl EmitBuilder { self } + /// Enable local offset date/timestamp output + pub fn use_local_build(&mut self) -> &mut Self { + self.build_config.use_local = true; + self + } + pub(crate) fn add_build_default( &self, e: Error, @@ -198,7 +205,13 @@ impl EmitBuilder { true, OffsetDateTime::from_unix_timestamp(i64::from_str(&v)?)?, ), - Err(std::env::VarError::NotPresent) => (false, OffsetDateTime::now_utc()), + Err(std::env::VarError::NotPresent) => { + if self.build_config.use_local { + (false, OffsetDateTime::now_local()?) + } else { + (false, OffsetDateTime::now_utc()) + } + } Err(e) => return Err(e.into()), }; diff --git a/vergen/src/feature/git/cmd.rs b/vergen/src/feature/git/cmd.rs index 05a4e7de..75d78e6e 100644 --- a/vergen/src/feature/git/cmd.rs +++ b/vergen/src/feature/git/cmd.rs @@ -28,7 +28,7 @@ use time::{ self, well_known::{Iso8601, Rfc3339}, }, - OffsetDateTime, + OffsetDateTime, UtcOffset, }; #[derive(Clone, Copy, Debug, Default)] @@ -57,6 +57,7 @@ pub(crate) struct Config { pub(crate) git_sha: bool, git_sha_short: bool, git_cmd: Option<&'static str>, + use_local: bool, } // This funkiness allows the command to be output in the docs @@ -440,6 +441,12 @@ impl EmitBuilder { self } + /// Enable local offset date/timestamp output + pub fn use_local_git(&mut self) -> &mut Self { + self.git_config.use_local = true; + self + } + pub(crate) fn add_git_default( &self, e: Error, @@ -638,7 +645,14 @@ impl EmitBuilder { OffsetDateTime::from_unix_timestamp(i64::from_str(&v)?)?, ), Err(std::env::VarError::NotPresent) => { - (false, OffsetDateTime::parse(&stdout, &Rfc3339)?) + let no_offset = OffsetDateTime::parse(&stdout, &Rfc3339)?; + if self.git_config.use_local { + let local = UtcOffset::local_offset_at(no_offset)?; + let local_offset = no_offset.checked_to_offset(local).unwrap_or(no_offset); + (false, local_offset) + } else { + (false, no_offset) + } } Err(e) => return Err(e.into()), }; diff --git a/vergen/src/feature/git/git2.rs b/vergen/src/feature/git/git2.rs index d96fedbc..adddfc8c 100644 --- a/vergen/src/feature/git/git2.rs +++ b/vergen/src/feature/git/git2.rs @@ -27,7 +27,7 @@ use std::{ }; use time::{ format_description::{self, well_known::Iso8601}, - OffsetDateTime, + OffsetDateTime, UtcOffset, }; #[derive(Clone, Copy, Debug, Default)] @@ -55,6 +55,7 @@ pub(crate) struct Config { // git rev-parse HEAD (optionally with --short) pub(crate) git_sha: bool, git_sha_short: bool, + use_local: bool, #[cfg(test)] fail: bool, } @@ -243,6 +244,12 @@ impl EmitBuilder { self } + /// Enable local offset date/timestamp output + pub fn use_local_git(&mut self) -> &mut Self { + self.git_config.use_local = true; + self + } + pub(crate) fn add_git_default( &self, e: Error, @@ -452,10 +459,16 @@ impl EmitBuilder { true, OffsetDateTime::from_unix_timestamp(i64::from_str(&v)?)?, ), - Err(std::env::VarError::NotPresent) => ( - false, - OffsetDateTime::from_unix_timestamp(commit.time().seconds())?, - ), + Err(std::env::VarError::NotPresent) => { + let no_offset = OffsetDateTime::from_unix_timestamp(commit.time().seconds())?; + if self.git_config.use_local { + let local = UtcOffset::local_offset_at(no_offset)?; + let local_offset = no_offset.checked_to_offset(local).unwrap_or(no_offset); + (false, local_offset) + } else { + (false, no_offset) + } + } Err(e) => return Err(e.into()), }; diff --git a/vergen/src/feature/git/gix.rs b/vergen/src/feature/git/gix.rs index 9ba6117e..02d40ac1 100644 --- a/vergen/src/feature/git/gix.rs +++ b/vergen/src/feature/git/gix.rs @@ -27,7 +27,7 @@ use std::{ }; use time::{ format_description::{self, well_known::Iso8601}, - OffsetDateTime, + OffsetDateTime, UtcOffset, }; #[derive(Clone, Copy, Debug, Default)] @@ -54,6 +54,7 @@ pub(crate) struct Config { // git rev-parse HEAD (optionally with --short) pub(crate) git_sha: bool, git_sha_short: bool, + use_local: bool, #[cfg(test)] fail: bool, } @@ -289,6 +290,12 @@ impl EmitBuilder { } } + /// Enable local offset date/timestamp output + pub fn use_local_git(&mut self) -> &mut Self { + self.git_config.use_local = true; + self + } + #[cfg(not(test))] pub(crate) fn add_git_map_entries( &self, @@ -452,10 +459,16 @@ impl EmitBuilder { true, OffsetDateTime::from_unix_timestamp(i64::from_str(&v)?)?, ), - Err(std::env::VarError::NotPresent) => ( - false, - OffsetDateTime::from_unix_timestamp(commit.time()?.seconds.try_into()?)?, - ), + Err(std::env::VarError::NotPresent) => { + let no_offset = OffsetDateTime::from_unix_timestamp(commit.time()?.seconds)?; + if self.git_config.use_local { + let local = UtcOffset::local_offset_at(no_offset)?; + let local_offset = no_offset.checked_to_offset(local).unwrap_or(no_offset); + (false, local_offset) + } else { + (false, no_offset) + } + } Err(e) => return Err(e.into()), }; diff --git a/vergen/tests/build_output.rs b/vergen/tests/build_output.rs index 23540a48..ebbb56a9 100644 --- a/vergen/tests/build_output.rs +++ b/vergen/tests/build_output.rs @@ -30,6 +30,15 @@ cargo:warning=VERGEN_BUILD_TIMESTAMP set to default cargo:rerun-if-changed=build.rs cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH +"#; + + const IDEM_OUTPUT_CUSTOM_BUILDRS: &str = r#"cargo:rustc-env=VERGEN_BUILD_DATE=VERGEN_IDEMPOTENT_OUTPUT +cargo:rustc-env=VERGEN_BUILD_TIMESTAMP=VERGEN_IDEMPOTENT_OUTPUT +cargo:warning=VERGEN_BUILD_DATE set to default +cargo:warning=VERGEN_BUILD_TIMESTAMP set to default +cargo:rerun-if-changed=a/custom_build.rs +cargo:rerun-if-env-changed=VERGEN_IDEMPOTENT +cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH "#; const DISABLED_OUTPUT: &str = r#""#; @@ -60,6 +69,31 @@ cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH Ok(()) } + #[test] + #[serial_test::serial] + fn build_all_output_local() -> Result<()> { + let mut stdout_buf = vec![]; + let result = EmitBuilder::builder() + .all_build() + .use_local_build() + .fail_on_error() + .emit_to(&mut stdout_buf); + check_local_result(result, &stdout_buf); + Ok(()) + } + + #[cfg(not(target_os = "linux"))] + fn check_local_result(result: Result, stdout_buf: &[u8]) { + assert!(result.is_ok()); + let output = String::from_utf8_lossy(stdout_buf); + assert!(BUILD_REGEX_INST.is_match(&output)); + } + + #[cfg(target_os = "linux")] + fn check_local_result(result: Result, _stdout_buf: &[u8]) { + assert!(result.is_err()); + } + #[test] #[serial_test::serial] fn build_disabled_output() -> Result<()> { @@ -86,6 +120,20 @@ cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH Ok(()) } + #[test] + #[serial_test::serial] + fn build_all_idempotent_custom_buildrs_output() -> Result<()> { + let mut stdout_buf = vec![]; + EmitBuilder::builder() + .idempotent() + .custom_build_rs("a/custom_build.rs") + .all_build() + .emit_to(&mut stdout_buf)?; + let output = String::from_utf8_lossy(&stdout_buf); + assert_eq!(IDEM_OUTPUT_CUSTOM_BUILDRS, output); + Ok(()) + } + #[test] #[serial_test::serial] fn build_all_idempotent_output_quiet() -> Result<()> { diff --git a/vergen/tests/git_output.rs b/vergen/tests/git_output.rs index 43e1f6bb..1e541fba 100644 --- a/vergen/tests/git_output.rs +++ b/vergen/tests/git_output.rs @@ -361,6 +361,35 @@ cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH Ok(()) } + #[test] + #[serial_test::serial] + fn git_all_flags_test_repo_local() -> Result<()> { + create_test_repo(); + clone_test_repo(); + let mut stdout_buf = vec![]; + let result = EmitBuilder::builder() + .all_git() + .git_describe(true, true, Some("0.1*")) + .git_sha(true) + .use_local_git() + .fail_on_error() + .emit_to_at(&mut stdout_buf, Some(clone_path())); + check_local_result(result, &stdout_buf); + Ok(()) + } + + #[cfg(not(target_os = "linux"))] + fn check_local_result(result: Result, stdout_buf: &[u8]) { + assert!(result.is_ok()); + let output = String::from_utf8_lossy(stdout_buf); + assert!(GIT_REGEX_SHORT_INST.is_match(&output)); + } + + #[cfg(target_os = "linux")] + fn check_local_result(result: Result, _stdout_buf: &[u8]) { + assert!(result.is_err()); + } + #[test] #[serial_test::serial] fn git_all_output_test_repo() -> Result<()> {