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::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 setup()?;
17
18 let args = Forge::parse();
19 args.global.init()?;
20
21 run_command(args)
22}
23
24pub fn setup() -> Result<()> {
26 utils::common_setup();
27 utils::subscriber();
28
29 Ok(())
30}
31
32pub fn run_command(args: Forge) -> Result<()> {
34 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 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(cmd) => {
80 if cmd.is_watch() {
81 global.block_on(watch::watch_build(cmd))
82 } else {
83 global.block_on(cmd.run()).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::Remove(cmd) => cmd.run(),
101 ForgeSubcommand::Remappings(cmd) => cmd.run(),
102 ForgeSubcommand::Init(cmd) => global.block_on(cmd.run()),
103 ForgeSubcommand::Completions { shell } => {
104 generate(shell, &mut Forge::command(), "forge", &mut std::io::stdout());
105 Ok(())
106 }
107 ForgeSubcommand::Clean { root } => {
108 let config = utils::load_config_with_root(root.as_deref())?;
109 let project = config.project()?;
110 for warning in config.cleanup(&project)? {
111 let _ = sh_warn!("{warning}");
112 }
113 Ok(())
114 }
115 ForgeSubcommand::Snapshot(cmd) => {
116 if cmd.is_watch() {
117 global.block_on(watch::watch_gas_snapshot(cmd))
118 } else {
119 global.block_on(cmd.run())
120 }
121 }
122 ForgeSubcommand::Fmt(cmd) => {
123 if cmd.is_watch() {
124 global.block_on(watch::watch_fmt(cmd))
125 } else {
126 cmd.run()
127 }
128 }
129 ForgeSubcommand::Config(cmd) => cmd.run(),
130 ForgeSubcommand::Flatten(cmd) => cmd.run(),
131 ForgeSubcommand::Inspect(cmd) => cmd.run(),
132 ForgeSubcommand::Tree(cmd) => cmd.run(),
133 ForgeSubcommand::Geiger(cmd) => cmd.run(),
134 ForgeSubcommand::Doc(cmd) => {
135 if cmd.is_watch() {
136 global.block_on(watch::watch_doc(cmd))
137 } else {
138 global.block_on(cmd.run())
139 }
140 }
141 ForgeSubcommand::Selectors { command } => global.block_on(command.run()),
142 ForgeSubcommand::Generate(cmd) => match cmd.sub {
143 GenerateSubcommands::Test(cmd) => cmd.run(),
144 },
145 ForgeSubcommand::Compiler(cmd) => cmd.run(),
146 ForgeSubcommand::Soldeer(cmd) => global.block_on(cmd.run()),
147 ForgeSubcommand::Eip712(cmd) => cmd.run(),
148 ForgeSubcommand::BindJson(cmd) => cmd.run(),
149 ForgeSubcommand::Lint(cmd) => cmd.run(),
150 }
151}
152
153fn block_on_command<Fut>(
154 global: &foundry_cli::opts::GlobalArgs,
155 make_future: impl FnOnce() -> Fut,
156) -> Fut::Output
157where
158 Fut: std::future::Future,
159{
160 global.block_on(make_future())
161}