1// Used to simulate a fairly large number of subcommands
2//
3// CLI used is from rustup 408ed84f0e50511ed44a405dd91365e5da588790
4
5use clap::{Arg, ArgAction, ArgGroup, Command};
6use criterion::{criterion_group, criterion_main, Criterion};
7
8pub fn build_rustup(c: &mut Criterion) {
9    c.bench_function("build_rustup", |b| b.iter(build_cli));
10}
11
12pub fn parse_rustup(c: &mut Criterion) {
13    c.bench_function("parse_rustup", |b| {
14        b.iter(|| build_cli().get_matches_from(vec![""]))
15    });
16}
17
18pub fn parse_rustup_with_sc(c: &mut Criterion) {
19    c.bench_function("parse_rustup_with_sc", |b| {
20        b.iter(|| build_cli().get_matches_from(vec!["rustup override add stable"]))
21    });
22}
23
24fn build_cli() -> Command {
25    Command::new("rustup")
26        .version("0.9.0") // Simulating
27        .about("The Rust toolchain installer")
28        .after_help(RUSTUP_HELP)
29        .arg(
30            Arg::new("verbose")
31                .help("Enable verbose output")
32                .short('v')
33                .long("verbose")
34                .action(ArgAction::SetTrue),
35        )
36        .subcommand(
37            Command::new("show")
38                .about("Show the active and installed toolchains")
39                .after_help(SHOW_HELP),
40        )
41        .subcommand(
42            Command::new("install")
43                .about("Update Rust toolchains")
44                .after_help(TOOLCHAIN_INSTALL_HELP)
45                .hide(true) // synonym for 'toolchain install'
46                .arg(Arg::new("toolchain").required(true)),
47        )
48        .subcommand(
49            Command::new("update")
50                .about("Update Rust toolchains")
51                .after_help(UPDATE_HELP)
52                .arg(Arg::new("toolchain").required(true))
53                .arg(
54                    Arg::new("no-self-update")
55                        .help("Don't perform self update when running the `rustup` command")
56                        .long("no-self-update")
57                        .action(ArgAction::SetTrue)
58                        .hide(true),
59                ),
60        )
61        .subcommand(
62            Command::new("default")
63                .about("Set the default toolchain")
64                .after_help(DEFAULT_HELP)
65                .arg(Arg::new("toolchain").required(true)),
66        )
67        .subcommand(
68            Command::new("toolchain")
69                .about("Modify or query the installed toolchains")
70                .after_help(TOOLCHAIN_HELP)
71                .subcommand(Command::new("list").about("List installed toolchains"))
72                .subcommand(
73                    Command::new("install")
74                        .about("Install or update a given toolchain")
75                        .arg(Arg::new("toolchain").required(true)),
76                )
77                .subcommand(
78                    Command::new("uninstall")
79                        .about("Uninstall a toolchain")
80                        .arg(Arg::new("toolchain").required(true)),
81                )
82                .subcommand(
83                    Command::new("link")
84                        .about("Create a custom toolchain by symlinking to a directory")
85                        .arg(Arg::new("toolchain").required(true))
86                        .arg(Arg::new("path").required(true)),
87                )
88                .subcommand(
89                    Command::new("update")
90                        .hide(true) // synonym for 'install'
91                        .arg(Arg::new("toolchain").required(true)),
92                )
93                .subcommand(
94                    Command::new("add")
95                        .hide(true) // synonym for 'install'
96                        .arg(Arg::new("toolchain").required(true)),
97                )
98                .subcommand(
99                    Command::new("remove")
100                        .hide(true) // synonym for 'uninstall'
101                        .arg(Arg::new("toolchain").required(true)),
102                ),
103        )
104        .subcommand(
105            Command::new("target")
106                .about("Modify a toolchain's supported targets")
107                .subcommand(
108                    Command::new("list")
109                        .about("List installed and available targets")
110                        .arg(
111                            Arg::new("toolchain")
112                                .long("toolchain")
113                                .action(ArgAction::Set),
114                        ),
115                )
116                .subcommand(
117                    Command::new("add")
118                        .about("Add a target to a Rust toolchain")
119                        .arg(Arg::new("target").required(true))
120                        .arg(
121                            Arg::new("toolchain")
122                                .long("toolchain")
123                                .action(ArgAction::Set),
124                        ),
125                )
126                .subcommand(
127                    Command::new("remove")
128                        .about("Remove a target  from a Rust toolchain")
129                        .arg(Arg::new("target").required(true))
130                        .arg(
131                            Arg::new("toolchain")
132                                .long("toolchain")
133                                .action(ArgAction::Set),
134                        ),
135                )
136                .subcommand(
137                    Command::new("install")
138                        .hide(true) // synonym for 'add'
139                        .arg(Arg::new("target").required(true))
140                        .arg(
141                            Arg::new("toolchain")
142                                .long("toolchain")
143                                .action(ArgAction::Set),
144                        ),
145                )
146                .subcommand(
147                    Command::new("uninstall")
148                        .hide(true) // synonym for 'remove'
149                        .arg(Arg::new("target").required(true))
150                        .arg(
151                            Arg::new("toolchain")
152                                .long("toolchain")
153                                .action(ArgAction::Set),
154                        ),
155                ),
156        )
157        .subcommand(
158            Command::new("component")
159                .about("Modify a toolchain's installed components")
160                .subcommand(
161                    Command::new("list")
162                        .about("List installed and available components")
163                        .arg(
164                            Arg::new("toolchain")
165                                .long("toolchain")
166                                .action(ArgAction::Set),
167                        ),
168                )
169                .subcommand(
170                    Command::new("add")
171                        .about("Add a component to a Rust toolchain")
172                        .arg(Arg::new("component").required(true))
173                        .arg(
174                            Arg::new("toolchain")
175                                .long("toolchain")
176                                .action(ArgAction::Set),
177                        )
178                        .arg(Arg::new("target").long("target").action(ArgAction::Set)),
179                )
180                .subcommand(
181                    Command::new("remove")
182                        .about("Remove a component from a Rust toolchain")
183                        .arg(Arg::new("component").required(true))
184                        .arg(
185                            Arg::new("toolchain")
186                                .long("toolchain")
187                                .action(ArgAction::Set),
188                        )
189                        .arg(Arg::new("target").long("target").action(ArgAction::Set)),
190                ),
191        )
192        .subcommand(
193            Command::new("override")
194                .about("Modify directory toolchain overrides")
195                .after_help(OVERRIDE_HELP)
196                .subcommand(Command::new("list").about("List directory toolchain overrides"))
197                .subcommand(
198                    Command::new("set")
199                        .about("Set the override toolchain for a directory")
200                        .arg(Arg::new("toolchain").required(true)),
201                )
202                .subcommand(
203                    Command::new("unset")
204                        .about("Remove the override toolchain for a directory")
205                        .after_help(OVERRIDE_UNSET_HELP)
206                        .arg(
207                            Arg::new("path")
208                                .long("path")
209                                .action(ArgAction::Set)
210                                .help("Path to the directory"),
211                        )
212                        .arg(
213                            Arg::new("nonexistent")
214                                .long("nonexistent")
215                                .action(ArgAction::SetTrue)
216                                .help("Remove override toolchain for all nonexistent directories"),
217                        ),
218                )
219                .subcommand(
220                    Command::new("add")
221                        .hide(true) // synonym for 'set'
222                        .arg(Arg::new("toolchain").required(true)),
223                )
224                .subcommand(
225                    Command::new("remove")
226                        .hide(true) // synonym for 'unset'
227                        .about("Remove the override toolchain for a directory")
228                        .arg(Arg::new("path").long("path").action(ArgAction::Set))
229                        .arg(
230                            Arg::new("nonexistent")
231                                .long("nonexistent")
232                                .action(ArgAction::SetTrue)
233                                .help("Remove override toolchain for all nonexistent directories"),
234                        ),
235                ),
236        )
237        .subcommand(
238            Command::new("run")
239                .about("Run a command with an environment configured for a given toolchain")
240                .after_help(RUN_HELP)
241                .arg(Arg::new("toolchain").required(true))
242                .arg(
243                    Arg::new("command")
244                        .required(true)
245                        .num_args(1..)
246                        .trailing_var_arg(true),
247                ),
248        )
249        .subcommand(
250            Command::new("which")
251                .about("Display which binary will be run for a given command")
252                .arg(Arg::new("command").required(true)),
253        )
254        .subcommand(
255            Command::new("doc")
256                .about("Open the documentation for the current toolchain")
257                .after_help(DOC_HELP)
258                .arg(
259                    Arg::new("book")
260                        .long("book")
261                        .action(ArgAction::SetTrue)
262                        .help("The Rust Programming Language book"),
263                )
264                .arg(
265                    Arg::new("std")
266                        .long("std")
267                        .action(ArgAction::SetTrue)
268                        .help("Standard library API documentation"),
269                )
270                .group(ArgGroup::new("page").args(["book", "std"])),
271        )
272        .subcommand(
273            Command::new("man")
274                .about("View the man page for a given command")
275                .arg(Arg::new("command").required(true))
276                .arg(
277                    Arg::new("toolchain")
278                        .long("toolchain")
279                        .action(ArgAction::Set),
280                ),
281        )
282        .subcommand(
283            Command::new("self")
284                .about("Modify the rustup installation")
285                .subcommand(Command::new("update").about("Download and install updates to rustup"))
286                .subcommand(
287                    Command::new("uninstall")
288                        .about("Uninstall rustup.")
289                        .arg(Arg::new("no-prompt").short('y').action(ArgAction::SetTrue)),
290                )
291                .subcommand(
292                    Command::new("upgrade-data").about("Upgrade the internal data format."),
293                ),
294        )
295        .subcommand(
296            Command::new("telemetry")
297                .about("rustup telemetry commands")
298                .hide(true)
299                .subcommand(Command::new("enable").about("Enable rustup telemetry"))
300                .subcommand(Command::new("disable").about("Disable rustup telemetry"))
301                .subcommand(Command::new("analyze").about("Analyze stored telemetry")),
302        )
303        .subcommand(
304            Command::new("set")
305                .about("Alter rustup settings")
306                .subcommand(
307                    Command::new("default-host")
308                        .about("The triple used to identify toolchains when not specified")
309                        .arg(Arg::new("host_triple").required(true)),
310                ),
311        )
312}
313
314static RUSTUP_HELP: &str = r"
315rustup installs The Rust Programming Language from the official
316release channels, enabling you to easily switch between stable, beta,
317and nightly compilers and keep them updated. It makes cross-compiling
318simpler with binary builds of the standard library for common platforms.
319
320If you are new to Rust consider running `rustup doc --book`
321to learn Rust.";
322
323static SHOW_HELP: &str = r"
324Shows the name of the active toolchain and the version of `rustc`.
325
326If the active toolchain has installed support for additional
327compilation targets, then they are listed as well.
328
329If there are multiple toolchains installed then all installed
330toolchains are listed as well.";
331
332static UPDATE_HELP: &str = r"
333With no toolchain specified, the `update` command updates each of the
334installed toolchains from the official release channels, then updates
335rustup itself.
336
337If given a toolchain argument then `update` updates that toolchain,
338the same as `rustup toolchain install`.
339
340'toolchain' specifies a toolchain name, such as 'stable', 'nightly',
341or '1.8.0'. For more information see `rustup help toolchain`.";
342
343static TOOLCHAIN_INSTALL_HELP: &str = r"
344Installs a specific rust toolchain.
345
346The 'install' command is an alias for 'rustup update <toolchain>'.
347
348'toolchain' specifies a toolchain name, such as 'stable', 'nightly',
349or '1.8.0'. For more information see `rustup help toolchain`.";
350
351static DEFAULT_HELP: &str = r"
352Sets the default toolchain to the one specified. If the toolchain is
353not already installed then it is installed first.";
354
355static TOOLCHAIN_HELP: &str = r"
356Many `rustup` commands deal with *toolchains*, a single installation
357of the Rust compiler. `rustup` supports multiple types of
358toolchains. The most basic track the official release channels:
359'stable', 'beta' and 'nightly'; but `rustup` can also install
360toolchains from the official archives, for alternate host platforms,
361and from local builds.
362
363Standard release channel toolchain names have the following form:
364
365    <channel>[-<date>][-<host>]
366
367    <channel>       = stable|beta|nightly|<version>
368    <date>          = YYYY-MM-DD
369    <host>          = <target-triple>
370
371'channel' is either a named release channel or an explicit version
372number, such as '1.8.0'. Channel names can be optionally appended with
373an archive date, as in 'nightly-2014-12-18', in which case the
374toolchain is downloaded from the archive for that date.
375
376Finally, the host may be specified as a target triple. This is most
377useful for installing a 32-bit compiler on a 64-bit platform, or for
378installing the [MSVC-based toolchain] on Windows. For example:
379
380    rustup toolchain install stable-x86_64-pc-windows-msvc
381
382For convenience, elements of the target triple that are omitted will be
383inferred, so the above could be written:
384
385    $ rustup default stable-msvc
386
387Toolchain names that don't name a channel instead can be used to name
388custom toolchains with the `rustup toolchain link` command.";
389
390static OVERRIDE_HELP: &str = r"
391Overrides configure rustup to use a specific toolchain when
392running in a specific directory.
393
394Directories can be assigned their own Rust toolchain with
395`rustup override`. When a directory has an override then
396any time `rustc` or `cargo` is run inside that directory,
397or one of its child directories, the override toolchain
398will be invoked.
399
400To pin to a specific nightly:
401
402    rustup override set nightly-2014-12-18
403
404Or a specific stable release:
405
406    rustup override set 1.0.0
407
408To see the active toolchain use `rustup show`. To remove the override
409and use the default toolchain again, `rustup override unset`.";
410
411static OVERRIDE_UNSET_HELP: &str = r"
412If `--path` argument is present, removes the override toolchain for
413the specified directory. If `--nonexistent` argument is present, removes
414the override toolchain for all nonexistent directories. Otherwise,
415removes the override toolchain for the current directory.";
416
417static RUN_HELP: &str = r"
418Configures an environment to use the given toolchain and then runs
419the specified program. The command may be any program, not just
420rustc or cargo. This can be used for testing arbitrary toolchains
421without setting an override.
422
423Commands explicitly proxied by `rustup` (such as `rustc` and `cargo`)
424also have a shorthand for this available. The toolchain can be set by
425using `+toolchain` as the first argument. These are equivalent:
426
427    cargo +nightly build
428
429    rustup run nightly cargo build";
430
431static DOC_HELP: &str = r"
432Opens the documentation for the currently active toolchain with the
433default browser.
434
435By default, it opens the documentation index. Use the various flags to
436open specific pieces of documentation.";
437
438criterion_group!(benches, build_rustup, parse_rustup, parse_rustup_with_sc);
439
440criterion_main!(benches);
441