Skip to main content

forge/
args.rs

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