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
12pub 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
27pub fn setup() -> Result<Vec<String>> {
29 let warnings = utils::common_setup();
30 utils::subscriber();
31
32 Ok(warnings)
33}
34
35pub fn run_command(args: Forge) -> Result<()> {
37 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 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}