flux_bin/
cargo_flux_opts.rs1use std::{path::Path, process::Command};
2
3use cargo_metadata::{MetadataCommand, camino::Utf8PathBuf};
4
5use crate::{cargo_style, utils::get_version};
6
7#[derive(clap::Parser)]
8#[command(name = "cargo")]
9#[command(bin_name = "cargo")]
10#[command(styles = cargo_style::CLAP_STYLING)]
11pub enum Cli {
12 Flux {
14 #[command(flatten)]
15 check_opts: CheckOpts,
16
17 #[command(subcommand)]
18 command: Option<CargoFluxCommand>,
19 },
20}
21
22#[derive(clap::Subcommand)]
23#[command(version = get_version())]
24pub enum CargoFluxCommand {
25 Check(CheckOpts),
28 Clean(CleanOpts),
30}
31
32impl CargoFluxCommand {
33 pub fn forward_args(&self, cmd: &mut Command, config_file: &Path) {
35 match self {
36 CargoFluxCommand::Check(check_opts) => {
37 cmd.arg("check");
38 check_opts.forward_args(cmd);
39 }
40 CargoFluxCommand::Clean(clean_opts) => {
41 cmd.arg("clean");
42 clean_opts.forward_args(cmd);
43 }
44 }
45 cmd.args(["--profile", "flux"]);
46 cmd.args(["--config".as_ref(), config_file.as_os_str()]);
47 }
48
49 pub fn cargo_subcommand(&self) -> &'static str {
51 match self {
52 CargoFluxCommand::Clean(_) => "clean",
53 CargoFluxCommand::Check(_) => "check",
54 }
55 }
56
57 pub fn metadata(&self) -> MetadataCommand {
58 let mut meta = cargo_metadata::MetadataCommand::new();
59 match self {
60 CargoFluxCommand::Check(check_options) => {
61 check_options.forward_to_metadata(&mut meta);
62 }
63 CargoFluxCommand::Clean(clean_options) => {
64 clean_options.forward_to_metadata(&mut meta);
65 }
66 }
67 meta
68 }
69}
70
71#[derive(clap::Args)]
72pub struct CheckOpts {
73 #[arg(long, value_name = "FMT")]
75 message_format: Option<String>,
76
77 #[command(flatten)]
78 workspace: Workspace,
79 #[command(flatten)]
80 features: Features,
81 #[command(flatten)]
82 manifest: ManifestOptions,
83}
84
85impl CheckOpts {
86 fn forward_args(&self, cmd: &mut Command) {
87 let CheckOpts { message_format, workspace, features, manifest } = self;
88 if let Some(message_format) = &message_format {
89 cmd.args(["--message-format", message_format]);
90 }
91 workspace.forward_args(cmd);
92 features.forward_args(cmd);
93 manifest.forward_args(cmd);
94 }
95
96 fn forward_to_metadata(&self, meta: &mut MetadataCommand) {
97 let CheckOpts { message_format: _, workspace: _, features, manifest } = self;
98 features.forward_to_metadata(meta);
99 manifest.forward_to_metadata(meta);
100 }
101}
102
103#[derive(clap::Args)]
104pub struct CleanOpts {
105 #[command(flatten, next_help_heading = "Package Selection")]
106 package: Package,
107 #[command(flatten)]
108 features: Features,
109 #[command(flatten)]
110 manifest: ManifestOptions,
111}
112
113impl CleanOpts {
114 fn forward_args(&self, cmd: &mut Command) {
115 let CleanOpts { package, features, manifest } = self;
116 package.forward_args(cmd);
117 features.forward_args(cmd);
118 manifest.forward_args(cmd);
119 }
120
121 fn forward_to_metadata(&self, meta: &mut MetadataCommand) {
122 let CleanOpts { package: _, features, manifest } = self;
123 features.forward_to_metadata(meta);
124 manifest.forward_to_metadata(meta);
125 }
126}
127
128#[derive(Debug, clap::Args)]
129#[command(about = None, long_about = None, next_help_heading = "Package Selection")]
130pub struct Workspace {
131 #[command(flatten)]
132 pub package: Package,
133
134 #[arg(long)]
135 pub workspace: bool,
137
138 #[arg(long, value_name = "SPEC")]
139 pub exclude: Vec<String>,
141}
142
143impl Workspace {
144 fn forward_args(&self, cmd: &mut Command) {
145 let Workspace { package, workspace, exclude } = self;
146 package.forward_args(cmd);
147 if *workspace {
148 cmd.arg("--workspace");
149 }
150 if !exclude.is_empty() {
151 cmd.args(exclude.iter().flat_map(|package| ["--exclude", package]));
152 }
153 }
154}
155
156#[derive(Debug, clap::Args)]
157#[command(about = None, long_about = None)]
158pub struct Package {
159 #[arg(short, long, value_name = "SPEC")]
160 pub package: Vec<String>,
162}
163
164impl Package {
165 fn forward_args(&self, cmd: &mut Command) {
166 let Package { package } = self;
167 if !package.is_empty() {
168 cmd.args(package.iter().flat_map(|package| ["--package", package]));
169 }
170 }
171}
172
173#[derive(Default, Clone, Debug, PartialEq, Eq, clap::Args)]
174#[command(about = None, long_about = None, next_help_heading = "Feature Selection")]
175pub struct Features {
176 #[arg(short = 'F', long, value_delimiter = ' ')]
177 pub features: Vec<String>,
179 #[arg(long)]
180 pub all_features: bool,
182 #[arg(long)]
183 pub no_default_features: bool,
185}
186
187impl Features {
188 fn forward_args(&self, cmd: &mut Command) {
189 let Features { features, all_features, no_default_features } = self;
190 if !features.is_empty() {
191 cmd.args(features.iter().flat_map(|feature| ["--features", feature]));
192 }
193 if *all_features {
194 cmd.arg("--all-features");
195 }
196 if *no_default_features {
197 cmd.arg("--no-default-features");
198 }
199 }
200
201 fn forward_to_metadata(&self, meta: &mut MetadataCommand) {
202 let Features { features, all_features, no_default_features } = self;
203 if *all_features {
204 meta.features(cargo_metadata::CargoOpt::AllFeatures);
205 }
206 if *no_default_features {
207 meta.features(cargo_metadata::CargoOpt::NoDefaultFeatures);
208 }
209 if !features.is_empty() {
210 meta.features(cargo_metadata::CargoOpt::SomeFeatures(features.clone()));
211 }
212 }
213}
214
215#[derive(Debug, clap::Args)]
216#[command(next_help_heading = "Manifest Options")]
217pub struct ManifestOptions {
218 #[arg(long, name = "PATH")]
219 manifest_path: Option<Utf8PathBuf>,
221 #[arg(long)]
223 offline: bool,
224}
225
226impl ManifestOptions {
227 fn forward_args(&self, cmd: &mut Command) {
228 let ManifestOptions { manifest_path, offline } = self;
229 if let Some(manifest_path) = &manifest_path {
230 cmd.args(["--manifest-path", manifest_path.as_str()]);
231 }
232 if *offline {
233 cmd.arg("--offline");
234 }
235 }
236
237 fn forward_to_metadata(&self, meta: &mut MetadataCommand) {
238 let ManifestOptions { manifest_path, offline: _ } = self;
240 if let Some(manifest_path) = &manifest_path {
241 meta.manifest_path(manifest_path);
242 }
243 }
244}