Skip to content

Instantly share code, notes, and snippets.

@maciektr
Created April 2, 2024 08:23
Show Gist options
  • Save maciektr/0e93d5ac00235c850e40f5cf4d2f8577 to your computer and use it in GitHub Desktop.
Save maciektr/0e93d5ac00235c850e40f5cf4d2f8577 to your computer and use it in GitHub Desktop.
diff --git a/scarb/src/bin/scarb/args.rs b/scarb/src/bin/scarb/args.rs
index 4fb488f7..c8d28473 100644
--- a/scarb/src/bin/scarb/args.rs
+++ b/scarb/src/bin/scarb/args.rs
@@ -8,7 +8,7 @@ use std::ffi::OsString;
use anyhow::Result;
use camino::Utf8PathBuf;
use clap::{CommandFactory, Parser, Subcommand};
-use scarb::ops::EmitTarget;
+use scarb::ops::{EmitTarget, FeaturesOpts};
use smol_str::SmolStr;
use tracing::level_filters::LevelFilter;
use tracing_log::AsTrace;
@@ -412,6 +412,9 @@ pub struct TestArgs {
#[command(flatten)]
pub packages_filter: PackagesFilter,
+ #[command(flatten)]
+ pub features: FeaturesSpec,
+
/// Arguments for the test program.
#[clap(allow_hyphen_values = true)]
pub args: Vec<OsString>,
@@ -420,6 +423,36 @@ pub struct TestArgs {
// because now they don't show in `scarb test -h`
}
+#[derive(Parser, Clone, Debug)]
+#[group(multiple = true)]
+pub struct FeaturesSpec {
+ /// Comma separated list of features to activate
+ #[arg(short = 'F', long, value_delimiter = ',', env = "SCARB_FEATURES")]
+ pub features: Vec<String>,
+
+ /// Activate all available features
+ #[arg(long, default_value_t = false, env = "SCARB_ALL_FEATURES")]
+ pub all_features: bool,
+
+ /// Do not activate the `default` feature
+ #[arg(long, default_value_t = false, env = "SCARB_NO_DEFAULT_FEATURES")]
+ pub no_default_features: bool,
+}
+
+impl From<FeaturesSpec> for FeaturesOpts {
+ fn from(spec: FeaturesSpec) -> Self {
+ Self {
+ features: spec
+ .features
+ .into_iter()
+ .filter(|f| !f.is_empty())
+ .collect(),
+ all_features: spec.all_features,
+ no_default_features: spec.no_default_features,
+ }
+ }
+}
+
/// Arguments accepted by both the `package` and the `publish` command.
#[derive(Parser, Clone, Debug)]
pub struct PackageSharedArgs {
diff --git a/scarb/src/bin/scarb/commands/test.rs b/scarb/src/bin/scarb/commands/test.rs
index b1a93765..7358bfc5 100644
--- a/scarb/src/bin/scarb/commands/test.rs
+++ b/scarb/src/bin/scarb/commands/test.rs
@@ -11,5 +11,8 @@ pub fn run(args: TestArgs, config: &Config) -> Result<()> {
args.packages_filter
.match_many(&ws)?
.iter()
- .try_for_each(|package| ops::execute_test_subcommand(package, &args.args, &ws).map(|_| ()))
+ .try_for_each(|package| {
+ ops::execute_test_subcommand(package, &args.args, &ws, args.features.clone().into())
+ .map(|_| ())
+ })
}
diff --git a/scarb/src/ops/subcommands.rs b/scarb/src/ops/subcommands.rs
index bac16d3c..099d5aea 100644
--- a/scarb/src/ops/subcommands.rs
+++ b/scarb/src/ops/subcommands.rs
@@ -13,8 +13,9 @@ use scarb_ui::components::Status;
use crate::core::{Config, Package, ScriptDefinition, Workspace};
use crate::internal::fsx::is_executable;
use crate::ops;
+use crate::ops::FeaturesOpts;
use crate::process::exec_replace;
-use crate::subcommands::{get_env_vars, EXTERNAL_CMD_PREFIX, SCARB_MANIFEST_PATH_ENV};
+use crate::subcommands::{get_env_vars, ToEnv, EXTERNAL_CMD_PREFIX, SCARB_MANIFEST_PATH_ENV};
/// Prepare environment and execute an external subcommand.
///
@@ -49,19 +50,21 @@ pub fn execute_test_subcommand(
package: &Package,
args: &[OsString],
ws: &Workspace<'_>,
+ features: FeaturesOpts,
) -> Result<()> {
let package_name = &package.id.name;
- let env = Some(HashMap::from_iter([(
+ let mut env = HashMap::from_iter([(
SCARB_MANIFEST_PATH_ENV.into(),
package.manifest_path().to_string(),
- )]));
+ )]);
+ env.extend(features.to_env_vars());
if let Some(script_definition) = package.manifest.scripts.get("test") {
debug!("using `test` script: {script_definition}");
ws.config().ui().print(Status::new(
"Running",
&format!("test {package_name} ({script_definition})"),
));
- ops::execute_script(script_definition, args, ws, package.root(), env)
+ ops::execute_script(script_definition, args, ws, package.root(), Some(env))
} else {
debug!("no explicit `test` script found, delegating to scarb-cairo-test");
ws.config().ui().print(Status::new(
@@ -70,7 +73,13 @@ pub fn execute_test_subcommand(
));
let args = args.iter().map(OsString::from).collect::<Vec<_>>();
let script_definition = ScriptDefinition::new("scarb cairo-test".into());
- ops::execute_script(&script_definition, args.as_ref(), ws, package.root(), env)
+ ops::execute_script(
+ &script_definition,
+ args.as_ref(),
+ ws,
+ package.root(),
+ Some(env),
+ )
}
}
diff --git a/scarb/src/subcommands.rs b/scarb/src/subcommands.rs
index 4c9cb7e2..69aea777 100644
--- a/scarb/src/subcommands.rs
+++ b/scarb/src/subcommands.rs
@@ -1,4 +1,5 @@
use crate::core::Config;
+use crate::ops::FeaturesOpts;
use crate::SCARB_ENV;
use camino::Utf8PathBuf;
use std::collections::HashMap;
@@ -39,3 +40,23 @@ pub fn get_env_vars(
}
Ok(HashMap::from_iter(vars))
}
+
+pub trait ToEnv {
+ fn to_env_vars(&self) -> HashMap<String, String>;
+}
+
+impl ToEnv for FeaturesOpts {
+ fn to_env_vars(&self) -> HashMap<String, String> {
+ let mut env = HashMap::new();
+ let features = self.features.join(",");
+ if !features.is_empty() {
+ env.insert("SCARB_FEATURES".into(), features);
+ }
+ env.insert("SCARB_ALL_FEATURES".into(), self.all_features.to_string());
+ env.insert(
+ "SCARB_NO_DEFAULT_FEATURES".into(),
+ self.no_default_features.to_string(),
+ );
+ env
+ }
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment