1use self::commands::{
2 addr2line, build, check, clean, completions, contract_id, init, new, parse_bytecode, plugins,
3 predicate_root, template, test, update,
4};
5use addr2line::Command as Addr2LineCommand;
6use anyhow::anyhow;
7pub use build::Command as BuildCommand;
8pub use check::Command as CheckCommand;
9use clap::{Parser, Subcommand};
10pub use clean::Command as CleanCommand;
11pub use completions::Command as CompletionsCommand;
12pub(crate) use contract_id::Command as ContractIdCommand;
13use forc_tracing::{init_tracing_subscriber, TracingSubscriberOptions};
14use forc_util::ForcResult;
15pub use init::Command as InitCommand;
16pub use new::Command as NewCommand;
17use parse_bytecode::Command as ParseBytecodeCommand;
18pub use plugins::Command as PluginsCommand;
19pub(crate) use predicate_root::Command as PredicateRootCommand;
20use std::str::FromStr;
21pub use template::Command as TemplateCommand;
22pub use test::Command as TestCommand;
23use tracing::metadata::LevelFilter;
24pub use update::Command as UpdateCommand;
25
26mod commands;
27mod plugin;
28pub mod shared;
29
30fn help() -> &'static str {
31 Box::leak(
32 format!(
33 "Examples:\n{}{}{}{}",
34 plugins::examples(),
35 test::examples(),
36 build::examples(),
37 check::examples(),
38 )
39 .trim_end()
40 .to_string()
41 .into_boxed_str(),
42 )
43}
44
45#[derive(Debug, Parser)]
46#[clap(name = "forc", about = "Fuel Orchestrator", version, after_long_help = help())]
47struct Opt {
48 #[clap(subcommand)]
50 command: Forc,
51
52 #[clap(short, long, action = clap::ArgAction::Count, global = true)]
54 verbose: u8,
55
56 #[clap(short, long, global = true)]
58 silent: bool,
59
60 #[clap(short='L', long, global = true, value_parser = LevelFilter::from_str)]
62 log_level: Option<LevelFilter>,
63}
64
65#[derive(Subcommand, Debug)]
66enum Forc {
67 #[clap(name = "addr2line")]
68 Addr2Line(Addr2LineCommand),
69 #[clap(visible_alias = "b")]
70 Build(BuildCommand),
71 Check(CheckCommand),
72 Clean(CleanCommand),
73 Completions(CompletionsCommand),
74 New(NewCommand),
75 Init(InitCommand),
76 ParseBytecode(ParseBytecodeCommand),
77 #[clap(visible_alias = "t")]
78 Test(TestCommand),
79 Update(UpdateCommand),
80 Plugins(PluginsCommand),
81 Template(TemplateCommand),
82 ContractId(ContractIdCommand),
83 PredicateRoot(PredicateRootCommand),
84 #[clap(external_subcommand)]
93 Plugin(Vec<String>),
94}
95
96impl Forc {
97 #[allow(dead_code)]
98 pub fn possible_values() -> Vec<&'static str> {
99 vec![
100 "addr2line",
101 "build",
102 "check",
103 "clean",
104 "completions",
105 "init",
106 "new",
107 "parse-bytecode",
108 "plugins",
109 "test",
110 "update",
111 "template",
112 "contract-id",
113 "predicate-root",
114 ]
115 }
116}
117
118pub async fn run_cli() -> ForcResult<()> {
119 let opt = Opt::parse();
120 let tracing_options = TracingSubscriberOptions {
121 verbosity: Some(opt.verbose),
122 silent: Some(opt.silent),
123 log_level: opt.log_level,
124 ..Default::default()
125 };
126
127 init_tracing_subscriber(tracing_options);
128
129 match opt.command {
130 Forc::Addr2Line(command) => addr2line::exec(command),
131 Forc::Build(command) => build::exec(command),
132 Forc::Check(command) => check::exec(command),
133 Forc::Clean(command) => clean::exec(command),
134 Forc::Completions(command) => completions::exec(command),
135 Forc::Init(command) => init::exec(command),
136 Forc::New(command) => new::exec(command),
137 Forc::ParseBytecode(command) => parse_bytecode::exec(command),
138 Forc::Plugins(command) => plugins::exec(command),
139 Forc::Test(command) => test::exec(command),
140 Forc::Update(command) => update::exec(command),
141 Forc::Template(command) => template::exec(command),
142 Forc::ContractId(command) => contract_id::exec(command),
143 Forc::PredicateRoot(command) => predicate_root::exec(command),
144 Forc::Plugin(args) => {
145 let output = plugin::execute_external_subcommand(&args)?;
146 let code = output
147 .status
148 .code()
149 .ok_or_else(|| anyhow!("plugin exit status unknown"))?;
150 std::process::exit(code);
151 }
152 }
153}