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