From 66bb9dc3a46e7c4b7b0e8e92c39b995e910a84b5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 10 Mar 2018 16:23:05 +0300 Subject: [PATCH] Reorganize subcommands as a separate submodule --- src/bin/cargo.rs | 1 + src/bin/{cli/mod.rs => cli.rs} | 72 +--- src/bin/command_prelude.rs | 323 ++++++++++++++++++ src/bin/{cli => commands}/bench.rs | 0 src/bin/{cli => commands}/build.rs | 0 src/bin/{cli => commands}/check.rs | 0 src/bin/{cli => commands}/clean.rs | 0 src/bin/{cli => commands}/doc.rs | 0 src/bin/{cli => commands}/fetch.rs | 0 .../{cli => commands}/generate_lockfile.rs | 0 src/bin/{cli => commands}/git_checkout.rs | 0 src/bin/{cli => commands}/init.rs | 0 src/bin/{cli => commands}/install.rs | 0 src/bin/{cli => commands}/locate_project.rs | 0 src/bin/{cli => commands}/login.rs | 0 src/bin/{cli => commands}/metadata.rs | 0 src/bin/commands/mod.rs | 66 ++++ src/bin/{cli => commands}/new.rs | 0 src/bin/{cli => commands}/owner.rs | 0 src/bin/{cli => commands}/package.rs | 0 src/bin/{cli => commands}/pkgid.rs | 0 src/bin/{cli => commands}/publish.rs | 0 src/bin/{cli => commands}/read_manifest.rs | 0 src/bin/{cli => commands}/run.rs | 0 src/bin/{cli => commands}/rustc.rs | 0 src/bin/{cli => commands}/rustdoc.rs | 0 src/bin/{cli => commands}/search.rs | 0 src/bin/{cli => commands}/test.rs | 0 src/bin/{cli => commands}/uninstall.rs | 0 src/bin/{cli => commands}/update.rs | 0 src/bin/{cli => commands}/verify_project.rs | 0 src/bin/{cli => commands}/version.rs | 0 src/bin/{cli => commands}/yank.rs | 0 33 files changed, 393 insertions(+), 69 deletions(-) rename src/bin/{cli/mod.rs => cli.rs} (95%) create mode 100644 src/bin/command_prelude.rs rename src/bin/{cli => commands}/bench.rs (100%) rename src/bin/{cli => commands}/build.rs (100%) rename src/bin/{cli => commands}/check.rs (100%) rename src/bin/{cli => commands}/clean.rs (100%) rename src/bin/{cli => commands}/doc.rs (100%) rename src/bin/{cli => commands}/fetch.rs (100%) rename src/bin/{cli => commands}/generate_lockfile.rs (100%) rename src/bin/{cli => commands}/git_checkout.rs (100%) rename src/bin/{cli => commands}/init.rs (100%) rename src/bin/{cli => commands}/install.rs (100%) rename src/bin/{cli => commands}/locate_project.rs (100%) rename src/bin/{cli => commands}/login.rs (100%) rename src/bin/{cli => commands}/metadata.rs (100%) create mode 100644 src/bin/commands/mod.rs rename src/bin/{cli => commands}/new.rs (100%) rename src/bin/{cli => commands}/owner.rs (100%) rename src/bin/{cli => commands}/package.rs (100%) rename src/bin/{cli => commands}/pkgid.rs (100%) rename src/bin/{cli => commands}/publish.rs (100%) rename src/bin/{cli => commands}/read_manifest.rs (100%) rename src/bin/{cli => commands}/run.rs (100%) rename src/bin/{cli => commands}/rustc.rs (100%) rename src/bin/{cli => commands}/rustdoc.rs (100%) rename src/bin/{cli => commands}/search.rs (100%) rename src/bin/{cli => commands}/test.rs (100%) rename src/bin/{cli => commands}/uninstall.rs (100%) rename src/bin/{cli => commands}/update.rs (100%) rename src/bin/{cli => commands}/verify_project.rs (100%) rename src/bin/{cli => commands}/version.rs (100%) rename src/bin/{cli => commands}/yank.rs (100%) diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs index b7aa9a412..83c0f78cf 100644 --- a/src/bin/cargo.rs +++ b/src/bin/cargo.rs @@ -20,6 +20,7 @@ use cargo::util::{CliError, ProcessError}; mod cli; mod command_prelude; +mod commands; fn main() { diff --git a/src/bin/cli/mod.rs b/src/bin/cli.rs similarity index 95% rename from src/bin/cli/mod.rs rename to src/bin/cli.rs index 8fb63d35f..6894d3bb6 100644 --- a/src/bin/cli/mod.rs +++ b/src/bin/cli.rs @@ -24,6 +24,7 @@ use std::fs; use search_directories; use is_executable; use command_prelude::*; +use commands; pub fn do_main(config: &mut Config) -> CliResult { let args = cli().get_matches_safe()?; @@ -620,44 +621,11 @@ Some common cargo commands are (see all commands with --list): See 'cargo help ' for more information on a specific command. ") - .subcommands(builtin_subcommands()) + .subcommands(commands::builtin()) ; app } -fn builtin_subcommands() -> Vec { - vec![ - bench::cli(), - build::cli(), - check::cli(), - clean::cli(), - doc::cli(), - fetch::cli(), - generate_lockfile::cli(), - git_checkout::cli(), - init::cli(), - install::cli(), - locate_project::cli(), - login::cli(), - metadata::cli(), - new::cli(), - owner::cli(), - package::cli(), - pkgid::cli(), - publish::cli(), - read_manifest::cli(), - run::cli(), - rustc::cli(), - rustdoc::cli(), - search::cli(), - test::cli(), - uninstall::cli(), - update::cli(), - verify_project::cli(), - version::cli(), - yank::cli(), - ] -} /// List all runnable commands pub fn list_commands(config: &Config) -> BTreeSet<(String, Option)> { @@ -688,43 +656,9 @@ pub fn list_commands(config: &Config) -> BTreeSet<(String, Option)> { } } - for cmd in builtin_subcommands() { + for cmd in commands::builtin() { commands.insert((cmd.get_name().to_string(), None)); } commands } - - -mod bench; -mod build; -mod check; -mod clean; -mod doc; -mod fetch; -mod generate_lockfile; - -// FIXME: let's just drop this subcommand? -mod git_checkout; - -mod init; -mod install; -mod locate_project; -mod login; -mod metadata; -mod new; -mod owner; -mod package; -mod pkgid; -mod publish; -mod read_manifest; -mod run; -mod rustc; -mod rustdoc; -mod search; -mod test; -mod uninstall; -mod update; -mod verify_project; -mod version; -mod yank; diff --git a/src/bin/command_prelude.rs b/src/bin/command_prelude.rs new file mode 100644 index 000000000..5d10c76be --- /dev/null +++ b/src/bin/command_prelude.rs @@ -0,0 +1,323 @@ +use std::path::PathBuf; + +use clap::{self, SubCommand, AppSettings, ArgMatches}; +use cargo::{Config, CargoResult}; +use cargo::core::Workspace; +use cargo::ops::{CompileMode, CompileOptions, CompileFilter, Packages, MessageFormat, + VersionControl, NewOptions}; +use cargo::util::important_paths::find_root_manifest_for_wd; + +pub use clap::Arg; + +pub type App = clap::App<'static, 'static>; + +pub trait CommonArgs: Sized { + fn _arg(self, arg: Arg<'static, 'static>) -> Self; + + fn arg_package(self, package: &'static str, all: &'static str, exclude: &'static str) -> Self { + self._arg(opt("package", package).short("p").value_name("SPEC").multiple(true)) + ._arg(opt("all", all)) + ._arg(opt("exclude", exclude).value_name("SPEC").multiple(true)) + } + + fn arg_single_package(self, package: &'static str) -> Self { + self._arg(opt("package", package).short("p").value_name("SPEC")) + } + + fn arg_jobs(self) -> Self { + self._arg( + opt("jobs", "Number of parallel jobs, defaults to # of CPUs") + .short("j").value_name("N") + ) + } + + fn arg_targets_all( + self, + lib: &'static str, + bin: &'static str, + bins: &'static str, + examle: &'static str, + examles: &'static str, + test: &'static str, + tests: &'static str, + bench: &'static str, + benchs: &'static str, + all: &'static str, + ) -> Self { + self.arg_targets_lib_bin(lib, bin, bins) + ._arg(opt("example", examle).value_name("NAME").multiple(true)) + ._arg(opt("examples", examles)) + ._arg(opt("test", test).value_name("NAME").multiple(true)) + ._arg(opt("tests", tests)) + ._arg(opt("bench", bench).value_name("NAME").multiple(true)) + ._arg(opt("benches", benchs)) + ._arg(opt("all-targets", all)) + } + + fn arg_targets_lib_bin( + self, + lib: &'static str, + bin: &'static str, + bins: &'static str, + ) -> Self { + self._arg(opt("lib", lib)) + ._arg(opt("bin", bin).value_name("NAME").multiple(true)) + ._arg(opt("bins", bins)) + } + + fn arg_targets_bins_examples( + self, + bin: &'static str, + bins: &'static str, + example: &'static str, + examples: &'static str, + ) -> Self { + self._arg(opt("bin", bin).value_name("NAME").multiple(true)) + ._arg(opt("bins", bins)) + ._arg(opt("example", example).value_name("NAME").multiple(true)) + ._arg(opt("examples", examples)) + } + + fn arg_targets_bin_example( + self, + bin: &'static str, + example: &'static str, + ) -> Self { + self._arg(opt("bin", bin).value_name("NAME").multiple(true)) + ._arg(opt("example", example).value_name("NAME").multiple(true)) + } + + fn arg_features(self) -> Self { + self + ._arg( + opt("features", "Space-separated list of features to activate") + .value_name("FEATURES") + ) + ._arg(opt("all-features", "Activate all available features")) + ._arg(opt("no-default-features", "Do not activate the `default` feature")) + } + + fn arg_release(self, release: &'static str) -> Self { + self._arg(opt("release", release)) + } + + fn arg_target_triple(self, target: &'static str) -> Self { + self._arg(opt("target", target).value_name("TRIPLE")) + } + + fn arg_manifest_path(self) -> Self { + self._arg(opt("manifest-path", "Path to Cargo.toml").value_name("PATH")) + } + + fn arg_message_format(self) -> Self { + self._arg( + opt("message-format", "Error format") + .value_name("FMT") + .case_insensitive(true) + .possible_values(&["human", "json"]).default_value("human") + ) + } + + fn arg_new_opts(self) -> Self { + self._arg( + opt("vcs", "\ +Initialize a new repository for the given version \ +control system (git, hg, pijul, or fossil) or do not \ +initialize any version control at all (none), overriding \ +a global configuration.") + .value_name("VCS") + .possible_values(&["git", "hg", "pijul", "fossil", "none"]) + ) + ._arg(opt("bin", "Use a binary (application) template [default]")) + ._arg(opt("lib", "Use a library template")) + ._arg( + opt("name", "Set the resulting package name, defaults to the directory name") + .value_name("NAME") + ) + } + + fn arg_index(self) -> Self { + self + ._arg( + opt("index", "Registry index to upload the package to") + .value_name("INDEX") + ) + ._arg( + opt("host", "DEPRECATED, renamed to '--index'") + .value_name("HOST") + .hidden(true) + ) + } +} + +impl CommonArgs for App { + fn _arg(self, arg: Arg<'static, 'static>) -> Self { + self.arg(arg) + } +} + +pub fn opt(name: &'static str, help: &'static str) -> Arg<'static, 'static> { + Arg::with_name(name).long(name).help(help) +} + +pub fn subcommand(name: &'static str) -> App { + SubCommand::with_name(name) + .settings(&[ + AppSettings::UnifiedHelpMessage, + AppSettings::DeriveDisplayOrder, + AppSettings::DontCollapseArgsInUsage, + ]) +} + +pub fn values(args: &ArgMatches, name: &str) -> Vec { + args.values_of(name).unwrap_or_default() + .map(|s| s.to_string()) + .collect() +} + + +pub fn config_from_args(config: &mut Config, args: &ArgMatches) -> CargoResult<()> { + let color = args.value_of("color").map(|s| s.to_string()); + config.configure( + args.occurrences_of("verbose") as u32, + if args.is_present("quite") { Some(true) } else { None }, + &color, + args.is_present("frozen"), + args.is_present("locked"), + &args.values_of_lossy("unstable-features").unwrap_or_default(), + ) +} + +pub fn root_manifest_from_args(config: &Config, args: &ArgMatches) -> CargoResult { + let manifest_path = args.value_of("manifest-path").map(|s| s.to_string()); + find_root_manifest_for_wd(manifest_path, config.cwd()) +} + +pub fn workspace_from_args<'a>(config: &'a Config, args: &ArgMatches) -> CargoResult> { + let root = root_manifest_from_args(config, args)?; + Workspace::new(&root, config) +} + +pub fn jobs_from_args(args: &ArgMatches) -> CargoResult> { //FIXME: validation + let jobs = match args.value_of("jobs") { + None => None, + Some(jobs) => Some(jobs.parse::().map_err(|_| { + clap::Error::value_validation_auto( + format!("could not parse `{}` as a number", jobs) + ) + })?) + }; + Ok(jobs) +} + +pub fn compile_options_from_args<'a>( + config: &'a Config, + args: &'a ArgMatches<'a>, + mode: CompileMode, +) -> CargoResult> { + let spec = Packages::from_flags( + args.is_present("all"), + values(args, "exclude"), + values(args, "package"), + )?; + + let message_format = match args.value_of("message-format") { + None => MessageFormat::Human, + Some(f) => { + if f.eq_ignore_ascii_case("json") { + MessageFormat::Json + } else if f.eq_ignore_ascii_case("human") { + MessageFormat::Human + } else { + panic!("Impossible message format: {:?}", f) + } + } + }; + + let opts = CompileOptions { + config, + jobs: jobs_from_args(args)?, + target: args.value_of("target"), + features: values(args, "features"), + all_features: args.is_present("all-features"), + no_default_features: args.is_present("no-default-features"), + spec, + mode, + release: args.is_present("release"), + filter: CompileFilter::new(args.is_present("lib"), + values(args, "bin"), args.is_present("bins"), + values(args, "test"), args.is_present("tests"), + values(args, "example"), args.is_present("examples"), + values(args, "bench"), args.is_present("benches"), + args.is_present("all-targets")), + message_format, + target_rustdoc_args: None, + target_rustc_args: None, + }; + Ok(opts) +} + +pub fn compile_options_from_args_for_single_package<'a>( + config: &'a Config, + args: &'a ArgMatches<'a>, + mode: CompileMode, +) -> CargoResult> { + let mut compile_opts = compile_options_from_args(config, args, mode)?; + compile_opts.spec = Packages::Packages(values(args, "package")); + Ok(compile_opts) +} + +pub fn new_opts_from_args<'a>(args: &'a ArgMatches<'a>, path: &'a str) -> CargoResult> { + let vcs = args.value_of("vcs").map(|vcs| match vcs { + "git" => VersionControl::Git, + "hg" => VersionControl::Hg, + "pijul" => VersionControl::Pijul, + "fossil" => VersionControl::Fossil, + "none" => VersionControl::NoVcs, + vcs => panic!("Impossible vcs: {:?}", vcs), + }); + NewOptions::new(vcs, + args.is_present("bin"), + args.is_present("lib"), + path, + args.value_of("name")) +} + +pub fn registry_from_args(config: &Config, args: &ArgMatches) -> CargoResult> { + match args.value_of("registry") { + Some(registry) => { + if !config.cli_unstable().unstable_options { + return Err(format_err!("registry option is an unstable feature and \ + requires -Zunstable-options to use.").into()); + } + Ok(Some(registry.to_string())) + } + None => Ok(None), + } +} + +pub fn index_from_args(config: &Config, args: &ArgMatches) -> CargoResult> { + // TODO: Deprecated + // remove once it has been decided --host can be removed + // We may instead want to repurpose the host flag, as + // mentioned in this issue + // https://github.com/rust-lang/cargo/issues/4208 + let msg = "The flag '--host' is no longer valid. + +Previous versions of Cargo accepted this flag, but it is being +deprecated. The flag is being renamed to 'index', as the flag +wants the location of the index. Please use '--index' instead. + +This will soon become a hard error, so it's either recommended +to update to a fixed version or contact the upstream maintainer +about this warning."; + + let index = match args.value_of("host") { + Some(host) => { + config.shell().warn(&msg)?; + Some(host.to_string()) + } + None => args.value_of("index").map(|s| s.to_string()) + }; + Ok(index) +} diff --git a/src/bin/cli/bench.rs b/src/bin/commands/bench.rs similarity index 100% rename from src/bin/cli/bench.rs rename to src/bin/commands/bench.rs diff --git a/src/bin/cli/build.rs b/src/bin/commands/build.rs similarity index 100% rename from src/bin/cli/build.rs rename to src/bin/commands/build.rs diff --git a/src/bin/cli/check.rs b/src/bin/commands/check.rs similarity index 100% rename from src/bin/cli/check.rs rename to src/bin/commands/check.rs diff --git a/src/bin/cli/clean.rs b/src/bin/commands/clean.rs similarity index 100% rename from src/bin/cli/clean.rs rename to src/bin/commands/clean.rs diff --git a/src/bin/cli/doc.rs b/src/bin/commands/doc.rs similarity index 100% rename from src/bin/cli/doc.rs rename to src/bin/commands/doc.rs diff --git a/src/bin/cli/fetch.rs b/src/bin/commands/fetch.rs similarity index 100% rename from src/bin/cli/fetch.rs rename to src/bin/commands/fetch.rs diff --git a/src/bin/cli/generate_lockfile.rs b/src/bin/commands/generate_lockfile.rs similarity index 100% rename from src/bin/cli/generate_lockfile.rs rename to src/bin/commands/generate_lockfile.rs diff --git a/src/bin/cli/git_checkout.rs b/src/bin/commands/git_checkout.rs similarity index 100% rename from src/bin/cli/git_checkout.rs rename to src/bin/commands/git_checkout.rs diff --git a/src/bin/cli/init.rs b/src/bin/commands/init.rs similarity index 100% rename from src/bin/cli/init.rs rename to src/bin/commands/init.rs diff --git a/src/bin/cli/install.rs b/src/bin/commands/install.rs similarity index 100% rename from src/bin/cli/install.rs rename to src/bin/commands/install.rs diff --git a/src/bin/cli/locate_project.rs b/src/bin/commands/locate_project.rs similarity index 100% rename from src/bin/cli/locate_project.rs rename to src/bin/commands/locate_project.rs diff --git a/src/bin/cli/login.rs b/src/bin/commands/login.rs similarity index 100% rename from src/bin/cli/login.rs rename to src/bin/commands/login.rs diff --git a/src/bin/cli/metadata.rs b/src/bin/commands/metadata.rs similarity index 100% rename from src/bin/cli/metadata.rs rename to src/bin/commands/metadata.rs diff --git a/src/bin/commands/mod.rs b/src/bin/commands/mod.rs new file mode 100644 index 000000000..6dea3eb16 --- /dev/null +++ b/src/bin/commands/mod.rs @@ -0,0 +1,66 @@ +use command_prelude::*; + +pub fn builtin() -> Vec { + vec![ + bench::cli(), + build::cli(), + check::cli(), + clean::cli(), + doc::cli(), + fetch::cli(), + generate_lockfile::cli(), + git_checkout::cli(), + init::cli(), + install::cli(), + locate_project::cli(), + login::cli(), + metadata::cli(), + new::cli(), + owner::cli(), + package::cli(), + pkgid::cli(), + publish::cli(), + read_manifest::cli(), + run::cli(), + rustc::cli(), + rustdoc::cli(), + search::cli(), + test::cli(), + uninstall::cli(), + update::cli(), + verify_project::cli(), + version::cli(), + yank::cli(), + ] +} + + +mod bench; +mod build; +mod check; +mod clean; +mod doc; +mod fetch; +mod generate_lockfile; +mod git_checkout; +mod init; +mod install; +mod locate_project; +mod login; +mod metadata; +mod new; +mod owner; +mod package; +mod pkgid; +mod publish; +mod read_manifest; +mod run; +mod rustc; +mod rustdoc; +mod search; +mod test; +mod uninstall; +mod update; +mod verify_project; +mod version; +mod yank; diff --git a/src/bin/cli/new.rs b/src/bin/commands/new.rs similarity index 100% rename from src/bin/cli/new.rs rename to src/bin/commands/new.rs diff --git a/src/bin/cli/owner.rs b/src/bin/commands/owner.rs similarity index 100% rename from src/bin/cli/owner.rs rename to src/bin/commands/owner.rs diff --git a/src/bin/cli/package.rs b/src/bin/commands/package.rs similarity index 100% rename from src/bin/cli/package.rs rename to src/bin/commands/package.rs diff --git a/src/bin/cli/pkgid.rs b/src/bin/commands/pkgid.rs similarity index 100% rename from src/bin/cli/pkgid.rs rename to src/bin/commands/pkgid.rs diff --git a/src/bin/cli/publish.rs b/src/bin/commands/publish.rs similarity index 100% rename from src/bin/cli/publish.rs rename to src/bin/commands/publish.rs diff --git a/src/bin/cli/read_manifest.rs b/src/bin/commands/read_manifest.rs similarity index 100% rename from src/bin/cli/read_manifest.rs rename to src/bin/commands/read_manifest.rs diff --git a/src/bin/cli/run.rs b/src/bin/commands/run.rs similarity index 100% rename from src/bin/cli/run.rs rename to src/bin/commands/run.rs diff --git a/src/bin/cli/rustc.rs b/src/bin/commands/rustc.rs similarity index 100% rename from src/bin/cli/rustc.rs rename to src/bin/commands/rustc.rs diff --git a/src/bin/cli/rustdoc.rs b/src/bin/commands/rustdoc.rs similarity index 100% rename from src/bin/cli/rustdoc.rs rename to src/bin/commands/rustdoc.rs diff --git a/src/bin/cli/search.rs b/src/bin/commands/search.rs similarity index 100% rename from src/bin/cli/search.rs rename to src/bin/commands/search.rs diff --git a/src/bin/cli/test.rs b/src/bin/commands/test.rs similarity index 100% rename from src/bin/cli/test.rs rename to src/bin/commands/test.rs diff --git a/src/bin/cli/uninstall.rs b/src/bin/commands/uninstall.rs similarity index 100% rename from src/bin/cli/uninstall.rs rename to src/bin/commands/uninstall.rs diff --git a/src/bin/cli/update.rs b/src/bin/commands/update.rs similarity index 100% rename from src/bin/cli/update.rs rename to src/bin/commands/update.rs diff --git a/src/bin/cli/verify_project.rs b/src/bin/commands/verify_project.rs similarity index 100% rename from src/bin/cli/verify_project.rs rename to src/bin/commands/verify_project.rs diff --git a/src/bin/cli/version.rs b/src/bin/commands/version.rs similarity index 100% rename from src/bin/cli/version.rs rename to src/bin/commands/version.rs diff --git a/src/bin/cli/yank.rs b/src/bin/commands/yank.rs similarity index 100% rename from src/bin/cli/yank.rs rename to src/bin/commands/yank.rs -- 2.30.2