Skip to main content

forge/
args.rs

1use crate::{
2    cmd::{cache::CacheSubcommands, watch},
3    opts::{Forge, ForgeSubcommand},
4};
5use clap::{CommandFactory, Parser};
6use clap_complete::generate;
7use eyre::Result;
8use foundry_cli::utils;
9use foundry_common::{sh_warn, shell};
10use foundry_evm::inspectors::cheatcodes::{ForgeContext, set_execution_context};
11
12/// Run the `forge` command line interface.
13pub fn run() -> Result<()> {
14    foundry_cli::opts::GlobalArgs::check_markdown_help::<Forge>();
15
16    let warnings = setup()?;
17
18    let args = Forge::parse();
19    args.global.init()?;
20    for warning in warnings {
21        let _ = foundry_common::sh_warn!("{warning}");
22    }
23
24    run_command(args)
25}
26
27/// Setup the global logger and other utilities.
28pub fn setup() -> Result<Vec<String>> {
29    let warnings = utils::common_setup();
30    utils::subscriber();
31
32    Ok(warnings)
33}
34
35/// Run the subcommand.
36pub fn run_command(args: Forge) -> Result<()> {
37    // Set the execution context based on the subcommand.
38    let context = match &args.cmd {
39        ForgeSubcommand::Test(_) | ForgeSubcommand::Fuzz(_) => ForgeContext::Test,
40        ForgeSubcommand::Coverage(_) => ForgeContext::Coverage,
41        ForgeSubcommand::Snapshot(_) => ForgeContext::Snapshot,
42        ForgeSubcommand::Script(cmd) => {
43            if cmd.broadcast {
44                ForgeContext::ScriptBroadcast
45            } else if cmd.resume {
46                ForgeContext::ScriptResume
47            } else {
48                ForgeContext::ScriptDryRun
49            }
50        }
51        _ => ForgeContext::Unknown,
52    };
53    set_execution_context(context);
54
55    let global = &args.global;
56
57    // Run the subcommand.
58    match args.cmd {
59        ForgeSubcommand::Test(cmd) => {
60            if cmd.is_watch() {
61                global.block_on(watch::watch_test(cmd))
62            } else {
63                let silent = cmd.junit || shell::is_json();
64                let outcome = global.block_on(cmd.run())?;
65                outcome.ensure_ok(silent)
66            }
67        }
68        ForgeSubcommand::Fuzz(cmd) => {
69            let silent = cmd.is_junit() || shell::is_json();
70            let outcome = global.block_on(cmd.run())?;
71            outcome.ensure_ok(silent)
72        }
73        ForgeSubcommand::Script(cmd) => block_on_command(global, || cmd.run_script()),
74        ForgeSubcommand::Coverage(cmd) => {
75            if cmd.is_watch() {
76                global.block_on(watch::watch_coverage(cmd))
77            } else {
78                global.block_on(cmd.run())
79            }
80        }
81        ForgeSubcommand::Bind(cmd) => cmd.run(),
82        ForgeSubcommand::Build { args, locked } => {
83            if args.is_watch() {
84                global.block_on(watch::watch_build(args))
85            } else {
86                global.block_on(args.run(locked)).map(drop)
87            }
88        }
89        ForgeSubcommand::VerifyContract(mut args) => {
90            args.print_submission_result_to_stdout = true;
91            global.block_on(args.run())
92        }
93        ForgeSubcommand::VerifyCheck(args) => global.block_on(args.run()),
94        ForgeSubcommand::VerifyBytecode(cmd) => global.block_on(cmd.run()),
95        ForgeSubcommand::Clone(cmd) => global.block_on(cmd.run()),
96        ForgeSubcommand::Cache(cmd) => match cmd.sub {
97            CacheSubcommands::Clean(cmd) => cmd.run(),
98            CacheSubcommands::Ls(cmd) => cmd.run(),
99        },
100        ForgeSubcommand::Create(cmd) => global.block_on(cmd.run()),
101        ForgeSubcommand::Update(cmd) => cmd.run(),
102        ForgeSubcommand::Install(cmd) => global.block_on(cmd.run()),
103        ForgeSubcommand::Reinit(cmd) => cmd.run(),
104        ForgeSubcommand::Remove(cmd) => cmd.run(),
105        ForgeSubcommand::Remappings(cmd) => cmd.run(),
106        ForgeSubcommand::Init(cmd) => global.block_on(cmd.run()),
107        ForgeSubcommand::Completions { shell } => {
108            generate(shell, &mut Forge::command(), "forge", &mut std::io::stdout());
109            Ok(())
110        }
111        ForgeSubcommand::Clean { root } => {
112            let config = utils::load_config_with_root(root.as_deref())?;
113            let project = config.project()?;
114            for warning in config.cleanup(&project)? {
115                let _ = sh_warn!("{warning}");
116            }
117            Ok(())
118        }
119        ForgeSubcommand::Snapshot(cmd) => {
120            if cmd.is_watch() {
121                global.block_on(watch::watch_gas_snapshot(cmd))
122            } else {
123                global.block_on(cmd.run())
124            }
125        }
126        ForgeSubcommand::Fmt(cmd) => {
127            if cmd.is_watch() {
128                global.block_on(watch::watch_fmt(cmd))
129            } else {
130                cmd.run()
131            }
132        }
133        ForgeSubcommand::Config(cmd) => cmd.run(),
134        ForgeSubcommand::Flatten(cmd) => cmd.run(),
135        ForgeSubcommand::Inspect(cmd) => cmd.run(),
136        ForgeSubcommand::Tree(cmd) => cmd.run(),
137        ForgeSubcommand::Geiger(cmd) => global.block_on(cmd.run()),
138        ForgeSubcommand::Doc(cmd) => {
139            if cmd.is_watch() {
140                global.block_on(watch::watch_doc(cmd))
141            } else {
142                global.block_on(cmd.run())
143            }
144        }
145        ForgeSubcommand::Selectors { command } => global.block_on(command.run()),
146        ForgeSubcommand::Compiler(cmd) => cmd.run(),
147        ForgeSubcommand::Soldeer(cmd) => global.block_on(cmd.run()),
148        ForgeSubcommand::Eip712(cmd) => cmd.run(),
149        ForgeSubcommand::BindJson(cmd) => cmd.run(),
150        ForgeSubcommand::Lint(cmd) => global.block_on(cmd.run()),
151        ForgeSubcommand::Lsp(cmd) => global.block_on(crate::cmd::lsp::run(cmd)),
152    }
153}
154
155fn block_on_command<Fut>(
156    global: &foundry_cli::opts::GlobalArgs,
157    make_future: impl FnOnce() -> Fut,
158) -> Fut::Output
159where
160    Fut: std::future::Future,
161{
162    global.block_on(make_future())
163}