cargo_feature_matrix/
lib.rs1mod config;
2mod execution;
3pub mod features;
4
5pub use self::{config::Config, execution::TaskKind};
6use self::{execution::Task, features::FeatureMatrix};
7use cargo_metadata::{Metadata, MetadataCommand, Package};
8use derive_more::{
9 derive::{Display, Error},
10 From,
11};
12use figment::{
13 providers::{Format, Json},
14 Figment,
15};
16use std::path::PathBuf;
17
18pub fn run(
19 command: String,
20 args: Vec<String>,
21 task: TaskKind,
22 manifest_path: Option<PathBuf>,
23 figment: Figment,
24) -> Result<(), Error> {
25 let mut cmd = MetadataCommand::new();
26 if let Some(manifest_path) = &manifest_path {
27 cmd.manifest_path(manifest_path);
28 }
29 let metadata = cmd.exec()?;
30
31 let mut error = None;
32 for package in get_workspace_members(&metadata) {
33 let figment =
34 if let Some(package_config) = package.metadata.get("feature-matrix") {
35 figment
36 .clone()
37 .merge(Figment::from(Json::string(&package_config.to_string())))
38 } else {
39 figment.clone()
40 };
41
42 let config = Config::from(figment)?;
43
44 let matrix = FeatureMatrix::new(package, &config);
45 let task = Task::new(
46 task,
47 &command,
48 manifest_path.as_deref(),
49 &package.name,
50 &args,
51 matrix,
52 );
53
54 if let Err(err) = task.run() {
55 error = Some(err);
56 }
57 }
58
59 match error {
60 Some(err) => Err(err),
61 None => Ok(()),
62 }
63}
64
65fn get_workspace_members(
67 metadata: &Metadata,
68) -> impl Iterator<Item = &Package> + '_ {
69 metadata
70 .packages
71 .iter()
72 .filter(|package| metadata.workspace_members.contains(&package.id))
73}
74
75#[derive(Debug, Display, Error, From)]
76pub enum Error {
77 #[display("failed to get cargo metadata")]
78 Metadata(cargo_metadata::Error),
79 #[display("{message}")]
80 Io {
81 message: &'static str,
82 source: std::io::Error,
83 },
84 #[display("child process exited with {_0}")]
85 #[from(ignore)]
86 #[error(ignore)]
87 Fail(std::process::ExitStatus),
88 #[display("failed to get config from metadata")]
89 Config(figment::Error),
90}
91
92#[cfg(test)]
93mod tests {}