From 8b36d4d0b18e9f8658e0c212c26cd3e7a6b0060c Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:59:27 +0100 Subject: [PATCH] feat(`common::shell`): add global verbosity level (`-vvv`) flag replacing `--verbose` (#9273) * remove --verbose, prefer output mode, introduce verbosity level (-vvv) * remove leftover * fix arg * add ability to set verbosity level * fix tests * remove evm args specific verbosity arg in favor of global arg due to Clap limitation * revert test modifications from https://github.com/foundry-rs/foundry/pull/9244 for TestArgs, simply pass + flatten ShellOpts in args * in lieu of a context specific help document the verbosity levels of the EVM as an example * format comment, update tests * fix clippy --- crates/cast/bin/args.rs | 4 +- crates/cast/bin/cmd/run.rs | 8 +- crates/cast/bin/cmd/wallet/mod.rs | 7 +- crates/cast/tests/cli/main.rs | 16 +++- crates/cli/src/opts/shell.rs | 43 +++++------ crates/common/src/evm.rs | 21 ++---- crates/common/src/io/shell.rs | 117 ++++++++++++++++-------------- crates/forge/bin/cmd/compiler.rs | 34 +++------ crates/forge/bin/cmd/config.rs | 10 +-- crates/forge/bin/cmd/test/mod.rs | 48 +++--------- crates/forge/tests/cli/cmd.rs | 16 +++- crates/script/src/lib.rs | 8 +- 12 files changed, 152 insertions(+), 180 deletions(-) diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index 6f17707d4ea89..8bb7f2d544334 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -793,7 +793,7 @@ pub enum CastSubcommand { who: Option, /// Perform a reverse lookup to verify that the name is correct. - #[arg(long, short)] + #[arg(long)] verify: bool, #[command(flatten)] @@ -807,7 +807,7 @@ pub enum CastSubcommand { who: Option
, /// Perform a normal lookup to verify that the address is correct. - #[arg(long, short)] + #[arg(long)] verify: bool, #[command(flatten)] diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 7389d1f35e4d8..880b2fe6f080a 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -8,7 +8,7 @@ use foundry_cli::{ opts::{EtherscanOpts, RpcOpts}, utils::{handle_traces, init_progress, TraceResult}, }; -use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; +use foundry_common::{is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE}; use foundry_compilers::artifacts::EvmVersion; use foundry_config::{ figment::{ @@ -48,10 +48,6 @@ pub struct RunArgs { #[arg(long)] quick: bool, - /// Prints the full address of the contract. - #[arg(long, short)] - verbose: bool, - /// Label addresses in the trace. /// /// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth @@ -252,7 +248,7 @@ impl RunArgs { self.label, self.debug, self.decode_internal, - self.verbose, + shell::verbosity() > 0, ) .await?; diff --git a/crates/cast/bin/cmd/wallet/mod.rs b/crates/cast/bin/cmd/wallet/mod.rs index 8023b8bdff334..b6dea48e15c0b 100644 --- a/crates/cast/bin/cmd/wallet/mod.rs +++ b/crates/cast/bin/cmd/wallet/mod.rs @@ -183,10 +183,6 @@ pub enum WalletSubcommands { #[arg(value_name = "MNEMONIC_INDEX_OR_DERIVATION_PATH")] mnemonic_index_or_derivation_path_override: Option, - /// Verbose mode, print the address and private key. - #[arg(short = 'v', long)] - verbose: bool, - #[command(flatten)] wallet: WalletOpts, }, @@ -462,7 +458,6 @@ flag to set your key via: wallet, mnemonic_override, mnemonic_index_or_derivation_path_override, - verbose, } => { let (index_override, derivation_path_override) = match mnemonic_index_or_derivation_path_override { @@ -485,7 +480,7 @@ flag to set your key via: .await?; match wallet { WalletSigner::Local(wallet) => { - if verbose { + if shell::verbosity() > 0 { sh_println!("Address: {}", wallet.address())?; sh_println!( "Private key: 0x{}", diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 746d9ca1d7d9c..75c57e6a70bbb 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -33,7 +33,7 @@ Options: Display options: --color - Log messages coloring + The color of the log messages Possible values: - auto: Intelligently guess whether to use color output (default) @@ -46,8 +46,18 @@ Display options: -q, --quiet Do not print log messages - --verbose - Use verbose output + -v, --verbosity... + Verbosity level of the log messages. + + Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + + Depending on the context the verbosity levels have different meanings. + + For example, the verbosity levels of the EVM are: + - 2 (-vv): Print logs for all tests. + - 3 (-vvv): Print execution traces for failing tests. + - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + - 5 (-vvvvv): Print execution and setup traces for all tests. Find more information in the book: http://book.getfoundry.sh/reference/cast/cast.html diff --git a/crates/cli/src/opts/shell.rs b/crates/cli/src/opts/shell.rs index fd83b952bef0f..e559cc0f275f5 100644 --- a/crates/cli/src/opts/shell.rs +++ b/crates/cli/src/opts/shell.rs @@ -1,24 +1,27 @@ -use clap::Parser; -use foundry_common::shell::{ColorChoice, OutputFormat, Shell, Verbosity}; +use clap::{ArgAction, Parser}; +use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity}; // note: `verbose` and `quiet` cannot have `short` because of conflicts with multiple commands. /// Global shell options. -#[derive(Clone, Copy, Debug, Parser)] +#[derive(Clone, Copy, Debug, Default, Parser)] pub struct ShellOpts { - /// Use verbose output. - #[clap(long, global = true, conflicts_with = "quiet", help_heading = "Display options")] - pub verbose: bool, + /// Verbosity level of the log messages. + /// + /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + /// + /// Depending on the context the verbosity levels have different meanings. + /// + /// For example, the verbosity levels of the EVM are: + /// - 2 (-vv): Print logs for all tests. + /// - 3 (-vvv): Print execution traces for failing tests. + /// - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + /// - 5 (-vvvvv): Print execution and setup traces for all tests. + #[clap(short, long, global = true, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count, help_heading = "Display options")] + pub verbosity: Verbosity, /// Do not print log messages. - #[clap( - short, - long, - global = true, - alias = "silent", - conflicts_with = "verbose", - help_heading = "Display options" - )] + #[clap(short, long, global = true, alias = "silent", help_heading = "Display options")] pub quiet: bool, /// Format log messages as JSON. @@ -31,18 +34,16 @@ pub struct ShellOpts { )] pub json: bool, - /// Log messages coloring. + /// The color of the log messages. #[clap(long, global = true, value_enum, help_heading = "Display options")] pub color: Option, } impl ShellOpts { pub fn shell(self) -> Shell { - let verbosity = match (self.verbose, self.quiet) { - (true, false) => Verbosity::Verbose, - (false, true) => Verbosity::Quiet, - (false, false) => Verbosity::Normal, - (true, true) => unreachable!(), + let mode = match self.quiet { + true => OutputMode::Quiet, + false => OutputMode::Normal, }; let color = self.json.then_some(ColorChoice::Never).or(self.color).unwrap_or_default(); let format = match self.json { @@ -50,6 +51,6 @@ impl ShellOpts { false => OutputFormat::Text, }; - Shell::new_with(format, color, verbosity) + Shell::new_with(format, mode, color, self.verbosity) } } diff --git a/crates/common/src/evm.rs b/crates/common/src/evm.rs index e738cc6ddce30..3eca0800e0cde 100644 --- a/crates/common/src/evm.rs +++ b/crates/common/src/evm.rs @@ -1,7 +1,7 @@ //! CLI arguments for configuring the EVM settings. use alloy_primitives::{map::HashMap, Address, B256, U256}; -use clap::{ArgAction, Parser}; +use clap::Parser; use eyre::ContextCompat; use foundry_config::{ figment::{ @@ -14,6 +14,8 @@ use foundry_config::{ }; use serde::Serialize; +use crate::shell; + /// Map keyed by breakpoints char to their location (contract address, pc) pub type Breakpoints = HashMap; @@ -101,19 +103,6 @@ pub struct EvmArgs { #[serde(skip)] pub always_use_create_2_factory: bool, - /// Verbosity of the EVM. - /// - /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). - /// - /// Verbosity levels: - /// - 2: Print logs for all tests - /// - 3: Print execution traces for failing tests - /// - 4: Print execution traces for all tests, and setup traces for failing tests - /// - 5: Print execution and setup traces for all tests - #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count)] - #[serde(skip)] - pub verbosity: u8, - /// Sets the number of assumed available compute units per second for this provider /// /// default value: 330 @@ -163,9 +152,9 @@ impl Provider for EvmArgs { let error = InvalidType(value.to_actual(), "map".into()); let mut dict = value.into_dict().ok_or(error)?; - if self.verbosity > 0 { + if shell::verbosity() > 0 { // need to merge that manually otherwise `from_occurrences` does not work - dict.insert("verbosity".to_string(), self.verbosity.into()); + dict.insert("verbosity".to_string(), shell::verbosity().into()); } if self.ffi { diff --git a/crates/common/src/io/shell.rs b/crates/common/src/io/shell.rs index 45d9c2296037a..09a167df94400 100644 --- a/crates/common/src/io/shell.rs +++ b/crates/common/src/io/shell.rs @@ -17,14 +17,19 @@ use std::{ }, }; -/// Returns the currently set verbosity. +/// Returns the currently set verbosity level. pub fn verbosity() -> Verbosity { Shell::get().verbosity() } -/// Returns whether the verbosity level is [`Verbosity::Quiet`]. +/// Set the verbosity level. +pub fn set_verbosity(verbosity: Verbosity) { + Shell::get().set_verbosity(verbosity); +} + +/// Returns whether the output mode is [`OutputMode::Quiet`]. pub fn is_quiet() -> bool { - verbosity().is_quiet() + Shell::get().output_mode().is_quiet() } /// Returns whether the output format is [`OutputFormat::Json`]. @@ -68,11 +73,9 @@ impl TtyWidth { } } -/// The requested verbosity of output. #[derive(Debug, Default, Clone, Copy, PartialEq)] -pub enum Verbosity { - /// All output - Verbose, +/// The requested output mode. +pub enum OutputMode { /// Default output #[default] Normal, @@ -80,20 +83,14 @@ pub enum Verbosity { Quiet, } -impl Verbosity { - /// Returns true if the verbosity level is `Verbose`. - #[inline] - pub fn is_verbose(self) -> bool { - self == Self::Verbose - } - - /// Returns true if the verbosity level is `Normal`. +impl OutputMode { + /// Returns true if the output mode is `Normal`. #[inline] pub fn is_normal(self) -> bool { self == Self::Normal } - /// Returns true if the verbosity level is `Quiet`. + /// Returns true if the output mode is `Quiet`. #[inline] pub fn is_quiet(self) -> bool { self == Self::Quiet @@ -124,6 +121,9 @@ impl OutputFormat { } } +/// The verbosity level. +pub type Verbosity = u8; + /// An abstraction around console output that remembers preferences for output /// verbosity and color. pub struct Shell { @@ -134,7 +134,10 @@ pub struct Shell { /// The format to use for message output. output_format: OutputFormat, - /// How verbose messages should be. + /// The verbosity mode to use for message output. + output_mode: OutputMode, + + /// The verbosity level to use for message output. verbosity: Verbosity, /// Flag that indicates the current line needs to be cleared before @@ -145,6 +148,8 @@ pub struct Shell { impl fmt::Debug for Shell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("Shell"); + s.field("output_format", &self.output_format); + s.field("output_mode", &self.output_mode); s.field("verbosity", &self.verbosity); if let ShellOut::Stream { color_choice, .. } = self.output { s.field("color_choice", &color_choice); @@ -190,12 +195,22 @@ impl Shell { /// output. #[inline] pub fn new() -> Self { - Self::new_with(OutputFormat::Text, ColorChoice::Auto, Verbosity::Verbose) + Self::new_with( + OutputFormat::Text, + OutputMode::Normal, + ColorChoice::Auto, + Verbosity::default(), + ) } /// Creates a new shell with the given color choice and verbosity. #[inline] - pub fn new_with(format: OutputFormat, color: ColorChoice, verbosity: Verbosity) -> Self { + pub fn new_with( + format: OutputFormat, + mode: OutputMode, + color: ColorChoice, + verbosity: Verbosity, + ) -> Self { Self { output: ShellOut::Stream { stdout: AutoStream::new(std::io::stdout(), color.to_anstream_color_choice()), @@ -204,6 +219,7 @@ impl Shell { stderr_tty: std::io::stderr().is_terminal(), }, output_format: format, + output_mode: mode, verbosity, needs_clear: AtomicBool::new(false), } @@ -215,7 +231,8 @@ impl Shell { Self { output: ShellOut::Empty(std::io::empty()), output_format: OutputFormat::Text, - verbosity: Verbosity::Quiet, + output_mode: OutputMode::Quiet, + verbosity: 0, needs_clear: AtomicBool::new(false), } } @@ -266,15 +283,27 @@ impl Shell { } } - /// Gets the verbosity of the shell. + /// Gets the output format of the shell. + #[inline] + pub fn output_format(&self) -> OutputFormat { + self.output_format + } + + /// Gets the output mode of the shell. + #[inline] + pub fn output_mode(&self) -> OutputMode { + self.output_mode + } + + /// Gets the verbosity of the shell when [`OutputMode::Normal`] is set. #[inline] pub fn verbosity(&self) -> Verbosity { self.verbosity } - /// Gets the output format of the shell. - pub fn output_format(&self) -> OutputFormat { - self.output_format + /// Sets the verbosity level. + pub fn set_verbosity(&mut self, verbosity: Verbosity) { + self.verbosity = verbosity; } /// Gets the current color choice. @@ -338,24 +367,6 @@ impl Shell { } } - /// Runs the callback only if we are in verbose mode. - #[inline] - pub fn verbose(&mut self, mut callback: impl FnMut(&mut Self) -> Result<()>) -> Result<()> { - match self.verbosity { - Verbosity::Verbose => callback(self), - _ => Ok(()), - } - } - - /// Runs the callback if we are not in verbose mode. - #[inline] - pub fn concise(&mut self, mut callback: impl FnMut(&mut Self) -> Result<()>) -> Result<()> { - match self.verbosity { - Verbosity::Verbose => Ok(()), - _ => callback(self), - } - } - /// Prints a red 'error' message. Use the [`sh_err!`] macro instead. /// This will render a message in [ERROR] style with a bold `Error: ` prefix. /// @@ -370,8 +381,8 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn warn(&mut self, message: impl fmt::Display) -> Result<()> { - match self.verbosity { - Verbosity::Quiet => Ok(()), + match self.output_mode { + OutputMode::Quiet => Ok(()), _ => self.print(&"Warning", &WARN, Some(&message), false), } } @@ -387,10 +398,9 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn print_out(&mut self, fragment: impl fmt::Display) -> Result<()> { - if self.verbosity == Verbosity::Quiet { - Ok(()) - } else { - self.write_stdout(fragment, &Style::new()) + match self.output_mode { + OutputMode::Quiet => Ok(()), + _ => self.write_stdout(fragment, &Style::new()), } } @@ -405,10 +415,9 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn print_err(&mut self, fragment: impl fmt::Display) -> Result<()> { - if self.verbosity == Verbosity::Quiet { - Ok(()) - } else { - self.write_stderr(fragment, &Style::new()) + match self.output_mode { + OutputMode::Quiet => Ok(()), + _ => self.write_stderr(fragment, &Style::new()), } } @@ -421,8 +430,8 @@ impl Shell { message: Option<&dyn fmt::Display>, justified: bool, ) -> Result<()> { - match self.verbosity { - Verbosity::Quiet => Ok(()), + match self.output_mode { + OutputMode::Quiet => Ok(()), _ => { self.maybe_err_erase_line(); self.output.message_stderr(status, style, message, justified) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 0b0ec171b4c79..a7115c4876b8f 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -1,5 +1,6 @@ -use clap::{ArgAction, Parser, Subcommand, ValueHint}; +use clap::{Parser, Subcommand, ValueHint}; use eyre::Result; +use foundry_common::shell; use foundry_compilers::{artifacts::EvmVersion, Graph}; use foundry_config::Config; use semver::Version; @@ -51,26 +52,11 @@ pub struct ResolveArgs { /// Skip files that match the given regex pattern. #[arg(long, short, value_name = "REGEX")] skip: Option, - - /// Verbosity of the output. - /// - /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). - /// - /// Verbosity levels: - /// - 0: Print compiler versions. - /// - 1: Print compiler version and source paths. - /// - 2: Print compiler version, source paths and max supported EVM version of the compiler. - #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count, help_heading = "Display options")] - pub verbosity: u8, - - /// Print as JSON. - #[arg(long, short, help_heading = "Display options")] - json: bool, } impl ResolveArgs { pub fn run(self) -> Result<()> { - let Self { root, skip, verbosity, json } = self; + let Self { root, skip } = self; let root = root.unwrap_or_else(|| PathBuf::from(".")); let config = Config::load_with_root(&root); @@ -110,7 +96,7 @@ impl ResolveArgs { }) .collect(); - let evm_version = if verbosity > 1 { + let evm_version = if shell::verbosity() > 1 { Some( EvmVersion::default() .normalize_version_solc(version) @@ -132,7 +118,7 @@ impl ResolveArgs { if !versions_with_paths.is_empty() { // Clear paths if verbosity is 0, performed only after filtering to avoid being // skipped. - if verbosity == 0 { + if shell::verbosity() == 0 { versions_with_paths.iter_mut().for_each(|version| version.paths.clear()); } @@ -140,20 +126,20 @@ impl ResolveArgs { } } - if json { + if shell::is_json() { sh_println!("{}", serde_json::to_string(&output)?)?; return Ok(()); } for (language, compilers) in &output { - match verbosity { + match shell::verbosity() { 0 => sh_println!("{language}:")?, _ => sh_println!("{language}:\n")?, } for resolved_compiler in compilers { let version = &resolved_compiler.version; - match verbosity { + match shell::verbosity() { 0 => sh_println!("- {version}")?, _ => { if let Some(evm) = &resolved_compiler.evm_version { @@ -164,7 +150,7 @@ impl ResolveArgs { } } - if verbosity > 0 { + if shell::verbosity() > 0 { let paths = &resolved_compiler.paths; for (idx, path) in paths.iter().enumerate() { if idx == paths.len() - 1 { @@ -176,7 +162,7 @@ impl ResolveArgs { } } - if verbosity == 0 { + if shell::verbosity() == 0 { sh_println!()? } } diff --git a/crates/forge/bin/cmd/config.rs b/crates/forge/bin/cmd/config.rs index 652c5a10fed3b..36f4d1731f4b1 100644 --- a/crates/forge/bin/cmd/config.rs +++ b/crates/forge/bin/cmd/config.rs @@ -2,7 +2,7 @@ use super::build::BuildArgs; use clap::Parser; use eyre::Result; use foundry_cli::utils::LoadConfig; -use foundry_common::evm::EvmArgs; +use foundry_common::{evm::EvmArgs, shell}; use foundry_config::fix::fix_tomls; foundry_config::impl_figment_convert!(ConfigArgs, opts, evm_opts); @@ -14,10 +14,6 @@ pub struct ConfigArgs { #[arg(long)] basic: bool, - /// Print currently set config values as JSON. - #[arg(long)] - json: bool, - /// Attempt to fix any configuration warnings. #[arg(long)] fix: bool, @@ -46,12 +42,12 @@ impl ConfigArgs { let s = if self.basic { let config = config.into_basic(); - if self.json { + if shell::is_json() { serde_json::to_string_pretty(&config)? } else { config.to_string_pretty()? } - } else if self.json { + } else if shell::is_json() { serde_json::to_string_pretty(&config)? } else { config.to_string_pretty()? diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 091599305dd86..77ae5d2631f66 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -17,7 +17,7 @@ use forge::{ MultiContractRunner, MultiContractRunnerBuilder, TestFilter, TestOptions, TestOptionsBuilder, }; use foundry_cli::{ - opts::CoreBuildArgs, + opts::{CoreBuildArgs, ShellOpts}, utils::{self, LoadConfig}, }; use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell, TestFunctionExt}; @@ -178,6 +178,9 @@ pub struct TestArgs { /// Print detailed test summary table. #[arg(long, help_heading = "Display options", requires = "summary")] pub detailed: bool, + + #[command(flatten)] + shell: ShellOpts, } impl TestArgs { @@ -993,56 +996,34 @@ fn junit_xml_report(results: &BTreeMap, verbosity: u8) -> R #[cfg(test)] mod tests { - use crate::opts::{Forge, ForgeSubcommand}; - use super::*; use foundry_config::{Chain, InvariantConfig}; use foundry_test_utils::forgetest_async; #[test] fn watch_parse() { - let args = match Forge::parse_from(["foundry-cli", "test", "-vw"]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = TestArgs::parse_from(["foundry-cli", "-vw"]); assert!(args.watch.watch.is_some()); } #[test] fn fuzz_seed() { - let args = match Forge::parse_from(["foundry-cli", "test", "--fuzz-seed", "0x10"]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = TestArgs::parse_from(["foundry-cli", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } // #[test] fn fuzz_seed_exists() { - let args = match Forge::parse_from([ - "foundry-cli", - "test", - "-vvv", - "--gas-report", - "--fuzz-seed", - "0x10", - ]) - .cmd - { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = + TestArgs::parse_from(["foundry-cli", "-vvv", "--gas-report", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } #[test] fn extract_chain() { let test = |arg: &str, expected: Chain| { - let args = match Forge::parse_from(["foundry-cli", "test", arg]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args = TestArgs::parse_from(["foundry-cli", arg]); assert_eq!(args.evm_opts.env.chain, Some(expected)); let (config, evm_opts) = args.load_config_and_evm_opts().unwrap(); assert_eq!(config.chain, Some(expected)); @@ -1096,19 +1077,12 @@ contract FooBarTest is DSTest { ) .unwrap(); - let args = match Forge::parse_from([ + let args = TestArgs::parse_from([ "foundry-cli", - "test", "--gas-report", "--root", &prj.root().to_string_lossy(), - ]) - .cmd - { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; - + ]); let outcome = args.run().await.unwrap(); let gas_report = outcome.gas_report.unwrap(); diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 89335a492d01e..9e9e1fda1c1fb 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -38,7 +38,7 @@ Options: Display options: --color - Log messages coloring + The color of the log messages Possible values: - auto: Intelligently guess whether to use color output (default) @@ -51,8 +51,18 @@ Display options: -q, --quiet Do not print log messages - --verbose - Use verbose output + -v, --verbosity... + Verbosity level of the log messages. + + Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + + Depending on the context the verbosity levels have different meanings. + + For example, the verbosity levels of the EVM are: + - 2 (-vv): Print logs for all tests. + - 3 (-vvv): Print execution traces for failing tests. + - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + - 5 (-vvvvv): Print execution and setup traces for all tests. Find more information in the book: http://book.getfoundry.sh/reference/forge/forge.html diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 707399d6305dc..180a09647d4ff 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -26,7 +26,10 @@ use dialoguer::Confirm; use eyre::{ContextCompat, Result}; use forge_script_sequence::{AdditionalContract, NestedValue}; use forge_verify::RetryArgs; -use foundry_cli::{opts::CoreBuildArgs, utils::LoadConfig}; +use foundry_cli::{ + opts::{CoreBuildArgs, ShellOpts}, + utils::LoadConfig, +}; use foundry_common::{ abi::{encode_function_args, get_func}, evm::{Breakpoints, EvmArgs}, @@ -210,6 +213,9 @@ pub struct ScriptArgs { #[command(flatten)] pub retry: RetryArgs, + + #[clap(flatten)] + pub shell: ShellOpts, } impl ScriptArgs {