From 61e560eacc2622c268660e83275d6ee3b4e70107 Mon Sep 17 00:00:00 2001 From: Jason Ozias Date: Thu, 25 Mar 2021 12:17:51 -0400 Subject: [PATCH] Add `sysinfo` support (#58) * initial sysinfo impl * Added some data to the sysinfo feature * Fixed sysinfo issue on windows * Fix broken tests * fixed broken test on windows * Added some tests and refactor for coverage * coverage crap * added name, brand, and freq to sysinfo * Fixed lint error * Fix rustc test on beta and stable Co-authored-by: Jason Ozias --- Cargo.toml | 5 +- src/config.rs | 67 +++++++++- src/constants.rs | 22 ++++ src/error.rs | 18 +++ src/feature/mod.rs | 13 +- src/feature/si.rs | 312 +++++++++++++++++++++++++++++++++++++++++++++ src/gen.rs | 78 ++++++++---- src/lib.rs | 21 ++- 8 files changed, 502 insertions(+), 34 deletions(-) create mode 100644 src/feature/si.rs diff --git a/Cargo.toml b/Cargo.toml index 9a18b6f5..7efa2345 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,11 +13,12 @@ repository = "https://github.com/rustyhorde/vergen" version = "5.0.1" [features] -default = ["build", "cargo", "git", "rustc"] +default = ["build", "cargo", "git", "rustc", "si"] build = ["chrono"] cargo = [] git = ["chrono", "git2"] rustc = ["rustc_version"] +si = ["sysinfo"] [dependencies] anyhow = "1" @@ -26,6 +27,7 @@ enum-iterator = "0" getset = "0" git2 = { version = "0", optional = true, default-features = false } rustc_version = { version = "0", optional = true } +sysinfo = { version = "0", optional = true } thiserror = "1" [build-dependencies] @@ -35,7 +37,6 @@ rustversion = "1" [dev-dependencies] lazy_static = "1" regex = "1" -rustversion = "1" serial_test = "0" [package.metadata.cargo-all-features] diff --git a/src/config.rs b/src/config.rs index ec6e673d..1b93c1ad 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,15 +16,21 @@ use crate::feature::Cargo; use crate::feature::Git; #[cfg(feature = "rustc")] use crate::feature::Rustc; +#[cfg(feature = "si")] +use crate::feature::Sysinfo; use crate::{ constants::{ 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, + RUSTC_HOST_TRIPLE_NAME, RUSTC_LLVM_VERSION, RUSTC_SEMVER_NAME, SYSINFO_CPU_BRAND, + SYSINFO_CPU_CORE_COUNT, SYSINFO_CPU_FREQUENCY, SYSINFO_CPU_NAME, SYSINFO_CPU_VENDOR, + SYSINFO_MEMORY, SYSINFO_NAME, SYSINFO_OS_VERSION, SYSINFO_USER, + }, + feature::{ + configure_build, configure_cargo, configure_git, configure_rustc, configure_sysinfo, }, - feature::{configure_build, configure_cargo, configure_git, configure_rustc}, }; use anyhow::Result; use enum_iterator::IntoEnumIterator; @@ -40,6 +46,7 @@ use std::{ /// * 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 +/// * See [`Sysinfo`](crate::Sysinfo) for details on `VERGEN_SYSINFO_*` instruction configuration /// /// # Example /// @@ -76,6 +83,13 @@ use std::{ *config.cargo_mut().profile_mut() = false; "## )] +#[cfg_attr( + feature = "si", + doc = r##" +// Turn off the sysinfo name instruction +*config.sysinfo_mut().name_mut() = false; +"## +)] /// ``` #[derive(Clone, Copy, Debug, Getters, MutGetters)] #[getset(get = "pub(crate)", get_mut = "pub")] @@ -92,6 +106,9 @@ pub struct Instructions { /// Use this to modify the [`Rustc`] feature configuration. #[cfg(feature = "rustc")] rustc: Rustc, + /// Use this to modify the [`Sysinfo`] feature configuration. + #[cfg(feature = "si")] + sysinfo: Sysinfo, } impl Default for Instructions { @@ -105,6 +122,8 @@ impl Default for Instructions { git: Git::default(), #[cfg(feature = "rustc")] rustc: Rustc::default(), + #[cfg(feature = "si")] + sysinfo: Sysinfo::default(), } } } @@ -120,6 +139,7 @@ impl Instructions { configure_git(self, repo_path, &mut config)?; configure_rustc(self, &mut config)?; configure_cargo(self, &mut config); + configure_sysinfo(self, &mut config)?; Ok(config) } @@ -171,6 +191,24 @@ pub(crate) enum VergenKey { CargoProfile, /// The cargo features (VERGEN_CARGO_FEATURES) CargoFeatures, + /// The sysinfo system name (VERGEN_SYSINFO_NAME) + SysinfoName, + /// The sysinfo os version (VERGEN_SYSINFO_OS_VERSION) + SysinfoOsVersion, + /// The sysinfo user name (VERGEN_SYSINFO_USER) + SysinfoUser, + /// The sysinfo total memory (VERGEN_SYSINFO_TOTAL_MEMORY) + SysinfoMemory, + /// The sysinfo cpu vendor (VERGEN_SYSINFO_CPU_VENDOR) + SysinfoCpuVendor, + /// The sysinfo cpu core count (VERGEN_SYSINFO_CPU_CORE_COUNT) + SysinfoCpuCoreCount, + /// The sysinfo cpu core count (VERGEN_SYSINFO_CPU_NAME) + SysinfoCpuName, + /// The sysinfo cpu core count (VERGEN_SYSINFO_CPU_BRAND) + SysinfoCpuBrand, + /// The sysinfo cpu core count (VERGEN_SYSINFO_CPU_FREQUENCY) + SysinfoCpuFrequency, } impl VergenKey { @@ -198,6 +236,15 @@ impl VergenKey { VergenKey::CargoTargetTriple => CARGO_TARGET_TRIPLE, VergenKey::CargoProfile => CARGO_PROFILE, VergenKey::CargoFeatures => CARGO_FEATURES, + VergenKey::SysinfoName => SYSINFO_NAME, + VergenKey::SysinfoOsVersion => SYSINFO_OS_VERSION, + VergenKey::SysinfoUser => SYSINFO_USER, + VergenKey::SysinfoMemory => SYSINFO_MEMORY, + VergenKey::SysinfoCpuVendor => SYSINFO_CPU_VENDOR, + VergenKey::SysinfoCpuCoreCount => SYSINFO_CPU_CORE_COUNT, + VergenKey::SysinfoCpuName => SYSINFO_CPU_NAME, + VergenKey::SysinfoCpuBrand => SYSINFO_CPU_BRAND, + VergenKey::SysinfoCpuFrequency => SYSINFO_CPU_FREQUENCY, } } } @@ -291,6 +338,21 @@ mod test { #[cfg(not(feature = "rustc"))] fn check_rustc_config(_instructions: &Instructions) {} + #[cfg(feature = "si")] + fn check_sysinfo_config(instructions: &Instructions) { + let config = instructions.sysinfo(); + assert!(config.has_enabled()); + assert!(config.name()); + assert!(config.os_version()); + assert!(config.user()); + assert!(config.memory()); + assert!(config.cpu_vendor()); + assert!(config.cpu_core_count()); + } + + #[cfg(not(feature = "si"))] + fn check_sysinfo_config(_instructions: &Instructions) {} + #[test] fn default_instructions() { let default = Instructions::default(); @@ -298,5 +360,6 @@ mod test { check_cargo_config(&default); check_git_config(&default); check_rustc_config(&default); + check_sysinfo_config(&default); } } diff --git a/src/constants.rs b/src/constants.rs index 9cf4cd78..5dafcaa7 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -37,6 +37,17 @@ pub(crate) const CARGO_TARGET_TRIPLE: &str = "VERGEN_CARGO_TARGET_TRIPLE"; pub(crate) const CARGO_PROFILE: &str = "VERGEN_CARGO_PROFILE"; pub(crate) const CARGO_FEATURES: &str = "VERGEN_CARGO_FEATURES"; +// sysinfo Constants +pub(crate) const SYSINFO_NAME: &str = "VERGEN_SYSINFO_NAME"; +pub(crate) const SYSINFO_OS_VERSION: &str = "VERGEN_SYSINFO_OS_VERSION"; +pub(crate) const SYSINFO_USER: &str = "VERGEN_SYSINFO_USER"; +pub(crate) const SYSINFO_MEMORY: &str = "VERGEN_SYSINFO_TOTAL_MEMORY"; +pub(crate) const SYSINFO_CPU_VENDOR: &str = "VERGEN_SYSINFO_CPU_VENDOR"; +pub(crate) const SYSINFO_CPU_CORE_COUNT: &str = "VERGEN_SYSINFO_CPU_CORE_COUNT"; +pub(crate) const SYSINFO_CPU_NAME: &str = "VERGEN_SYSINFO_CPU_NAME"; +pub(crate) const SYSINFO_CPU_BRAND: &str = "VERGEN_SYSINFO_CPU_BRAND"; +pub(crate) const SYSINFO_CPU_FREQUENCY: &str = "VERGEN_SYSINFO_CPU_FREQUENCY"; + #[cfg(test)] mod test { use super::*; @@ -67,5 +78,16 @@ mod test { assert_eq!(CARGO_TARGET_TRIPLE, "VERGEN_CARGO_TARGET_TRIPLE"); assert_eq!(CARGO_PROFILE, "VERGEN_CARGO_PROFILE"); assert_eq!(CARGO_FEATURES, "VERGEN_CARGO_FEATURES"); + + // sysinfo Constants + assert_eq!(SYSINFO_NAME, "VERGEN_SYSINFO_NAME"); + assert_eq!(SYSINFO_OS_VERSION, "VERGEN_SYSINFO_OS_VERSION"); + assert_eq!(SYSINFO_USER, "VERGEN_SYSINFO_USER"); + assert_eq!(SYSINFO_MEMORY, "VERGEN_SYSINFO_TOTAL_MEMORY"); + assert_eq!(SYSINFO_CPU_VENDOR, "VERGEN_SYSINFO_CPU_VENDOR"); + assert_eq!(SYSINFO_CPU_CORE_COUNT, "VERGEN_SYSINFO_CPU_CORE_COUNT"); + assert_eq!(SYSINFO_CPU_NAME, "VERGEN_SYSINFO_CPU_NAME"); + assert_eq!(SYSINFO_CPU_BRAND, "VERGEN_SYSINFO_CPU_BRAND"); + assert_eq!(SYSINFO_CPU_FREQUENCY, "VERGEN_SYSINFO_CPU_FREQUENCY"); } } diff --git a/src/error.rs b/src/error.rs index 0e820f51..8525b0e3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -42,6 +42,14 @@ pub(crate) enum Error { /// An error getting the 'CARGO_PKG_VERSION' environment variable #[error("{}: The 'CARGO_PKG_VERSION' environment variable may not be set: {}", ErrKind::Env, .0)] Var(#[from] std::env::VarError), + /// An error getting the current pid + #[cfg(feature = "si")] + #[error( + "{}: Unable to determine the current process pid: {}", + ErrKind::Protocol, + msg + )] + Pid { msg: &'static str }, } #[cfg(test)] @@ -89,6 +97,16 @@ mod test { assert_eq!("protocol: An error occurred in the \'git2\' library: failed to resolve path \'blah\': The system cannot find the file specified.\r\n; class=Os (2); code=NotFound (-3)", format!("{}", err)); } + #[cfg(feature = "si")] + #[test] + fn pid_error() { + let err: Error = Error::Pid { msg: "test" }; + assert_eq!( + "protocol: Unable to determine the current process pid: test", + format!("{}", err) + ); + } + #[test] fn var_error() { let res = env::var("yoda").map_err(|e| Error::from(e)); diff --git a/src/feature/mod.rs b/src/feature/mod.rs index bd92fcd5..1560af3f 100644 --- a/src/feature/mod.rs +++ b/src/feature/mod.rs @@ -12,7 +12,8 @@ feature = "build", feature = "cargo", feature = "git", - feature = "rustc" + feature = "rustc", + feature = "si", ))] use {crate::config::VergenKey, std::collections::BTreeMap}; @@ -20,6 +21,7 @@ mod build; mod cargo; mod git; mod rustc; +mod si; pub(crate) use build::configure_build; #[cfg(feature = "build")] @@ -33,12 +35,16 @@ pub use git::{Git, SemverKind, ShaKind}; pub(crate) use rustc::configure_rustc; #[cfg(feature = "rustc")] pub use rustc::Rustc; +pub(crate) use si::configure_sysinfo; +#[cfg(feature = "si")] +pub use si::Sysinfo; #[cfg(any( feature = "build", feature = "cargo", feature = "git", - feature = "rustc" + feature = "rustc", + feature = "si", ))] pub(crate) fn add_entry( map: &mut BTreeMap>, @@ -80,7 +86,8 @@ pub enum TimestampKind { feature = "build", feature = "cargo", feature = "git", - feature = "rustc" + feature = "rustc", + feature = "si", ) ))] mod test { diff --git a/src/feature/si.rs b/src/feature/si.rs new file mode 100644 index 00000000..9ae5f1d7 --- /dev/null +++ b/src/feature/si.rs @@ -0,0 +1,312 @@ +// Copyright (c) 2016, 2018, 2021 vergen developers +// +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , at your +// option. All files in the project carrying such notice may not be copied, +// modified, or distributed except according to those terms. + +//! `vergen` sysinfo feature implementation + +use crate::config::{Config, Instructions}; +use anyhow::Result; +#[cfg(feature = "si")] +use { + crate::{config::VergenKey, error::Error::Pid, feature::add_entry}, + getset::{Getters, MutGetters}, + sysinfo::{get_current_pid, Process, ProcessorExt, System, SystemExt, User, UserExt}, +}; + +/// Configuration for the `VERGEN_SYSINFO_*` instructions +/// +/// # Instructions +/// The following instructions can be generated: +/// +/// | Instruction | Default | +/// | ----------- | :-----: | +/// | `cargo:rustc-env=VERGEN_SYSINFO_NAME=Darwin` | * | +/// | `cargo:rustc-env=VERGEN_SYSINFO_OS_VERSION=MacOS 10.15.7 Catalina` | * | +/// | `cargo:rustc-env=VERGEN_SYSINFO_USER=yoda` | * | +/// | `cargo:rustc-env=VERGEN_SYSINFO_TOTAL_MEMORY=16 GB` | * | +/// | `cargo:rustc-env=VERGEN_SYSINFO_CPU_VENDOR=Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz` | * | +/// | `cargo:rustc-env=VERGEN_SYSINFO_CPU_CORE_COUNT=4` | * | +/// +/// * If the `name` field is false, the `VERGEN_SYSINFO_NAME` instruction will not be generated. +/// * If the `os_version` field is false, the `VERGEN_SYSINFO_OS_VERSION` instruction will not be generated. +/// * If the `user` field is false, the `VERGEN_SYSINFO_USER` instruction will not be generated. +/// * If the `memory` field is false, the `VERGEN_SYSINFO_TOTAL_MEMORY` instruction will not be generated. +/// * If the `cpu_vendor` field is false, the `VERGEN_SYSINFO_CPU_VENDOR` instruction will not be generated. +/// * If the `cpu_core_count` field is false, the `VERGEN_SYSINFO_CPU_CORE_COUNT` instruction will not be generated. +/// +/// # Example +/// +/// ``` +/// # use anyhow::Result; +/// use vergen::{vergen, Config}; +/// +/// # pub fn main() -> Result<()> { +/// let mut config = Config::default(); +#[cfg_attr( + feature = "si", + doc = r##" +// Turn off the name instruction +*config.sysinfo_mut().name_mut() = false; + +// Generate the instructions +vergen(config)?; +"## +)] +/// # Ok(()) +/// # } +#[cfg(feature = "si")] +#[derive(Clone, Copy, Debug, Getters, MutGetters)] +#[getset(get = "pub(crate)", get_mut = "pub")] +#[allow(clippy::clippy::struct_excessive_bools)] +pub struct Sysinfo { + /// Enable/Disable the `VERGEN_SYSINFO_NAME` instruction + name: bool, + /// Enable/Disable the `VERGEN_SYSINFO_OS_VERSION` instruction + os_version: bool, + /// Enable/Disable the `VERGEN_SYSINFO_USER` instruction + user: bool, + /// Enable/Disable the `VERGEN_SYSINFO_TOTAL_MEMORY` instruction + memory: bool, + /// Enable/Disable the `VERGEN_SYSINFO_CPU_VENDOR` instruction + cpu_vendor: bool, + /// Enable/Disable the `VERGEN_SYSINFO_CPU_CORE_COUNT` instruction + cpu_core_count: bool, + /// Enable/Disable the `VERGEN_SYSINFO_CPU_NAME` instruction + cpu_name: bool, + /// Enable/Disable the `VERGEN_SYSINFO_CPU_BRAND` instruction + cpu_brand: bool, + /// Enable/Disable the `VERGEN_SYSINFO_CPU_FREQUENCY` instruction + cpu_frequency: bool, +} + +#[cfg(feature = "si")] +impl Default for Sysinfo { + fn default() -> Self { + Self { + name: true, + os_version: true, + user: true, + memory: true, + cpu_vendor: true, + cpu_core_count: true, + cpu_name: true, + cpu_brand: true, + cpu_frequency: true, + } + } +} + +#[cfg(feature = "si")] +impl Sysinfo { + pub(crate) fn has_enabled(self) -> bool { + self.name + || self.os_version + || self.user + || self.memory + || self.cpu_vendor + || self.cpu_core_count + || self.cpu_name + || self.cpu_brand + || self.cpu_frequency + } +} + +#[cfg(feature = "si")] +pub(crate) fn configure_sysinfo(instructions: Instructions, config: &mut Config) -> Result<()> { + let sysinfo_config = instructions.sysinfo(); + if sysinfo_config.has_enabled() { + let mut system = System::new_all(); + // First we update all information of our system struct. + system.refresh_all(); + + if *sysinfo_config.name() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoName, + system.get_name(), + ); + } + + if *sysinfo_config.os_version() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoOsVersion, + system.get_long_os_version(), + ); + } + + if *sysinfo_config.user() { + let pid = get_current_pid().map_err(|e| Pid { msg: e })?; + if let Some(process) = system.get_process(pid) { + for user in system.get_users() { + if check_user(process, user) { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoUser, + Some(user.get_name().to_string()), + ); + } + } + } + } + + if *sysinfo_config.memory() { + let mut curr_memory = system.get_total_memory(); + let mut count = 0; + + while curr_memory > 1000 { + curr_memory /= 1000; + count += 1; + } + + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoMemory, + Some(format!("{} {}", curr_memory, suffix(count))), + ); + } + + if *sysinfo_config.cpu_vendor() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoCpuVendor, + system + .get_processors() + .get(0) + .map(|processor| processor.get_vendor_id().to_string()), + ) + } + + if *sysinfo_config.cpu_core_count() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoCpuCoreCount, + system.get_physical_core_count().map(|x| x.to_string()), + ); + } + + if *sysinfo_config.cpu_name() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoCpuName, + Some( + system + .get_processors() + .iter() + .map(|p| p.get_name()) + .collect::>() + .join(","), + ), + ); + } + + if *sysinfo_config.cpu_brand() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoCpuBrand, + system + .get_processors() + .get(0) + .map(|processor| processor.get_brand().to_string()), + ); + } + + if *sysinfo_config.cpu_frequency() { + add_entry( + config.cfg_map_mut(), + VergenKey::SysinfoCpuFrequency, + system + .get_processors() + .get(0) + .map(|processor| processor.get_frequency().to_string()), + ); + } + } + + Ok(()) +} + +#[cfg(not(feature = "si"))] +pub(crate) fn configure_sysinfo(_instructions: Instructions, _config: &mut Config) -> Result<()> { + Ok(()) +} + +#[cfg(all(feature = "si", not(target_os = "windows")))] +fn check_user(process: &Process, user: &User) -> bool { + *user.get_uid() == process.uid +} + +#[cfg(all(feature = "si", target_os = "windows"))] +fn check_user(_process: &Process, _user: &User) -> bool { + false +} + +#[cfg(feature = "si")] +fn suffix(val: usize) -> &'static str { + match val { + 0 => "KB", + 1 => "MB", + 2 => "GB", + _ => "xB", + } +} + +#[cfg(all(test, feature = "si"))] +mod test { + use super::{suffix, Sysinfo}; + use crate::config::Instructions; + + #[test] + fn rustc_config() { + let mut config = Instructions::default(); + assert!(config.sysinfo().name); + assert!(config.sysinfo().os_version); + assert!(config.sysinfo().user); + assert!(config.sysinfo().cpu_vendor); + assert!(config.sysinfo().cpu_core_count); + assert!(config.sysinfo().cpu_name); + assert!(config.sysinfo().cpu_brand); + assert!(config.sysinfo().cpu_frequency); + config.sysinfo_mut().os_version = false; + assert!(!config.sysinfo().os_version); + } + + #[test] + fn has_enabled_works() { + let mut sysinfo = Sysinfo::default(); + assert!(sysinfo.has_enabled()); + *sysinfo.name_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.os_version_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.user_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.memory_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.cpu_vendor_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.cpu_core_count_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.cpu_name_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.cpu_brand_mut() = false; + assert!(sysinfo.has_enabled()); + *sysinfo.cpu_frequency_mut() = false; + assert!(!sysinfo.has_enabled()); + } + + #[test] + fn suffix_works() { + assert_eq!("KB", suffix(0)); + assert_eq!("MB", suffix(1)); + assert_eq!("GB", suffix(2)); + assert_eq!("xB", suffix(3)); + } +} + +#[cfg(all(test, not(feature = "si")))] +mod test {} diff --git a/src/gen.rs b/src/gen.rs index 18548139..424fa353 100644 --- a/src/gen.rs +++ b/src/gen.rs @@ -205,7 +205,7 @@ mod test { static ref RUSTC_LLVM_RE_STR: &'static str = r#"cargo:rustc-env=VERGEN_RUSTC_LLVM_VERSION=\d{2}\.\d{1}"#; static ref RUSTC_SEMVER_RE_STR: &'static str = r#"cargo:rustc-env=VERGEN_RUSTC_SEMVER=(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?"#; - static ref RUSTC_NIGHTLY_REGEX: Regex = { + static ref RUSTC_REGEX: Regex = { let re_str = vec![ *RUSTC_CHANNEL_RE_STR, *RUSTC_CD_RE_STR, @@ -219,16 +219,50 @@ mod test { }; } - #[cfg(feature = "rustc")] - #[rustversion::stable] + #[cfg(all(feature = "si", not(target_os = "windows")))] lazy_static! { - static ref RUSTC_REGEX: Regex = { + static ref NAME_RE_STR: &'static str = r#"cargo:rustc-env=VERGEN_SYSINFO_NAME=.*"#; + static ref OS_VERSION_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_OS_VERSION=.*"#; + static ref USER_RE_STR: &'static str = r#"cargo:rustc-env=VERGEN_SYSINFO_USER=.*"#; + static ref TOTAL_MEMORY_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_TOTAL_MEMORY=.*"#; + static ref CPU_VENDOR_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_CPU_VENDOR=.*"#; + static ref CPU_CORE_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_CPU_CORE_COUNT=.*"#; + static ref SYSINFO_REGEX_INST: Regex = { let re_str = vec![ - *RUSTC_CHANNEL_RE_STR, - *RUSTC_CD_RE_STR, - *RUSTC_CH_RE_STR, - *RUSTC_HT_RE_STR, - *RUSTC_SEMVER_RE_STR, + *NAME_RE_STR, + *OS_VERSION_RE_STR, + *USER_RE_STR, + *TOTAL_MEMORY_RE_STR, + *CPU_VENDOR_RE_STR, + *CPU_CORE_RE_STR, + ] + .join("\n"); + Regex::new(&re_str).unwrap() + }; + } + + #[cfg(all(feature = "si", target_os = "windows"))] + lazy_static! { + static ref NAME_RE_STR: &'static str = r#"cargo:rustc-env=VERGEN_SYSINFO_NAME=.*"#; + static ref OS_VERSION_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_OS_VERSION=.*"#; + static ref TOTAL_MEMORY_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_TOTAL_MEMORY=.*"#; + static ref CPU_VENDOR_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_CPU_VENDOR=.*"#; + static ref CPU_CORE_RE_STR: &'static str = + r#"cargo:rustc-env=VERGEN_SYSINFO_CPU_CORE_COUNT=.*"#; + static ref SYSINFO_REGEX_INST: Regex = { + let re_str = vec![ + *NAME_RE_STR, + *OS_VERSION_RE_STR, + *TOTAL_MEMORY_RE_STR, + *CPU_VENDOR_RE_STR, + *CPU_CORE_RE_STR, ] .join("\n"); Regex::new(&re_str).unwrap() @@ -309,6 +343,7 @@ mod test { not(feature = "cargo"), not(feature = "git"), not(feature = "rustc"), + not(feature = "si"), ))] #[test] fn no_features_no_output() { @@ -383,22 +418,21 @@ mod test { check_rustc_output(&stdout_buf); } - #[cfg(feature = "rustc")] - #[rustversion::nightly] - fn check_rustc_output(stdout: &[u8]) { - assert!(RUSTC_NIGHTLY_REGEX.is_match(&String::from_utf8_lossy(&stdout))); - } - - // 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]) { - assert!(!stdout.is_empty()); + #[cfg(feature = "si")] + #[test] + fn contains_sysinfo_output() { + let repo_path = PathBuf::from("."); + let mut stdout_buf = vec![]; + assert!(config_from_instructions( + Instructions::default(), + Some(repo_path), + &mut stdout_buf, + ) + .is_ok()); + assert!(SYSINFO_REGEX_INST.is_match(&String::from_utf8_lossy(&stdout_buf))); } #[cfg(feature = "rustc")] - #[rustversion::stable] fn check_rustc_output(stdout: &[u8]) { assert!(RUSTC_REGEX.is_match(&String::from_utf8_lossy(&stdout))); } diff --git a/src/lib.rs b/src/lib.rs index fa1640b0..918c5e22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,7 +54,7 @@ //! ``` //! //! ## Features -//! `vergen` has four feature toggles allowing you to customize your output. +//! `vergen` has five feature toggles allowing you to customize your output. //! //! | Feature | Enables | //! | ------- | ------- | @@ -62,8 +62,9 @@ //! | cargo | `VERGEN_CARGO_*` instructions | //! | git | `VERGEN_GIT_*` instructions and the `cargo:rerun-if-changed` instructions | //! | rustc | `VERGEN_RUSTC_*` instructions | +//! | si | `VERGEN_SYSINFO_*` instructions | //! -//! **NOTE** - All four features are enabled by default. +//! **NOTE** - All five features are enabled by default. //! //! ## Sample Output //! If all features are enabled and the default [`Config`] is used the build script will generate instructions for cargo similar to below. @@ -86,6 +87,9 @@ //! cargo:rustc-env=VERGEN_CARGO_FEATURES=git,build //! cargo:rustc-env=VERGEN_CARGO_PROFILE=debug //! cargo:rustc-env=VERGEN_CARGO_TARGET_TRIPLE=x86_64-unknown-linux-gnu +//! cargo:rustc-env=VERGEN_SYSINFO_NAME=Darwin +//! cargo:rustc-env=VERGEN_SYSINFO_OS_VERSION=MacOS 10.15.7 Catalina +//! cargo:rustc-env=VERGEN_SYSINFO_USER=yoda //! 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/fun //! ``` @@ -118,6 +122,13 @@ //! | `VERGEN_CARGO_FEATURES` | git,build | //! | `VERGEN_CARGO_PROFILE` | debug | //! | `VERGEN_CARGO_TARGET_TRIPLE` | x86_64-unknown-linux-gnu | +//! | See [`Sysinfo`](crate::Sysinfo) to configure the following | +//! | `VERGEN_SYSINFO_NAME` | Darwin | +//! | `VERGEN_SYSINFO_OS_VERSION` | `MacOS 10.15.7 Catalina` | +//! | `VERGEN_SYSINFO_USER` | Yoda | +//! | `VERGEN_SYSINFO_TOTAL_MEMORY` | 16 GB | +//! | `VERGEN_SYSINFO_CPU_VENDOR` | Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz | +//! | `VERGEN_SYSINFO_CPU_CORE_COUNT` | 4 | //! //! ## Usage //! @@ -307,7 +318,7 @@ rustdoc::invalid_html_tags, rustdoc::missing_crate_level_docs, rustdoc::missing_doc_code_examples, - rustdoc::private_doc_tests, + // rustdoc::private_doc_tests, ) )] @@ -330,14 +341,14 @@ pub use crate::feature::Rustc; pub use crate::feature::SemverKind; #[cfg(feature = "git")] pub use crate::feature::ShaKind; +#[cfg(feature = "si")] +pub use crate::feature::Sysinfo; #[cfg(any(feature = "git", feature = "build"))] pub use crate::feature::TimeZone; #[cfg(any(feature = "git", feature = "build"))] pub use crate::feature::TimestampKind; pub use crate::gen::vergen; -#[cfg(all(test, not(feature = "rustc")))] -use rustversion as _; #[cfg(all(test, not(feature = "cargo")))] use serial_test as _;