From efbd2a508c3acd1dcf722808f118341e48bea9cc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 30 Jul 2023 22:58:03 +0200 Subject: [PATCH] port to hand-rolled parser, since clap doesn't behave just the right way --- src/tools/miri/miri-script/Cargo.lock | 299 --------------------- src/tools/miri/miri-script/Cargo.toml | 1 - src/tools/miri/miri-script/src/commands.rs | 20 +- src/tools/miri/miri-script/src/main.rs | 184 +++++++++---- 4 files changed, 150 insertions(+), 354 deletions(-) diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index be6eea0ed5d98..cf6062d7d7f58 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -2,121 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" - -[[package]] -name = "anstyle-parse" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" -dependencies = [ - "anstyle", - "windows-sys", -] - [[package]] name = "anyhow" version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "clap" -version = "4.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" -dependencies = [ - "clap_builder", - "clap_derive", - "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" -dependencies = [ - "anstream", - "anstyle", - "bitflags", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "dunce" version = "1.0.4" @@ -129,62 +20,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - -[[package]] -name = "is-terminal" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" -dependencies = [ - "hermit-abi", - "io-lifetimes", - "rustix", - "windows-sys", -] - [[package]] name = "itertools" version = "0.10.5" @@ -200,18 +35,11 @@ version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" -[[package]] -name = "linux-raw-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" - [[package]] name = "miri-script" version = "0.1.0" dependencies = [ "anyhow", - "clap", "dunce", "itertools", "path_macro", @@ -234,24 +62,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6e819bbd49d5939f682638fa54826bf1650abddcd65d000923de8ad63cc7d15" -[[package]] -name = "proc-macro2" -version = "1.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" -dependencies = [ - "proc-macro2", -] - [[package]] name = "rustc_version" version = "0.4.0" @@ -261,20 +71,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "same-file" version = "1.0.6" @@ -296,35 +92,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "2.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "walkdir" version = "2.3.3" @@ -377,72 +144,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - [[package]] name = "xshell" version = "0.2.3" diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml index 197f6abd99039..c0414a2fe374a 100644 --- a/src/tools/miri/miri-script/Cargo.toml +++ b/src/tools/miri/miri-script/Cargo.toml @@ -11,7 +11,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = {version = "4.2", features = ["derive", "env"]} which = "4.4" walkdir = "2.3" itertools = "0.10" diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 33e407a65dab5..66c2a4b0fd665 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -79,13 +79,11 @@ impl Command { Command::Fmt { flags } => Self::fmt(flags), Command::Clippy { flags } => Self::clippy(flags), Command::Cargo { flags } => Self::cargo(flags), - Command::ManySeeds { command, seed_start, seeds } => - Self::many_seeds(command, seed_start, seeds), + Command::ManySeeds { command } => Self::many_seeds(command), Command::Bench { benches } => Self::bench(benches), Command::Toolchain { flags } => Self::toolchain(flags), Command::RustcPull { commit } => Self::rustc_pull(commit.clone()), - Command::RustcPush { rustc_git, github_user, branch } => - Self::rustc_push(rustc_git, github_user, branch), + Command::RustcPush { github_user, branch } => Self::rustc_push(github_user, branch), } } @@ -178,7 +176,7 @@ impl Command { Ok(()) } - fn rustc_push(rustc_git: Option, github_user: String, branch: String) -> Result<()> { + fn rustc_push(github_user: String, branch: String) -> Result<()> { let sh = shell()?; sh.change_dir(miri_dir()?); let base = sh.read_file("rust-version")?.trim().to_owned(); @@ -188,7 +186,7 @@ impl Command { } // Find a repo we can do our preparation in. - if let Some(rustc_git) = rustc_git { + if let Ok(rustc_git) = env::var("RUSTC_GIT") { // If rustc_git is `Some`, we'll use an existing fork for the branch updates. sh.change_dir(rustc_git); } else { @@ -254,7 +252,15 @@ impl Command { Ok(()) } - fn many_seeds(command: Vec, seed_start: u64, seed_count: u64) -> Result<()> { + fn many_seeds(command: Vec) -> Result<()> { + let seed_start: u64 = env::var("MIRI_SEED_START") + .unwrap_or_else(|_| "0".into()) + .parse() + .context("failed to parse MIRI_SEED_START")?; + let seed_count: u64 = env::var("MIRI_SEEDS") + .unwrap_or_else(|_| "256".into()) + .parse() + .context("failed to parse MIRI_SEEDS")?; let seed_end = seed_start + seed_count; let Some((command_name, trailing_args)) = command.split_first() else { bail!("expected many-seeds command to be non-empty"); diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index ce00de5ac542d..849a9168028f2 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -1,19 +1,12 @@ mod commands; mod util; +use std::env; use std::ffi::OsString; -use anyhow::Result; -use clap::{Parser, Subcommand}; +use anyhow::{anyhow, bail, Result}; -#[derive(Parser, Clone, Debug)] -#[command(author, about, long_about = None)] -pub struct Cli { - #[command(subcommand)] - pub command: Command, -} - -#[derive(Subcommand, Clone, Debug)] +#[derive(Clone, Debug)] pub enum Command { /// Installs the miri driver and cargo-miri. /// Sets up the rpath such that the installed binary should work in any @@ -21,83 +14,58 @@ pub enum Command { /// sysroot, to prevent conflicts with other toolchains. Install { /// Flags that are passed through to `cargo install`. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, }, /// Just build miri. Build { /// Flags that are passed through to `cargo build`. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, }, /// Just check miri. Check { /// Flags that are passed through to `cargo check`. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, }, /// Build miri, set up a sysroot and then run the test suite. Test { - #[arg(long, default_value_t = false)] bless: bool, /// Flags that are passed through to `cargo test`. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, }, /// Build miri, set up a sysroot and then run the driver with the given . /// (Also respects MIRIFLAGS environment variable.) Run { - #[arg(long, default_value_t = false)] dep: bool, - /// Flags that are passed through to `miri` - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] + /// Flags that are passed through to `miri`. flags: Vec, }, /// Format all sources and tests. Fmt { /// Flags that are passed through to `rustfmt`. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, }, /// Runs clippy on all sources. Clippy { /// Flags that are passed through to `cargo clippy`. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] flags: Vec, }, /// Runs just `cargo ` with the Miri-specific environment variables. /// Mainly meant to be invoked by rust-analyzer. - Cargo { - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] - flags: Vec, - }, + Cargo { flags: Vec }, /// Runs over and over again with different seeds for Miri. The MIRIFLAGS /// variable is set to its original value appended with ` -Zmiri-seed=$SEED` for /// many different seeds. - ManySeeds { - /// Starting seed. - #[arg(long, env = "MIRI_SEED_START", default_value_t = 0)] - seed_start: u64, - /// Amount of seeds to try. - #[arg(long, env = "MIRI_SEEDS", default_value_t = 256)] - seeds: u64, - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] - command: Vec, - }, + ManySeeds { command: Vec }, /// Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed. Bench { /// List of benchmarks to run. By default all benchmarks are run. - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] benches: Vec, }, /// Update and activate the rustup toolchain 'miri' to the commit given in the /// `rust-version` file. /// `rustup-toolchain-install-master` must be installed for this to work. Any extra /// flags are passed to `rustup-toolchain-install-master`. - Toolchain { - #[arg(trailing_var_arg = true, allow_hyphen_values = true)] - flags: Vec, - }, + Toolchain { flags: Vec }, /// Pull and merge Miri changes from the rustc repo. Defaults to fetching the latest /// rustc commit. The fetched commit is stored in the `rust-version` file, so the /// next `./miri toolchain` will install the rustc that just got pulled. @@ -105,16 +73,138 @@ pub enum Command { /// Push Miri changes back to the rustc repo. This will pull a copy of the rustc /// history into the Miri repo, unless you set the RUSTC_GIT env var to an existing /// clone of the rustc repo. - RustcPush { - #[arg(long, env = "RUSTC_GIT")] - rustc_git: Option, - github_user: String, - branch: String, - }, + RustcPush { github_user: String, branch: String }, } +const HELP: &str = r#" COMMANDS + +./miri build : +Just build miri. are passed to `cargo build`. + +./miri check : +Just check miri. are passed to `cargo check`. + +./miri test [--bless] : +Build miri, set up a sysroot and then run the test suite. are passed +to the final `cargo test` invocation. + +./miri run [--dep] : +Build miri, set up a sysroot and then run the driver with the given . +(Also respects MIRIFLAGS environment variable.) + +./miri fmt : +Format all sources and tests. are passed to `rustfmt`. + +./miri clippy : +Runs clippy on all sources. are passed to `cargo clippy`. + +./miri cargo : +Runs just `cargo ` with the Miri-specific environment variables. +Mainly meant to be invoked by rust-analyzer. + +./miri install : +Installs the miri driver and cargo-miri. are passed to `cargo +install`. Sets up the rpath such that the installed binary should work in any +working directory. Note that the binaries are placed in the `miri` toolchain +sysroot, to prevent conflicts with other toolchains. + +./miri many-seeds : +Runs over and over again with different seeds for Miri. The MIRIFLAGS +variable is set to its original value appended with ` -Zmiri-seed=$SEED` for +many different seeds. The MIRI_SEEDS variable controls how many seeds are being +tried; MIRI_SEED_START controls the first seed to try. + +./miri bench : +Runs the benchmarks from bench-cargo-miri in hyperfine. hyperfine needs to be installed. + can explicitly list the benchmarks to run; by default, all of them are run. + +./miri toolchain : +Update and activate the rustup toolchain 'miri' to the commit given in the +`rust-version` file. +`rustup-toolchain-install-master` must be installed for this to work. Any extra +flags are passed to `rustup-toolchain-install-master`. + +./miri rustc-pull : +Pull and merge Miri changes from the rustc repo. Defaults to fetching the latest +rustc commit. The fetched commit is stored in the `rust-version` file, so the +next `./miri toolchain` will install the rustc that just got pulled. + +./miri rustc-push : +Push Miri changes back to the rustc repo. This will pull a copy of the rustc +history into the Miri repo, unless you set the RUSTC_GIT env var to an existing +clone of the rustc repo. + + ENVIRONMENT VARIABLES + +MIRI_SYSROOT: +If already set, the "sysroot setup" step is skipped. + +CARGO_EXTRA_FLAGS: +Pass extra flags to all cargo invocations. (Ignored by `./miri cargo`.)"#; + fn main() -> Result<()> { - let args = Cli::parse(); - args.command.exec()?; + // We are hand-rolling our own argument parser, since `clap` can't express what we need + // (https://github.com/clap-rs/clap/issues/5055). + let mut args = env::args_os().peekable(); + args.next().unwrap(); // skip program name + let command = match args.next().and_then(|s| s.into_string().ok()).as_deref() { + Some("build") => Command::Build { flags: args.collect() }, + Some("check") => Command::Check { flags: args.collect() }, + Some("test") => { + let bless = args.peek().is_some_and(|a| a.to_str() == Some("--bless")); + if bless { + // Consume the flag. + args.next().unwrap(); + } + Command::Test { bless, flags: args.collect() } + } + Some("run") => { + let dep = args.peek().is_some_and(|a| a.to_str() == Some("--dep")); + if dep { + // Consume the flag. + args.next().unwrap(); + } + Command::Run { dep, flags: args.collect() } + } + Some("fmt") => Command::Fmt { flags: args.collect() }, + Some("clippy") => Command::Clippy { flags: args.collect() }, + Some("cargo") => Command::Cargo { flags: args.collect() }, + Some("install") => Command::Install { flags: args.collect() }, + Some("many-seeds") => Command::ManySeeds { command: args.collect() }, + Some("bench") => Command::Bench { benches: args.collect() }, + Some("toolchain") => Command::Toolchain { flags: args.collect() }, + Some("rustc-pull") => { + let commit = args.next().map(|a| a.to_string_lossy().into_owned()); + if args.next().is_some() { + bail!("Too many arguments for `./miri rustc-pull`"); + } + Command::RustcPull { commit } + } + Some("rustc-push") => { + let github_user = args + .next() + .ok_or_else(|| { + anyhow!("Missing first argument for `./miri rustc-push GITHUB_USER BRANCH`") + })? + .to_string_lossy() + .into_owned(); + let branch = args + .next() + .ok_or_else(|| { + anyhow!("Missing second argument for `./miri rustc-push GITHUB_USER BRANCH`") + })? + .to_string_lossy() + .into_owned(); + if args.next().is_some() { + bail!("Too many arguments for `./miri rustc-push GITHUB_USER BRANCH`"); + } + Command::RustcPush { github_user, branch } + } + _ => { + eprintln!("Unknown or missing command. Usage:\n\n{HELP}"); + std::process::exit(1); + } + }; + command.exec()?; Ok(()) }