Skip to content

Commit

Permalink
initial implementation of VERGEN_CARGO_DEPENDENCIES (#290)
Browse files Browse the repository at this point in the history
* initial implementation of VERGEN_CARGO_DEPENDENCIES

* Added name and dep_kind filter to cargo dependencies
  • Loading branch information
CraZySacX authored Jan 15, 2024
1 parent 8bad39c commit 03ea0db
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 11 deletions.
6 changes: 5 additions & 1 deletion vergen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ version = "8.2.9"

[package.metadata.cargo-all-features]
denylist = [
"cargo_metadata",
"git",
"git2",
"git2-rs",
"gitcl",
"gix",
"gitoxide",
"regex",
"rustc_version",
"sysinfo",
"time",
Expand All @@ -29,7 +31,7 @@ denylist = [
[features]
default = []
build = ["time"]
cargo = []
cargo = ["cargo_metadata", "regex"]
git = []
gitcl = ["time"]
git2 = ["time", "git2-rs"]
Expand All @@ -40,11 +42,13 @@ si = ["sysinfo"]

[dependencies]
anyhow = "1.0.72"
cargo_metadata = { version = "0.18.1", optional = true }
git2-rs = { version = "0.18.0", package = "git2", optional = true, default-features = false }
gix = { version = "0.57.1", optional = true, default-features = false, features = [
"revision",
"interrupt",
] }
regex = { version = "1.9.1", optional = true }
rustc_version = { version = "0.4.0", optional = true }
sysinfo = { version = "0.30.4", optional = true, default-features = false }
time = { version = "0.3.23", features = [
Expand Down
2 changes: 2 additions & 0 deletions vergen/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ mod features {
#[cfg(feature = "cargo")]
pub(crate) const CARGO_DEBUG: &str = "VERGEN_CARGO_DEBUG";
#[cfg(feature = "cargo")]
pub(crate) const CARGO_DEPENDENCIES: &str = "VERGEN_CARGO_DEPENDENCIES";
#[cfg(feature = "cargo")]
pub(crate) const CARGO_FEATURES: &str = "VERGEN_CARGO_FEATURES";
#[cfg(feature = "cargo")]
pub(crate) const CARGO_OPT_LEVEL: &str = "VERGEN_CARGO_OPT_LEVEL";
Expand Down
164 changes: 156 additions & 8 deletions vergen/src/feature/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
// modified, or distributed except according to those terms.

use crate::{
constants::{CARGO_DEBUG, CARGO_FEATURES, CARGO_OPT_LEVEL, CARGO_TARGET_TRIPLE},
constants::{
CARGO_DEBUG, CARGO_DEPENDENCIES, CARGO_FEATURES, CARGO_OPT_LEVEL, CARGO_TARGET_TRIPLE,
},
emitter::{EmitBuilder, RustcEnvMap},
key::VergenKey,
utils::fns::{add_default_map_entry, add_map_entry},
};
use anyhow::{Error, Result};
use anyhow::{anyhow, Error, Result};
use cargo_metadata::{DepKindInfo, DependencyKind, MetadataCommand, Package, PackageId};
use regex::Regex;
use std::env;

#[derive(Clone, Copy, Debug, Default)]
Expand All @@ -22,11 +26,18 @@ pub(crate) struct Config {
pub(crate) cargo_features: bool,
pub(crate) cargo_opt_level: bool,
pub(crate) cargo_target_triple: bool,
pub(crate) cargo_dependencies: bool,
cargo_name_filter: Option<&'static str>,
cargo_dep_kind_filter: Option<DependencyKind>,
}

impl Config {
pub(crate) fn any(self) -> bool {
self.cargo_debug || self.cargo_features || self.cargo_opt_level || self.cargo_target_triple
self.cargo_debug
|| self.cargo_features
|| self.cargo_opt_level
|| self.cargo_target_triple
|| self.cargo_dependencies
}
}

Expand Down Expand Up @@ -108,6 +119,7 @@ impl EmitBuilder {
.cargo_features()
.cargo_opt_level()
.cargo_target_triple()
.cargo_dependencies()
}

/// Emit the DEBUG value set by cargo
Expand Down Expand Up @@ -154,6 +166,42 @@ impl EmitBuilder {
self
}

/// Emit the dependencies value derived from `Cargo.toml`
///
/// ```text
/// cargo:rustc-env=VERGEN_CARGO_DEPENDENCIES=<dependencies>
/// ```
pub fn cargo_dependencies(&mut self) -> &mut Self {
self.cargo_config.cargo_dependencies = true;
self
}

/// Add a name [`Regex`](regex::Regex) filter for cargo dependencies
///
/// ```text
/// cargo:rustc-env=VERGEN_CARGO_DEPENDENCIES=<deps_filtered_by_name>
/// ```
pub fn cargo_dependencies_name_filter(
&mut self,
name_filter: Option<&'static str>,
) -> &mut Self {
self.cargo_config.cargo_name_filter = name_filter;
self
}

/// Add a [`DependencyKind`](cargo_metadata::DependencyKind) filter for cargo dependencies
///
/// ```text
/// cargo:rustc-env=VERGEN_CARGO_DEPENDENCIES=<deps_filtered_by_kind>
/// ```
pub fn cargo_dependencies_dep_kind_filter(
&mut self,
dep_kind_filter: Option<DependencyKind>,
) -> &mut Self {
self.cargo_config.cargo_dep_kind_filter = dep_kind_filter;
self
}

pub(crate) fn add_cargo_default(
&self,
e: Error,
Expand All @@ -176,6 +224,9 @@ impl EmitBuilder {
if self.cargo_config.cargo_target_triple {
add_default_map_entry(VergenKey::CargoTargetTriple, map, warnings);
}
if self.cargo_config.cargo_dependencies {
add_default_map_entry(VergenKey::CargoDependencies, map, warnings);
}
Ok(())
}
}
Expand Down Expand Up @@ -215,9 +266,89 @@ impl EmitBuilder {
add_map_entry(VergenKey::CargoTargetTriple, env::var("TARGET")?, map);
}
}

if self.cargo_config.cargo_dependencies {
if let Ok(value) = env::var(CARGO_DEPENDENCIES) {
add_map_entry(VergenKey::CargoDependencies, value, map);
} else {
let value = Self::get_dependencies(
self.cargo_config.cargo_name_filter,
self.cargo_config.cargo_dep_kind_filter,
)?;
if !value.is_empty() {
add_map_entry(VergenKey::CargoDependencies, value, map);
}
}
}
}
Ok(())
}

fn get_dependencies(
name_filter: Option<&'static str>,
dep_kind_filter: Option<DependencyKind>,
) -> Result<String> {
let metadata = MetadataCommand::new().exec()?;
let resolved_crates = metadata.resolve.ok_or_else(|| anyhow!("No resolve"))?;
let root_id = resolved_crates.root.ok_or_else(|| anyhow!("No root id"))?;
let root = resolved_crates
.nodes
.into_iter()
.find(|node| node.id == root_id)
.ok_or_else(|| anyhow!("No root node"))?;
let package_ids: Vec<(PackageId, Vec<DepKindInfo>)> = root
.deps
.into_iter()
.map(|node_dep| (node_dep.pkg, node_dep.dep_kinds))
.collect();

let packages: Vec<(&Package, &Vec<DepKindInfo>)> = package_ids
.iter()
.filter_map(|(package_id, dep_kinds)| {
metadata
.packages
.iter()
.find(|&package| package.id == *package_id)
.map(|package| (package, dep_kinds))
})
.collect();

let results: Vec<String> = packages
.iter()
.filter_map(|(package, dep_kind_info)| {
if let Some(name_regex) = name_filter {
if let Ok(regex) = Regex::new(name_regex) {
if regex.is_match(&package.name) {
Some((package, dep_kind_info))
} else {
None
}
} else {
Some((package, dep_kind_info))
}
} else {
Some((package, dep_kind_info))
}
})
.filter_map(|(package, dep_kind_info)| {
if let Some(dep_kind_filter) = dep_kind_filter {
let kinds: Vec<DependencyKind> = dep_kind_info
.iter()
.map(|dep_kind_info| dep_kind_info.kind)
.collect();
if kinds.contains(&dep_kind_filter) {
Some(package)
} else {
None
}
} else {
Some(package)
}
})
.map(|package| format!("{} {}", package.name, package.version))
.collect();
Ok(results.join(","))
}
}

fn is_cargo_feature(var: (String, String)) -> Option<String> {
Expand Down Expand Up @@ -247,7 +378,7 @@ mod test {
.idempotent()
.all_cargo()
.test_emit()?;
assert_eq!(4, config.cargo_rustc_env_map.len());
assert_eq!(5, config.cargo_rustc_env_map.len());
assert_eq!(0, count_idempotent(&config.cargo_rustc_env_map));
assert_eq!(0, config.warnings.len());
teardown();
Expand All @@ -259,7 +390,7 @@ mod test {
fn build_all() -> Result<()> {
setup();
let config = EmitBuilder::builder().all_cargo().test_emit()?;
assert_eq!(4, config.cargo_rustc_env_map.len());
assert_eq!(5, config.cargo_rustc_env_map.len());
assert_eq!(0, count_idempotent(&config.cargo_rustc_env_map));
assert_eq!(0, config.warnings.len());
teardown();
Expand All @@ -282,9 +413,9 @@ mod test {
let emit_res = EmitBuilder::builder().all_cargo().test_emit();
assert!(emit_res.is_ok());
let emit = emit_res?;
assert_eq!(4, emit.cargo_rustc_env_map.len());
assert_eq!(4, count_idempotent(&emit.cargo_rustc_env_map));
assert_eq!(4, emit.warnings.len());
assert_eq!(5, emit.cargo_rustc_env_map.len());
assert_eq!(5, count_idempotent(&emit.cargo_rustc_env_map));
assert_eq!(5, emit.warnings.len());
Ok(())
}

Expand Down Expand Up @@ -355,4 +486,21 @@ mod test {
teardown();
Ok(())
}

#[test]
#[serial_test::serial]
fn cargo_dependencies_override_works() -> Result<()> {
setup();
env::set_var("VERGEN_CARGO_DEPENDENCIES", "this is a bad some dep");
let mut stdout_buf = vec![];
assert!(EmitBuilder::builder()
.all_cargo()
.emit_to(&mut stdout_buf)
.is_ok());
let output = String::from_utf8_lossy(&stdout_buf);
assert!(output.contains("cargo:rustc-env=VERGEN_CARGO_DEPENDENCIES=this is a bad some dep"));
env::remove_var("VERGEN_CARGO_DEPENDENCIES");
teardown();
Ok(())
}
}
9 changes: 8 additions & 1 deletion vergen/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ mod keys {
#[cfg(feature = "build")]
use crate::constants::{BUILD_DATE_NAME, BUILD_TIMESTAMP_NAME};
#[cfg(feature = "cargo")]
use crate::constants::{CARGO_DEBUG, CARGO_FEATURES, CARGO_OPT_LEVEL, CARGO_TARGET_TRIPLE};
use crate::constants::{
CARGO_DEBUG, CARGO_DEPENDENCIES, CARGO_FEATURES, CARGO_OPT_LEVEL, CARGO_TARGET_TRIPLE,
};
#[cfg(all(
feature = "git",
any(feature = "gitcl", feature = "git2", feature = "gix")
Expand Down Expand Up @@ -68,6 +70,9 @@ mod keys {
/// The cargo target triple (VERGEN_CARGO_TARGET_TRIPLE)
#[cfg(feature = "cargo")]
CargoTargetTriple,
/// The cargo dependencies (VERGEN_CARGO_DEPENDENCIES)
#[cfg(feature = "cargo")]
CargoDependencies,
/// The current working branch name (VERGEN_GIT_BRANCH)
#[cfg(all(
feature = "git",
Expand Down Expand Up @@ -191,6 +196,8 @@ mod keys {
VergenKey::CargoOptLevel => CARGO_OPT_LEVEL,
#[cfg(feature = "cargo")]
VergenKey::CargoTargetTriple => CARGO_TARGET_TRIPLE,
#[cfg(feature = "cargo")]
VergenKey::CargoDependencies => CARGO_DEPENDENCIES,
#[cfg(all(
feature = "git",
any(feature = "gitcl", feature = "git2", feature = "gix")
Expand Down
8 changes: 8 additions & 0 deletions vergen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,11 @@ mod utils;
use {gix as _, lazy_static as _, regex as _, repo_util as _, serial_test as _, temp_env as _};

pub use crate::emitter::EmitBuilder;
#[cfg(feature = "si")]
pub use sysinfo::CpuRefreshKind;
#[cfg(feature = "si")]
pub use sysinfo::MemoryRefreshKind;
#[cfg(feature = "si")]
pub use sysinfo::ProcessRefreshKind;
#[cfg(feature = "si")]
pub use sysinfo::RefreshKind;
Loading

0 comments on commit 03ea0db

Please sign in to comment.