Address autobins warning.
authorEric Huss <eric@huss.org>
Thu, 3 May 2018 16:13:36 +0000 (09:13 -0700)
committerEric Huss <eric@huss.org>
Thu, 3 May 2018 17:08:26 +0000 (10:08 -0700)
66 files changed:
src/bin/cargo.rs [deleted file]
src/bin/cargo/cli.rs [new file with mode: 0644]
src/bin/cargo/command_prelude.rs [new file with mode: 0644]
src/bin/cargo/commands/bench.rs [new file with mode: 0644]
src/bin/cargo/commands/build.rs [new file with mode: 0644]
src/bin/cargo/commands/check.rs [new file with mode: 0644]
src/bin/cargo/commands/clean.rs [new file with mode: 0644]
src/bin/cargo/commands/doc.rs [new file with mode: 0644]
src/bin/cargo/commands/fetch.rs [new file with mode: 0644]
src/bin/cargo/commands/generate_lockfile.rs [new file with mode: 0644]
src/bin/cargo/commands/git_checkout.rs [new file with mode: 0644]
src/bin/cargo/commands/init.rs [new file with mode: 0644]
src/bin/cargo/commands/install.rs [new file with mode: 0644]
src/bin/cargo/commands/locate_project.rs [new file with mode: 0644]
src/bin/cargo/commands/login.rs [new file with mode: 0644]
src/bin/cargo/commands/metadata.rs [new file with mode: 0644]
src/bin/cargo/commands/mod.rs [new file with mode: 0644]
src/bin/cargo/commands/new.rs [new file with mode: 0644]
src/bin/cargo/commands/owner.rs [new file with mode: 0644]
src/bin/cargo/commands/package.rs [new file with mode: 0644]
src/bin/cargo/commands/pkgid.rs [new file with mode: 0644]
src/bin/cargo/commands/publish.rs [new file with mode: 0644]
src/bin/cargo/commands/read_manifest.rs [new file with mode: 0644]
src/bin/cargo/commands/run.rs [new file with mode: 0644]
src/bin/cargo/commands/rustc.rs [new file with mode: 0644]
src/bin/cargo/commands/rustdoc.rs [new file with mode: 0644]
src/bin/cargo/commands/search.rs [new file with mode: 0644]
src/bin/cargo/commands/test.rs [new file with mode: 0644]
src/bin/cargo/commands/uninstall.rs [new file with mode: 0644]
src/bin/cargo/commands/update.rs [new file with mode: 0644]
src/bin/cargo/commands/verify_project.rs [new file with mode: 0644]
src/bin/cargo/commands/version.rs [new file with mode: 0644]
src/bin/cargo/commands/yank.rs [new file with mode: 0644]
src/bin/cargo/main.rs [new file with mode: 0644]
src/bin/cli.rs [deleted file]
src/bin/command_prelude.rs [deleted file]
src/bin/commands/bench.rs [deleted file]
src/bin/commands/build.rs [deleted file]
src/bin/commands/check.rs [deleted file]
src/bin/commands/clean.rs [deleted file]
src/bin/commands/doc.rs [deleted file]
src/bin/commands/fetch.rs [deleted file]
src/bin/commands/generate_lockfile.rs [deleted file]
src/bin/commands/git_checkout.rs [deleted file]
src/bin/commands/init.rs [deleted file]
src/bin/commands/install.rs [deleted file]
src/bin/commands/locate_project.rs [deleted file]
src/bin/commands/login.rs [deleted file]
src/bin/commands/metadata.rs [deleted file]
src/bin/commands/mod.rs [deleted file]
src/bin/commands/new.rs [deleted file]
src/bin/commands/owner.rs [deleted file]
src/bin/commands/package.rs [deleted file]
src/bin/commands/pkgid.rs [deleted file]
src/bin/commands/publish.rs [deleted file]
src/bin/commands/read_manifest.rs [deleted file]
src/bin/commands/run.rs [deleted file]
src/bin/commands/rustc.rs [deleted file]
src/bin/commands/rustdoc.rs [deleted file]
src/bin/commands/search.rs [deleted file]
src/bin/commands/test.rs [deleted file]
src/bin/commands/uninstall.rs [deleted file]
src/bin/commands/update.rs [deleted file]
src/bin/commands/verify_project.rs [deleted file]
src/bin/commands/version.rs [deleted file]
src/bin/commands/yank.rs [deleted file]

diff --git a/src/bin/cargo.rs b/src/bin/cargo.rs
deleted file mode 100644 (file)
index 7d7c7db..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-extern crate cargo;
-extern crate clap;
-extern crate env_logger;
-#[macro_use]
-extern crate failure;
-extern crate git2_curl;
-extern crate log;
-#[macro_use]
-extern crate serde_derive;
-extern crate serde_json;
-extern crate toml;
-
-use std::env;
-use std::fs;
-use std::path::{Path, PathBuf};
-use std::collections::BTreeSet;
-
-use cargo::core::shell::Shell;
-use cargo::util::{self, lev_distance, CargoResult, CliResult, Config};
-use cargo::util::{CliError, ProcessError};
-
-mod cli;
-mod command_prelude;
-mod commands;
-
-fn main() {
-    env_logger::init();
-
-    let mut config = match Config::default() {
-        Ok(cfg) => cfg,
-        Err(e) => {
-            let mut shell = Shell::new();
-            cargo::exit_with_error(e.into(), &mut shell)
-        }
-    };
-
-    let result = {
-        init_git_transports(&mut config);
-        let _token = cargo::util::job::setup();
-        cli::main(&mut config)
-    };
-
-    match result {
-        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
-        Ok(()) => {}
-    }
-}
-
-fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
-    let alias_name = format!("alias.{}", command);
-    let mut result = Ok(None);
-    match config.get_string(&alias_name) {
-        Ok(value) => {
-            if let Some(record) = value {
-                let alias_commands = record
-                    .val
-                    .split_whitespace()
-                    .map(|s| s.to_string())
-                    .collect();
-                result = Ok(Some(alias_commands));
-            }
-        }
-        Err(_) => {
-            let value = config.get_list(&alias_name)?;
-            if let Some(record) = value {
-                let alias_commands: Vec<String> =
-                    record.val.iter().map(|s| s.0.to_string()).collect();
-                result = Ok(Some(alias_commands));
-            }
-        }
-    }
-    result
-}
-
-/// List all runnable commands
-fn list_commands(config: &Config) -> BTreeSet<(String, Option<String>)> {
-    let prefix = "cargo-";
-    let suffix = env::consts::EXE_SUFFIX;
-    let mut commands = BTreeSet::new();
-    for dir in search_directories(config) {
-        let entries = match fs::read_dir(dir) {
-            Ok(entries) => entries,
-            _ => continue,
-        };
-        for entry in entries.filter_map(|e| e.ok()) {
-            let path = entry.path();
-            let filename = match path.file_name().and_then(|s| s.to_str()) {
-                Some(filename) => filename,
-                _ => continue,
-            };
-            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
-                continue;
-            }
-            if is_executable(entry.path()) {
-                let end = filename.len() - suffix.len();
-                commands.insert((
-                    filename[prefix.len()..end].to_string(),
-                    Some(path.display().to_string()),
-                ));
-            }
-        }
-    }
-
-    for cmd in commands::builtin() {
-        commands.insert((cmd.get_name().to_string(), None));
-    }
-
-    commands
-}
-
-fn find_closest(config: &Config, cmd: &str) -> Option<String> {
-    let cmds = list_commands(config);
-    // Only consider candidates with a lev_distance of 3 or less so we don't
-    // suggest out-of-the-blue options.
-    let mut filtered = cmds.iter()
-        .map(|&(ref c, _)| (lev_distance(c, cmd), c))
-        .filter(|&(d, _)| d < 4)
-        .collect::<Vec<_>>();
-    filtered.sort_by(|a, b| a.0.cmp(&b.0));
-    filtered.get(0).map(|slot| slot.1.clone())
-}
-
-fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
-    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
-    let path = search_directories(config)
-        .iter()
-        .map(|dir| dir.join(&command_exe))
-        .find(|file| is_executable(file));
-    let command = match path {
-        Some(command) => command,
-        None => {
-            let err = match find_closest(config, cmd) {
-                Some(closest) => format_err!(
-                    "no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
-                    cmd,
-                    closest
-                ),
-                None => format_err!("no such subcommand: `{}`", cmd),
-            };
-            return Err(CliError::new(err, 101));
-        }
-    };
-
-    let cargo_exe = config.cargo_exe()?;
-    let err = match util::process(&command)
-        .env(cargo::CARGO_ENV, cargo_exe)
-        .args(args)
-        .exec_replace()
-    {
-        Ok(()) => return Ok(()),
-        Err(e) => e,
-    };
-
-    if let Some(perr) = err.downcast_ref::<ProcessError>() {
-        if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
-            return Err(CliError::code(code));
-        }
-    }
-    Err(CliError::new(err, 101))
-}
-
-#[cfg(unix)]
-fn is_executable<P: AsRef<Path>>(path: P) -> bool {
-    use std::os::unix::prelude::*;
-    fs::metadata(path)
-        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
-        .unwrap_or(false)
-}
-#[cfg(windows)]
-fn is_executable<P: AsRef<Path>>(path: P) -> bool {
-    fs::metadata(path)
-        .map(|metadata| metadata.is_file())
-        .unwrap_or(false)
-}
-
-fn search_directories(config: &Config) -> Vec<PathBuf> {
-    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
-    if let Some(val) = env::var_os("PATH") {
-        dirs.extend(env::split_paths(&val));
-    }
-    dirs
-}
-
-fn init_git_transports(config: &Config) {
-    // Only use a custom transport if any HTTP options are specified,
-    // such as proxies or custom certificate authorities. The custom
-    // transport, however, is not as well battle-tested.
-
-    match cargo::ops::needs_custom_http_transport(config) {
-        Ok(true) => {}
-        _ => return,
-    }
-
-    let handle = match cargo::ops::http_handle(config) {
-        Ok(handle) => handle,
-        Err(..) => return,
-    };
-
-    // The unsafety of the registration function derives from two aspects:
-    //
-    // 1. This call must be synchronized with all other registration calls as
-    //    well as construction of new transports.
-    // 2. The argument is leaked.
-    //
-    // We're clear on point (1) because this is only called at the start of this
-    // binary (we know what the state of the world looks like) and we're mostly
-    // clear on point (2) because we'd only free it after everything is done
-    // anyway
-    unsafe {
-        git2_curl::register(handle);
-    }
-}
diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs
new file mode 100644 (file)
index 0000000..9fbd12c
--- /dev/null
@@ -0,0 +1,214 @@
+extern crate clap;
+
+use clap::{AppSettings, Arg, ArgMatches};
+
+use cargo::{self, CliResult, Config};
+
+use super::list_commands;
+use super::commands;
+use command_prelude::*;
+
+pub fn main(config: &mut Config) -> CliResult {
+    let args = cli().get_matches_safe()?;
+
+    if args.value_of("unstable-features") == Some("help") {
+        println!(
+            "
+Available unstable (nightly-only) flags:
+
+    -Z avoid-dev-deps   -- Avoid installing dev-dependencies if possible
+    -Z minimal-versions -- Install minimal dependency versions instead of maximum
+    -Z no-index-update  -- Do not update the registry, avoids a network request for benchmarking
+    -Z offline          -- Offline mode that does not perform network requests
+    -Z unstable-options -- Allow the usage of unstable options such as --registry
+
+Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
+        );
+        return Ok(());
+    }
+
+    let is_verbose = args.occurrences_of("verbose") > 0;
+    if args.is_present("version") {
+        let version = cargo::version();
+        println!("{}", version);
+        if is_verbose {
+            println!(
+                "release: {}.{}.{}",
+                version.major, version.minor, version.patch
+            );
+            if let Some(ref cfg) = version.cfg_info {
+                if let Some(ref ci) = cfg.commit_info {
+                    println!("commit-hash: {}", ci.commit_hash);
+                    println!("commit-date: {}", ci.commit_date);
+                }
+            }
+        }
+        return Ok(());
+    }
+
+    if let Some(ref code) = args.value_of("explain") {
+        let mut procss = config.rustc(None)?.process();
+        procss.arg("--explain").arg(code).exec()?;
+        return Ok(());
+    }
+
+    if args.is_present("list") {
+        println!("Installed Commands:");
+        for command in list_commands(config) {
+            let (command, path) = command;
+            if is_verbose {
+                match path {
+                    Some(p) => println!("    {:<20} {}", command, p),
+                    None => println!("    {:<20}", command),
+                }
+            } else {
+                println!("    {}", command);
+            }
+        }
+        return Ok(());
+    }
+
+    let args = expand_aliases(config, args)?;
+
+    execute_subcommand(config, args)
+}
+
+fn expand_aliases(
+    config: &mut Config,
+    args: ArgMatches<'static>,
+) -> Result<ArgMatches<'static>, CliError> {
+    if let (cmd, Some(args)) = args.subcommand() {
+        match (
+            commands::builtin_exec(cmd),
+            super::aliased_command(config, cmd)?,
+        ) {
+            (None, Some(mut alias)) => {
+                alias.extend(
+                    args.values_of("")
+                        .unwrap_or_default()
+                        .map(|s| s.to_string()),
+                );
+                let args = cli()
+                    .setting(AppSettings::NoBinaryName)
+                    .get_matches_from_safe(alias)?;
+                return expand_aliases(config, args);
+            }
+            (Some(_), Some(_)) => {
+                config.shell().warn(format!(
+                    "alias `{}` is ignored, because it is shadowed by a built in command",
+                    cmd
+                ))?;
+            }
+            (_, None) => {}
+        }
+    };
+    Ok(args)
+}
+
+fn execute_subcommand(config: &mut Config, args: ArgMatches) -> CliResult {
+    let (cmd, subcommand_args) = match args.subcommand() {
+        (cmd, Some(args)) => (cmd, args),
+        _ => {
+            cli().print_help()?;
+            return Ok(());
+        }
+    };
+
+    let arg_target_dir = &subcommand_args.value_of_path("target-dir", config);
+
+    config.configure(
+        args.occurrences_of("verbose") as u32,
+        if args.is_present("quiet") {
+            Some(true)
+        } else {
+            None
+        },
+        &args.value_of("color").map(|s| s.to_string()),
+        args.is_present("frozen"),
+        args.is_present("locked"),
+        arg_target_dir,
+        &args.values_of_lossy("unstable-features")
+            .unwrap_or_default(),
+    )?;
+
+    if let Some(exec) = commands::builtin_exec(cmd) {
+        return exec(config, subcommand_args);
+    }
+
+    let mut ext_args: Vec<&str> = vec![cmd];
+    ext_args.extend(subcommand_args.values_of("").unwrap_or_default());
+    super::execute_external_subcommand(config, cmd, &ext_args)
+}
+
+fn cli() -> App {
+    let app = App::new("cargo")
+        .settings(&[
+            AppSettings::UnifiedHelpMessage,
+            AppSettings::DeriveDisplayOrder,
+            AppSettings::VersionlessSubcommands,
+            AppSettings::AllowExternalSubcommands,
+        ])
+        .about("")
+        .template(
+            "\
+Rust's package manager
+
+USAGE:
+    {usage}
+
+OPTIONS:
+{unified}
+
+Some common cargo commands are (see all commands with --list):
+    build       Compile the current project
+    check       Analyze the current project and report errors, but don't build object files
+    clean       Remove the target directory
+    doc         Build this project's and its dependencies' documentation
+    new         Create a new cargo project
+    init        Create a new cargo project in an existing directory
+    run         Build and execute src/main.rs
+    test        Run the tests
+    bench       Run the benchmarks
+    update      Update dependencies listed in Cargo.lock
+    search      Search registry for crates
+    publish     Package and upload this project to the registry
+    install     Install a Rust binary
+    uninstall   Uninstall a Rust binary
+
+See 'cargo help <command>' for more information on a specific command.\n",
+        )
+        .arg(opt("version", "Print version info and exit").short("V"))
+        .arg(opt("list", "List installed commands"))
+        .arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE"))
+        .arg(
+            opt(
+                "verbose",
+                "Use verbose output (-vv very verbose/build.rs output)",
+            ).short("v")
+                .multiple(true)
+                .global(true),
+        )
+        .arg(
+            opt("quiet", "No output printed to stdout")
+                .short("q")
+                .global(true),
+        )
+        .arg(
+            opt("color", "Coloring: auto, always, never")
+                .value_name("WHEN")
+                .global(true),
+        )
+        .arg(opt("frozen", "Require Cargo.lock and cache are up to date").global(true))
+        .arg(opt("locked", "Require Cargo.lock is up to date").global(true))
+        .arg(
+            Arg::with_name("unstable-features")
+                .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details")
+                .short("Z")
+                .value_name("FLAG")
+                .multiple(true)
+                .number_of_values(1)
+                .global(true),
+        )
+        .subcommands(commands::builtin());
+    app
+}
diff --git a/src/bin/cargo/command_prelude.rs b/src/bin/cargo/command_prelude.rs
new file mode 100644 (file)
index 0000000..2f6a046
--- /dev/null
@@ -0,0 +1,402 @@
+use std::path::PathBuf;
+use std::fs;
+
+use clap::{self, SubCommand};
+use cargo::CargoResult;
+use cargo::core::Workspace;
+use cargo::ops::{CompileFilter, CompileMode, CompileOptions, MessageFormat, NewOptions, Packages,
+                 VersionControl};
+use cargo::util::paths;
+use cargo::util::important_paths::find_root_manifest_for_wd;
+
+pub use clap::{AppSettings, Arg, ArgMatches};
+pub use cargo::{CliError, CliResult, Config};
+
+pub type App = clap::App<'static, 'static>;
+
+pub trait AppExt: Sized {
+    fn _arg(self, arg: Arg<'static, 'static>) -> Self;
+
+    fn arg_package_spec(
+        self,
+        package: &'static str,
+        all: &'static str,
+        exclude: &'static str,
+    ) -> Self {
+        self.arg_package_spec_simple(package)
+            ._arg(opt("all", all))
+            ._arg(multi_opt("exclude", "SPEC", exclude))
+    }
+
+    fn arg_package_spec_simple(self, package: &'static str) -> Self {
+        self._arg(multi_opt("package", "SPEC", package).short("p"))
+    }
+
+    fn arg_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,
+        example: &'static str,
+        examples: &'static str,
+        test: &'static str,
+        tests: &'static str,
+        bench: &'static str,
+        benches: &'static str,
+        all: &'static str,
+    ) -> Self {
+        self.arg_targets_lib_bin(lib, bin, bins)
+            ._arg(multi_opt("example", "NAME", example))
+            ._arg(opt("examples", examples))
+            ._arg(multi_opt("test", "NAME", test))
+            ._arg(opt("tests", tests))
+            ._arg(multi_opt("bench", "NAME", bench))
+            ._arg(opt("benches", benches))
+            ._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(multi_opt("bin", "NAME", bin))
+            ._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(multi_opt("bin", "NAME", bin))
+            ._arg(opt("bins", bins))
+            ._arg(multi_opt("example", "NAME", example))
+            ._arg(opt("examples", examples))
+    }
+
+    fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self {
+        self._arg(multi_opt("bin", "NAME", bin))
+            ._arg(multi_opt("example", "NAME", example))
+    }
+
+    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_doc(self, doc: &'static str) -> Self {
+        self._arg(opt("doc", doc))
+    }
+
+    fn arg_target_triple(self, target: &'static str) -> Self {
+        self._arg(opt("target", target).value_name("TRIPLE"))
+    }
+
+    fn arg_target_dir(self) -> Self {
+        self._arg(opt("target-dir", "Directory for all generated artifacts").value_name("DIRECTORY"))
+    }
+
+    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 AppExt 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 multi_opt(
+    name: &'static str,
+    value_name: &'static str,
+    help: &'static str,
+) -> Arg<'static, 'static> {
+    // Note that all `.multiple(true)` arguments in Cargo should specify
+    // `.number_of_values(1)` as well, so that `--foo val1 val2` is
+    // **not** parsed as `foo` with values ["val1", "val2"].
+    // `number_of_values` should become the default in clap 3.
+    opt(name, help)
+        .value_name(value_name)
+        .multiple(true)
+        .number_of_values(1)
+}
+
+pub fn subcommand(name: &'static str) -> App {
+    SubCommand::with_name(name).settings(&[
+        AppSettings::UnifiedHelpMessage,
+        AppSettings::DeriveDisplayOrder,
+        AppSettings::DontCollapseArgsInUsage,
+    ])
+}
+
+pub trait ArgMatchesExt {
+    fn value_of_u32(&self, name: &str) -> CargoResult<Option<u32>> {
+        let arg = match self._value_of(name) {
+            None => None,
+            Some(arg) => Some(arg.parse::<u32>().map_err(|_| {
+                clap::Error::value_validation_auto(format!("could not parse `{}` as a number", arg))
+            })?),
+        };
+        Ok(arg)
+    }
+
+    /// Returns value of the `name` command-line argument as an absolute path
+    fn value_of_path(&self, name: &str, config: &Config) -> Option<PathBuf> {
+        self._value_of(name).map(|path| config.cwd().join(path))
+    }
+
+    fn root_manifest(&self, config: &Config) -> CargoResult<PathBuf> {
+        if let Some(path) = self.value_of_path("manifest-path", config) {
+            // In general, we try to avoid normalizing paths in Cargo,
+            // but in this particular case we need it to fix #3586.
+            let path = paths::normalize_path(&path);
+            if !path.ends_with("Cargo.toml") {
+                bail!("the manifest-path must be a path to a Cargo.toml file")
+            }
+            if !fs::metadata(&path).is_ok() {
+                bail!(
+                    "manifest path `{}` does not exist",
+                    self._value_of("manifest-path").unwrap()
+                )
+            }
+            return Ok(path);
+        }
+        find_root_manifest_for_wd(config.cwd())
+    }
+
+    fn workspace<'a>(&self, config: &'a Config) -> CargoResult<Workspace<'a>> {
+        let root = self.root_manifest(config)?;
+        let mut ws = Workspace::new(&root, config)?;
+        if config.cli_unstable().avoid_dev_deps {
+            ws.set_require_optional_deps(false);
+        }
+        Ok(ws)
+    }
+
+    fn jobs(&self) -> CargoResult<Option<u32>> {
+        self.value_of_u32("jobs")
+    }
+
+    fn target(&self) -> Option<String> {
+        self._value_of("target").map(|s| s.to_string())
+    }
+
+    fn compile_options<'a>(
+        &self,
+        config: &'a Config,
+        mode: CompileMode,
+    ) -> CargoResult<CompileOptions<'a>> {
+        let spec = Packages::from_flags(
+            self._is_present("all"),
+            self._values_of("exclude"),
+            self._values_of("package"),
+        )?;
+
+        let message_format = match self._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: self.jobs()?,
+            target: self.target(),
+            features: self._values_of("features"),
+            all_features: self._is_present("all-features"),
+            no_default_features: self._is_present("no-default-features"),
+            spec,
+            mode,
+            release: self._is_present("release"),
+            filter: CompileFilter::new(
+                self._is_present("lib"),
+                self._values_of("bin"),
+                self._is_present("bins"),
+                self._values_of("test"),
+                self._is_present("tests"),
+                self._values_of("example"),
+                self._is_present("examples"),
+                self._values_of("bench"),
+                self._is_present("benches"),
+                self._is_present("all-targets"),
+            ),
+            message_format,
+            target_rustdoc_args: None,
+            target_rustc_args: None,
+            export_dir: None,
+        };
+        Ok(opts)
+    }
+
+    fn compile_options_for_single_package<'a>(
+        &self,
+        config: &'a Config,
+        mode: CompileMode,
+    ) -> CargoResult<CompileOptions<'a>> {
+        let mut compile_opts = self.compile_options(config, mode)?;
+        compile_opts.spec = Packages::Packages(self._values_of("package"));
+        Ok(compile_opts)
+    }
+
+    fn new_options(&self, config: &Config) -> CargoResult<NewOptions> {
+        let vcs = self._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,
+            self._is_present("bin"),
+            self._is_present("lib"),
+            self.value_of_path("path", config).unwrap(),
+            self._value_of("name").map(|s| s.to_string()),
+        )
+    }
+
+    fn registry(&self, config: &Config) -> CargoResult<Option<String>> {
+        match self._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),
+        }
+    }
+
+    fn index(&self, config: &Config) -> CargoResult<Option<String>> {
+        // 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 self._value_of("host") {
+            Some(host) => {
+                config.shell().warn(&msg)?;
+                Some(host.to_string())
+            }
+            None => self._value_of("index").map(|s| s.to_string()),
+        };
+        Ok(index)
+    }
+
+    fn _value_of(&self, name: &str) -> Option<&str>;
+
+    fn _values_of(&self, name: &str) -> Vec<String>;
+
+    fn _is_present(&self, name: &str) -> bool;
+}
+
+impl<'a> ArgMatchesExt for ArgMatches<'a> {
+    fn _value_of(&self, name: &str) -> Option<&str> {
+        self.value_of(name)
+    }
+
+    fn _values_of(&self, name: &str) -> Vec<String> {
+        self.values_of(name)
+            .unwrap_or_default()
+            .map(|s| s.to_string())
+            .collect()
+    }
+
+    fn _is_present(&self, name: &str) -> bool {
+        self.is_present(name)
+    }
+}
+
+pub fn values(args: &ArgMatches, name: &str) -> Vec<String> {
+    args.values_of(name)
+        .unwrap_or_default()
+        .map(|s| s.to_string())
+        .collect()
+}
diff --git a/src/bin/cargo/commands/bench.rs b/src/bin/cargo/commands/bench.rs
new file mode 100644 (file)
index 0000000..83e3ab5
--- /dev/null
@@ -0,0 +1,105 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode, TestOptions};
+
+pub fn cli() -> App {
+    subcommand("bench")
+        .setting(AppSettings::TrailingVarArg)
+        .about("Execute all benchmarks of a local package")
+        .arg(
+            Arg::with_name("BENCHNAME")
+                .help("If specified, only run benches containing this string in their names"),
+        )
+        .arg(
+            Arg::with_name("args")
+                .help("Arguments for the bench binary")
+                .multiple(true)
+                .last(true),
+        )
+        .arg_targets_all(
+            "Benchmark only this package's library",
+            "Benchmark only the specified binary",
+            "Benchmark all binaries",
+            "Benchmark only the specified example",
+            "Benchmark all examples",
+            "Benchmark only the specified test target",
+            "Benchmark all tests",
+            "Benchmark only the specified bench target",
+            "Benchmark all benches",
+            "Benchmark all targets (default)",
+        )
+        .arg(opt("no-run", "Compile, but don't run benchmarks"))
+        .arg_package_spec(
+            "Package to run benchmarks for",
+            "Benchmark all packages in the workspace",
+            "Exclude packages from the benchmark",
+        )
+        .arg_jobs()
+        .arg_features()
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .arg(opt(
+            "no-fail-fast",
+            "Run all benchmarks regardless of failure",
+        ))
+        .after_help(
+            "\
+The benchmark filtering argument `BENCHNAME` and all the arguments following the
+two dashes (`--`) are passed to the benchmark binaries and thus to libtest
+(rustc's built in unit-test and micro-benchmarking framework).  If you're
+passing arguments to both Cargo and the binary, the ones after `--` go to the
+binary, the ones before go to Cargo.  For details about libtest's arguments see
+the output of `cargo bench -- --help`.
+
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be benchmarked. If it is not given, then
+the current package is benchmarked. For more information on SPEC and its format,
+see the `cargo help pkgid` command.
+
+All packages in the workspace are benchmarked if the `--all` flag is supplied. The
+`--all` flag is automatically assumed for a virtual manifest.
+Note that `--exclude` has to be specified in conjunction with the `--all` flag.
+
+The --jobs argument affects the building of the benchmark executable but does
+not affect how many jobs are used when running the benchmarks.
+
+Compilation can be customized with the `bench` profile in the manifest.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let mut compile_opts = args.compile_options(config, CompileMode::Bench)?;
+    compile_opts.release = true;
+
+    let ops = TestOptions {
+        no_run: args.is_present("no-run"),
+        no_fail_fast: args.is_present("no-fail-fast"),
+        only_doc: false,
+        compile_opts,
+    };
+
+    let mut bench_args = vec![];
+    bench_args.extend(
+        args.value_of("BENCHNAME")
+            .into_iter()
+            .map(|s| s.to_string()),
+    );
+    bench_args.extend(
+        args.values_of("args")
+            .unwrap_or_default()
+            .map(|s| s.to_string()),
+    );
+
+    let err = ops::run_benches(&ws, &ops, &bench_args)?;
+    match err {
+        None => Ok(()),
+        Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) {
+            Some(i) => CliError::new(format_err!("bench failed"), i),
+            None => CliError::new(err.into(), 101),
+        }),
+    }
+}
diff --git a/src/bin/cargo/commands/build.rs b/src/bin/cargo/commands/build.rs
new file mode 100644 (file)
index 0000000..0ab86aa
--- /dev/null
@@ -0,0 +1,63 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode};
+
+pub fn cli() -> App {
+    subcommand("build")
+        .alias("b")
+        .about("Compile a local package and all of its dependencies")
+        .arg_package_spec(
+            "Package to build",
+            "Build all packages in the workspace",
+            "Exclude packages from the build",
+        )
+        .arg_jobs()
+        .arg_targets_all(
+            "Build only this package's library",
+            "Build only the specified binary",
+            "Build all binaries",
+            "Build only the specified example",
+            "Build all examples",
+            "Build only the specified test target",
+            "Build all tests",
+            "Build only the specified bench target",
+            "Build all benches",
+            "Build all targets (lib and bin targets by default)",
+        )
+        .arg_release("Build artifacts in release mode, with optimizations")
+        .arg_features()
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg(opt("out-dir", "Copy final artifacts to this directory").value_name("PATH"))
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be built. If it is not given, then the
+current package is built. For more information on SPEC and its format, see the
+`cargo help pkgid` command.
+
+All packages in the workspace are built if the `--all` flag is supplied. The
+`--all` flag is automatically assumed for a virtual manifest.
+Note that `--exclude` has to be specified in conjunction with the `--all` flag.
+
+Compilation can be configured via the use of profiles which are configured in
+the manifest. The default profile for this command is `dev`, but passing
+the --release flag will use the `release` profile instead.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let mut compile_opts = args.compile_options(config, CompileMode::Build)?;
+    compile_opts.export_dir = args.value_of_path("out-dir", config);
+    if compile_opts.export_dir.is_some() && !config.cli_unstable().unstable_options {
+        Err(format_err!(
+            "`--out-dir` flag is unstable, pass `-Z unstable-options` to enable it"
+        ))?;
+    };
+    ops::compile(&ws, &compile_opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/check.rs b/src/bin/cargo/commands/check.rs
new file mode 100644 (file)
index 0000000..e4295c5
--- /dev/null
@@ -0,0 +1,72 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode};
+
+pub fn cli() -> App {
+    subcommand("check")
+        .about("Check a local package and all of its dependencies for errors")
+        .arg_package_spec(
+            "Package(s) to check",
+            "Check all packages in the workspace",
+            "Exclude packages from the check",
+        )
+        .arg_jobs()
+        .arg_targets_all(
+            "Check only this package's library",
+            "Check only the specified binary",
+            "Check all binaries",
+            "Check only the specified example",
+            "Check all examples",
+            "Check only the specified test target",
+            "Check all tests",
+            "Check only the specified bench target",
+            "Check all benches",
+            "Check all targets (lib and bin targets by default)",
+        )
+        .arg_release("Check artifacts in release mode, with optimizations")
+        .arg(opt("profile", "Profile to build the selected target for").value_name("PROFILE"))
+        .arg_features()
+        .arg_target_triple("Check for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be built. If it is not given, then the
+current package is built. For more information on SPEC and its format, see the
+`cargo help pkgid` command.
+
+All packages in the workspace are checked if the `--all` flag is supplied. The
+`--all` flag is automatically assumed for a virtual manifest.
+Note that `--exclude` has to be specified in conjunction with the `--all` flag.
+
+Compilation can be configured via the use of profiles which are configured in
+the manifest. The default profile for this command is `dev`, but passing
+the --release flag will use the `release` profile instead.
+
+The `--profile test` flag can be used to check unit tests with the
+`#[cfg(test)]` attribute.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let test = match args.value_of("profile") {
+        Some("test") => true,
+        None => false,
+        Some(profile) => {
+            let err = format_err!(
+                "unknown profile: `{}`, only `test` is \
+                 currently supported",
+                profile
+            );
+            return Err(CliError::new(err, 101));
+        }
+    };
+    let mode = CompileMode::Check { test };
+    let compile_opts = args.compile_options(config, mode)?;
+    ops::compile(&ws, &compile_opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/clean.rs b/src/bin/cargo/commands/clean.rs
new file mode 100644 (file)
index 0000000..a7606a6
--- /dev/null
@@ -0,0 +1,35 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CleanOptions};
+
+pub fn cli() -> App {
+    subcommand("clean")
+        .about("Remove artifacts that cargo has generated in the past")
+        .arg_package_spec_simple("Package to clean artifacts for")
+        .arg_manifest_path()
+        .arg_target_triple("Target triple to clean output for (default all)")
+        .arg_target_dir()
+        .arg_release("Whether or not to clean release artifacts")
+        .arg_doc("Whether or not to clean just the documentation directory")
+        .after_help(
+            "\
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package's artifacts should be cleaned out. If it is not
+given, then all packages' artifacts are removed. For more information on SPEC
+and its format, see the `cargo help pkgid` command.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let opts = CleanOptions {
+        config,
+        spec: values(args, "package"),
+        target: args.target(),
+        release: args.is_present("release"),
+        doc: args.is_present("doc"),
+    };
+    ops::clean(&ws, &opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/doc.rs b/src/bin/cargo/commands/doc.rs
new file mode 100644 (file)
index 0000000..54ba967
--- /dev/null
@@ -0,0 +1,59 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode, DocOptions};
+
+pub fn cli() -> App {
+    subcommand("doc")
+        .about("Build a package's documentation")
+        .arg(opt(
+            "open",
+            "Opens the docs in a browser after the operation",
+        ))
+        .arg_package_spec(
+            "Package to document",
+            "Document all packages in the workspace",
+            "Exclude packages from the build",
+        )
+        .arg(opt("no-deps", "Don't build documentation for dependencies"))
+        .arg_jobs()
+        .arg_targets_lib_bin(
+            "Document only this package's library",
+            "Document only the specified binary",
+            "Document all binaries",
+        )
+        .arg_release("Build artifacts in release mode, with optimizations")
+        .arg_features()
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+By default the documentation for the local package and all dependencies is
+built. The output is all placed in `target/doc` in rustdoc's usual format.
+
+All packages in the workspace are documented if the `--all` flag is supplied. The
+`--all` flag is automatically assumed for a virtual manifest.
+Note that `--exclude` has to be specified in conjunction with the `--all` flag.
+
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be documented. If it is not given, then the
+current package is documented. For more information on SPEC and its format, see
+the `cargo help pkgid` command.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let mode = CompileMode::Doc {
+        deps: !args.is_present("no-deps"),
+    };
+    let compile_opts = args.compile_options(config, mode)?;
+    let doc_opts = DocOptions {
+        open_result: args.is_present("open"),
+        compile_opts,
+    };
+    ops::doc(&ws, &doc_opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/fetch.rs b/src/bin/cargo/commands/fetch.rs
new file mode 100644 (file)
index 0000000..f69ed25
--- /dev/null
@@ -0,0 +1,34 @@
+use command_prelude::*;
+
+use cargo::ops;
+use cargo::ops::FetchOptions;
+
+pub fn cli() -> App {
+    subcommand("fetch")
+        .about("Fetch dependencies of a package from the network")
+        .arg_manifest_path()
+        .arg_target_triple("Fetch dependencies for the target triple")
+        .after_help(
+            "\
+If a lockfile is available, this command will ensure that all of the git
+dependencies and/or registries dependencies are downloaded and locally
+available. The network is never touched after a `cargo fetch` unless
+the lockfile changes.
+
+If the lockfile is not available, then this is the equivalent of
+`cargo generate-lockfile`. A lockfile is generated and dependencies are also
+all updated.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+
+    let opts = FetchOptions {
+        config,
+        target: args.target(),
+    };
+    ops::fetch(&ws, &opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/generate_lockfile.rs b/src/bin/cargo/commands/generate_lockfile.rs
new file mode 100644 (file)
index 0000000..f730872
--- /dev/null
@@ -0,0 +1,27 @@
+use command_prelude::*;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("generate-lockfile")
+        .about("Generate the lockfile for a project")
+        .arg_manifest_path()
+        .after_help(
+            "\
+If a lockfile is available, this command will ensure that all of the git
+dependencies and/or registries dependencies are downloaded and locally
+available. The network is never touched after a `cargo fetch` unless
+the lockfile changes.
+
+If the lockfile is not available, then this is the equivalent of
+`cargo generate-lockfile`. A lockfile is generated and dependencies are also
+all updated.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    ops::generate_lockfile(&ws)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/git_checkout.rs b/src/bin/cargo/commands/git_checkout.rs
new file mode 100644 (file)
index 0000000..a9401f1
--- /dev/null
@@ -0,0 +1,36 @@
+use command_prelude::*;
+
+use cargo::core::{GitReference, Source, SourceId};
+use cargo::sources::GitSource;
+use cargo::util::ToUrl;
+
+pub fn cli() -> App {
+    subcommand("git-checkout")
+        .about("Checkout a copy of a Git repository")
+        .arg(
+            Arg::with_name("url")
+                .long("url")
+                .value_name("URL")
+                .required(true),
+        )
+        .arg(
+            Arg::with_name("reference")
+                .long("reference")
+                .value_name("REF")
+                .required(true),
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let url = args.value_of("url").unwrap().to_url()?;
+    let reference = args.value_of("reference").unwrap();
+
+    let reference = GitReference::Branch(reference.to_string());
+    let source_id = SourceId::for_git(&url, reference)?;
+
+    let mut source = GitSource::new(&source_id, config)?;
+
+    source.update()?;
+
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/init.rs b/src/bin/cargo/commands/init.rs
new file mode 100644 (file)
index 0000000..c32dead
--- /dev/null
@@ -0,0 +1,19 @@
+use command_prelude::*;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("init")
+        .about("Create a new cargo package in an existing directory")
+        .arg(Arg::with_name("path").default_value("."))
+        .arg_new_opts()
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let opts = args.new_options(config)?;
+    ops::init(&opts, config)?;
+    config
+        .shell()
+        .status("Created", format!("{} project", opts.kind))?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/install.rs b/src/bin/cargo/commands/install.rs
new file mode 100644 (file)
index 0000000..0acdd02
--- /dev/null
@@ -0,0 +1,122 @@
+use command_prelude::*;
+
+use cargo::core::{GitReference, SourceId};
+use cargo::ops::{self, CompileMode};
+use cargo::util::ToUrl;
+
+pub fn cli() -> App {
+    subcommand("install")
+        .about("Install a Rust binary")
+        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
+        .arg(
+            opt("version", "Specify a version to install from crates.io")
+                .alias("vers")
+                .value_name("VERSION"),
+        )
+        .arg(opt("git", "Git URL to install the specified crate from").value_name("URL"))
+        .arg(opt("branch", "Branch to use when installing from git").value_name("BRANCH"))
+        .arg(opt("tag", "Tag to use when installing from git").value_name("TAG"))
+        .arg(opt("rev", "Specific commit to use when installing from git").value_name("SHA"))
+        .arg(opt("path", "Filesystem path to local crate to install").value_name("PATH"))
+        .arg(opt(
+            "list",
+            "list all installed packages and their versions",
+        ))
+        .arg_jobs()
+        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
+        .arg_features()
+        .arg(opt("debug", "Build in debug mode instead of release mode"))
+        .arg_targets_bins_examples(
+            "Install only the specified binary",
+            "Install all binaries",
+            "Install only the specified example",
+            "Install all examples",
+        )
+        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
+        .after_help(
+            "\
+This command manages Cargo's local set of installed binary crates. Only packages
+which have [[bin]] targets can be installed, and all binaries are installed into
+the installation root's `bin` folder. The installation root is determined, in
+order of precedence, by `--root`, `$CARGO_INSTALL_ROOT`, the `install.root`
+configuration key, and finally the home directory (which is either
+`$CARGO_HOME` if set or `$HOME/.cargo` by default).
+
+There are multiple sources from which a crate can be installed. The default
+location is crates.io but the `--git` and `--path` flags can change this source.
+If the source contains more than one package (such as crates.io or a git
+repository with multiple crates) the `<crate>` argument is required to indicate
+which crate should be installed.
+
+Crates from crates.io can optionally specify the version they wish to install
+via the `--vers` flags, and similarly packages from git repositories can
+optionally specify the branch, tag, or revision that should be installed. If a
+crate has multiple binaries, the `--bin` argument can selectively install only
+one of them, and if you'd rather install examples the `--example` argument can
+be used as well.
+
+By default cargo will refuse to overwrite existing binaries. The `--force` flag
+enables overwriting existing binaries. Thus you can reinstall a crate with
+`cargo install --force <crate>`.
+
+As a special convenience, omitting the <crate> specification entirely will
+install the crate in the current directory. That is, `install` is equivalent to
+the more explicit `install --path .`.
+
+If the source is crates.io or `--git` then by default the crate will be built
+in a temporary target directory.  To avoid this, the target directory can be
+specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
+path.  In particular, this can be useful for caching build artifacts on
+continuous integration systems.",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let mut compile_opts = args.compile_options(config, CompileMode::Build)?;
+    compile_opts.release = !args.is_present("debug");
+
+    let krates = args.values_of("crate")
+        .unwrap_or_default()
+        .collect::<Vec<_>>();
+
+    let mut from_cwd = false;
+
+    let source = if let Some(url) = args.value_of("git") {
+        let url = url.to_url()?;
+        let gitref = if let Some(branch) = args.value_of("branch") {
+            GitReference::Branch(branch.to_string())
+        } else if let Some(tag) = args.value_of("tag") {
+            GitReference::Tag(tag.to_string())
+        } else if let Some(rev) = args.value_of("rev") {
+            GitReference::Rev(rev.to_string())
+        } else {
+            GitReference::Branch("master".to_string())
+        };
+        SourceId::for_git(&url, gitref)?
+    } else if let Some(path) = args.value_of_path("path", config) {
+        SourceId::for_path(&path)?
+    } else if krates.is_empty() {
+        from_cwd = true;
+        SourceId::for_path(config.cwd())?
+    } else {
+        SourceId::crates_io(config)?
+    };
+
+    let version = args.value_of("version");
+    let root = args.value_of("root");
+
+    if args.is_present("list") {
+        ops::install_list(root, config)?;
+    } else {
+        ops::install(
+            root,
+            krates,
+            &source,
+            from_cwd,
+            version,
+            &compile_opts,
+            args.is_present("force"),
+        )?;
+    }
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/locate_project.rs b/src/bin/cargo/commands/locate_project.rs
new file mode 100644 (file)
index 0000000..2e20ccf
--- /dev/null
@@ -0,0 +1,33 @@
+use command_prelude::*;
+
+use cargo::print_json;
+
+pub fn cli() -> App {
+    subcommand("locate-project")
+        .about("Print a JSON representation of a Cargo.toml file's location")
+        .arg_manifest_path()
+}
+
+#[derive(Serialize)]
+pub struct ProjectLocation {
+    root: String,
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let root = args.root_manifest(config)?;
+
+    let root = root.to_str()
+        .ok_or_else(|| {
+            format_err!(
+                "your project path contains characters \
+                 not representable in Unicode"
+            )
+        })
+        .map_err(|e| CliError::new(e, 1))?
+        .to_string();
+
+    let location = ProjectLocation { root };
+
+    print_json(&location);
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/login.rs b/src/bin/cargo/commands/login.rs
new file mode 100644 (file)
index 0000000..1999510
--- /dev/null
@@ -0,0 +1,58 @@
+use command_prelude::*;
+
+use std::io::{self, BufRead};
+
+use cargo::core::{Source, SourceId};
+use cargo::sources::RegistrySource;
+use cargo::util::{CargoError, CargoResultExt};
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("login")
+        .about(
+            "Save an api token from the registry locally. \
+             If token is not specified, it will be read from stdin.",
+        )
+        .arg(Arg::with_name("token"))
+        .arg(opt("host", "Host to set the token for").value_name("HOST"))
+        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let registry = args.registry(config)?;
+
+    let token = match args.value_of("token") {
+        Some(token) => token.to_string(),
+        None => {
+            let host = match registry {
+                Some(ref _registry) => {
+                    return Err(format_err!(
+                        "token must be provided when \
+                         --registry is provided."
+                    ).into());
+                }
+                None => {
+                    let src = SourceId::crates_io(config)?;
+                    let mut src = RegistrySource::remote(&src, config);
+                    src.update()?;
+                    let config = src.config()?.unwrap();
+                    args.value_of("host")
+                        .map(|s| s.to_string())
+                        .unwrap_or(config.api.unwrap())
+                }
+            };
+            println!("please visit {}me and paste the API Token below", host);
+            let mut line = String::new();
+            let input = io::stdin();
+            input
+                .lock()
+                .read_line(&mut line)
+                .chain_err(|| "failed to read stdin")
+                .map_err(CargoError::from)?;
+            line.trim().to_string()
+        }
+    };
+
+    ops::registry_login(config, token, registry)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/metadata.rs b/src/bin/cargo/commands/metadata.rs
new file mode 100644 (file)
index 0000000..b701acd
--- /dev/null
@@ -0,0 +1,53 @@
+use command_prelude::*;
+
+use cargo::ops::{self, OutputMetadataOptions};
+use cargo::print_json;
+
+pub fn cli() -> App {
+    subcommand("metadata")
+        .about(
+            "Output the resolved dependencies of a project, \
+             the concrete used versions including overrides, \
+             in machine-readable format",
+        )
+        .arg_features()
+        .arg(opt(
+            "no-deps",
+            "Output information only about the root package \
+             and don't fetch dependencies",
+        ))
+        .arg_manifest_path()
+        .arg(
+            opt("format-version", "Format version")
+                .value_name("VERSION")
+                .possible_value("1"),
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+
+    let version = match args.value_of("format-version") {
+        None => {
+            config.shell().warn(
+                "\
+                 please specify `--format-version` flag explicitly \
+                 to avoid compatibility problems",
+            )?;
+            1
+        }
+        Some(version) => version.parse().unwrap(),
+    };
+
+    let options = OutputMetadataOptions {
+        features: values(args, "features"),
+        all_features: args.is_present("all-features"),
+        no_default_features: args.is_present("no-default-features"),
+        no_deps: args.is_present("no-deps"),
+        version,
+    };
+
+    let result = ops::output_metadata(&ws, &options)?;
+    print_json(&result);
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/mod.rs b/src/bin/cargo/commands/mod.rs
new file mode 100644 (file)
index 0000000..fc829a8
--- /dev/null
@@ -0,0 +1,101 @@
+use command_prelude::*;
+
+pub fn builtin() -> Vec<App> {
+    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(),
+    ]
+}
+
+pub fn builtin_exec(cmd: &str) -> Option<fn(&mut Config, &ArgMatches) -> CliResult> {
+    let f = match cmd {
+        "bench" => bench::exec,
+        "build" => build::exec,
+        "check" => check::exec,
+        "clean" => clean::exec,
+        "doc" => doc::exec,
+        "fetch" => fetch::exec,
+        "generate-lockfile" => generate_lockfile::exec,
+        "git-checkout" => git_checkout::exec,
+        "init" => init::exec,
+        "install" => install::exec,
+        "locate-project" => locate_project::exec,
+        "login" => login::exec,
+        "metadata" => metadata::exec,
+        "new" => new::exec,
+        "owner" => owner::exec,
+        "package" => package::exec,
+        "pkgid" => pkgid::exec,
+        "publish" => publish::exec,
+        "read-manifest" => read_manifest::exec,
+        "run" => run::exec,
+        "rustc" => rustc::exec,
+        "rustdoc" => rustdoc::exec,
+        "search" => search::exec,
+        "test" => test::exec,
+        "uninstall" => uninstall::exec,
+        "update" => update::exec,
+        "verify-project" => verify_project::exec,
+        "version" => version::exec,
+        "yank" => yank::exec,
+        _ => return None,
+    };
+    Some(f)
+}
+
+pub mod bench;
+pub mod build;
+pub mod check;
+pub mod clean;
+pub mod doc;
+pub mod fetch;
+pub mod generate_lockfile;
+pub mod git_checkout;
+pub mod init;
+pub mod install;
+pub mod locate_project;
+pub mod login;
+pub mod metadata;
+pub mod new;
+pub mod owner;
+pub mod package;
+pub mod pkgid;
+pub mod publish;
+pub mod read_manifest;
+pub mod run;
+pub mod rustc;
+pub mod rustdoc;
+pub mod search;
+pub mod test;
+pub mod uninstall;
+pub mod update;
+pub mod verify_project;
+pub mod version;
+pub mod yank;
diff --git a/src/bin/cargo/commands/new.rs b/src/bin/cargo/commands/new.rs
new file mode 100644 (file)
index 0000000..ff84722
--- /dev/null
@@ -0,0 +1,26 @@
+use command_prelude::*;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("new")
+        .about("Create a new cargo package at <path>")
+        .arg(Arg::with_name("path").required(true))
+        .arg_new_opts()
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let opts = args.new_options(config)?;
+
+    ops::new(&opts, config)?;
+    let path = args.value_of("path").unwrap();
+    let project_name = if let Some(name) = args.value_of("name") {
+        name
+    } else {
+        path
+    };
+    config
+        .shell()
+        .status("Created", format!("{} `{}` project", opts.kind, project_name))?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/owner.rs b/src/bin/cargo/commands/owner.rs
new file mode 100644 (file)
index 0000000..f20be31
--- /dev/null
@@ -0,0 +1,49 @@
+use command_prelude::*;
+
+use cargo::ops::{self, OwnersOptions};
+
+pub fn cli() -> App {
+    subcommand("owner")
+        .about("Manage the owners of a crate on the registry")
+        .arg(Arg::with_name("crate"))
+        .arg(multi_opt("add", "LOGIN", "Name of a user or team to add as an owner").short("a"))
+        .arg(
+            multi_opt(
+                "remove",
+                "LOGIN",
+                "Name of a user or team to remove as an owner",
+            ).short("r"),
+        )
+        .arg(opt("list", "List owners of a crate").short("l"))
+        .arg(opt("index", "Registry index to modify owners for").value_name("INDEX"))
+        .arg(opt("token", "API token to use when authenticating").value_name("TOKEN"))
+        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+        .after_help(
+            "\
+    This command will modify the owners for a package
+    on the specified registry(or
+    default).Note that owners of a package can upload new versions, yank old
+    versions.Explicitly named owners can also modify the set of owners, so take
+    caution!
+
+        See http://doc.crates.io/crates-io.html#cargo-owner for detailed documentation
+        and troubleshooting.",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let registry = args.registry(config)?;
+    let opts = OwnersOptions {
+        krate: args.value_of("crate").map(|s| s.to_string()),
+        token: args.value_of("token").map(|s| s.to_string()),
+        index: args.value_of("index").map(|s| s.to_string()),
+        to_add: args.values_of("add")
+            .map(|xs| xs.map(|s| s.to_string()).collect()),
+        to_remove: args.values_of("remove")
+            .map(|xs| xs.map(|s| s.to_string()).collect()),
+        list: args.is_present("list"),
+        registry,
+    };
+    ops::modify_owners(config, &opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/package.rs b/src/bin/cargo/commands/package.rs
new file mode 100644 (file)
index 0000000..f5e9d91
--- /dev/null
@@ -0,0 +1,48 @@
+use command_prelude::*;
+
+use cargo::ops::{self, PackageOpts};
+
+pub fn cli() -> App {
+    subcommand("package")
+        .about("Assemble the local package into a distributable tarball")
+        .arg(
+            opt(
+                "list",
+                "Print files included in a package without making one",
+            ).short("l"),
+        )
+        .arg(opt(
+            "no-verify",
+            "Don't verify the contents by building them",
+        ))
+        .arg(opt(
+            "no-metadata",
+            "Ignore warnings about a lack of human-usable metadata",
+        ))
+        .arg(opt(
+            "allow-dirty",
+            "Allow dirty working directories to be packaged",
+        ))
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_jobs()
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    ops::package(
+        &ws,
+        &PackageOpts {
+            config,
+            verify: !args.is_present("no-verify"),
+            list: args.is_present("list"),
+            check_metadata: !args.is_present("no-metadata"),
+            allow_dirty: args.is_present("allow-dirty"),
+            target: args.target(),
+            jobs: args.jobs()?,
+            registry: None,
+        },
+    )?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/pkgid.rs b/src/bin/cargo/commands/pkgid.rs
new file mode 100644 (file)
index 0000000..7010092
--- /dev/null
@@ -0,0 +1,41 @@
+use command_prelude::*;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("pkgid")
+        .about("Print a fully qualified package specification")
+        .arg(Arg::with_name("spec"))
+        .arg_package("Argument to get the package id specifier for")
+        .arg_manifest_path()
+        .after_help(
+            "\
+Given a <spec> argument, print out the fully qualified package id specifier.
+This command will generate an error if <spec> is ambiguous as to which package
+it refers to in the dependency graph. If no <spec> is given, then the pkgid for
+the local package is printed.
+
+This command requires that a lockfile is available and dependencies have been
+fetched.
+
+Example Package IDs
+
+           pkgid                  |  name  |  version  |          url
+    |-----------------------------|--------|-----------|---------------------|
+     foo                          | foo    | *         | *
+     foo:1.2.3                    | foo    | 1.2.3     | *
+     crates.io/foo                | foo    | *         | *://crates.io/foo
+     crates.io/foo#1.2.3          | foo    | 1.2.3     | *://crates.io/foo
+     crates.io/bar#foo:1.2.3      | foo    | 1.2.3     | *://crates.io/bar
+     http://crates.io/foo#1.2.3   | foo    | 1.2.3     | http://crates.io/foo
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let spec = args.value_of("spec").or(args.value_of("package"));
+    let spec = ops::pkgid(&ws, spec)?;
+    println!("{}", spec);
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/publish.rs b/src/bin/cargo/commands/publish.rs
new file mode 100644 (file)
index 0000000..b50d361
--- /dev/null
@@ -0,0 +1,46 @@
+use command_prelude::*;
+
+use cargo::ops::{self, PublishOpts};
+
+pub fn cli() -> App {
+    subcommand("publish")
+        .about("Upload a package to the registry")
+        .arg_index()
+        .arg(opt("token", "Token to use when uploading").value_name("TOKEN"))
+        .arg(opt(
+            "no-verify",
+            "Don't verify the contents by building them",
+        ))
+        .arg(opt(
+            "allow-dirty",
+            "Allow dirty working directories to be packaged",
+        ))
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_jobs()
+        .arg(opt("dry-run", "Perform all checks without uploading"))
+        .arg(opt("registry", "Registry to publish to").value_name("REGISTRY"))
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let registry = args.registry(config)?;
+    let ws = args.workspace(config)?;
+    let index = args.index(config)?;
+
+    ops::publish(
+        &ws,
+        &PublishOpts {
+            config,
+            token: args.value_of("token").map(|s| s.to_string()),
+            index,
+            verify: !args.is_present("no-verify"),
+            allow_dirty: args.is_present("allow-dirty"),
+            target: args.target(),
+            jobs: args.jobs()?,
+            dry_run: args.is_present("dry-run"),
+            registry,
+        },
+    )?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/read_manifest.rs b/src/bin/cargo/commands/read_manifest.rs
new file mode 100644 (file)
index 0000000..1e54c79
--- /dev/null
@@ -0,0 +1,18 @@
+use command_prelude::*;
+
+use cargo::print_json;
+
+pub fn cli() -> App {
+    subcommand("read-manifest")
+        .about(
+            "Deprecated, use `cargo metadata --no-deps` instead.
+Print a JSON representation of a Cargo.toml manifest.",
+        )
+        .arg_manifest_path()
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    print_json(&ws.current()?);
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/run.rs b/src/bin/cargo/commands/run.rs
new file mode 100644 (file)
index 0000000..763263d
--- /dev/null
@@ -0,0 +1,69 @@
+use command_prelude::*;
+
+use cargo::core::Verbosity;
+use cargo::ops::{self, CompileFilter, CompileMode};
+
+pub fn cli() -> App {
+    subcommand("run")
+        .alias("r")
+        .setting(AppSettings::TrailingVarArg)
+        .about("Run the main binary of the local package (src/main.rs)")
+        .arg(Arg::with_name("args").multiple(true))
+        .arg_targets_bin_example(
+            "Name of the bin target to run",
+            "Name of the example target to run",
+        )
+        .arg_package("Package with the target to run")
+        .arg_jobs()
+        .arg_release("Build artifacts in release mode, with optimizations")
+        .arg_features()
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+If neither `--bin` nor `--example` are given, then if the project only has one
+bin target it will be run. Otherwise `--bin` specifies the bin target to run,
+and `--example` specifies the example target to run. At most one of `--bin` or
+`--example` can be provided.
+
+All the arguments following the two dashes (`--`) are passed to the binary to
+run. If you're passing arguments to both Cargo and the binary, the ones after
+`--` go to the binary, the ones before go to Cargo.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+
+    let mut compile_opts = args.compile_options_for_single_package(config, CompileMode::Build)?;
+    if !args.is_present("example") && !args.is_present("bin") {
+        compile_opts.filter = CompileFilter::Default {
+            required_features_filterable: false,
+        };
+    };
+    match ops::run(&ws, &compile_opts, &values(args, "args"))? {
+        None => Ok(()),
+        Some(err) => {
+            // If we never actually spawned the process then that sounds pretty
+            // bad and we always want to forward that up.
+            let exit = match err.exit {
+                Some(exit) => exit,
+                None => return Err(CliError::new(err.into(), 101)),
+            };
+
+            // If `-q` was passed then we suppress extra error information about
+            // a failed process, we assume the process itself printed out enough
+            // information about why it failed so we don't do so as well
+            let exit_code = exit.code().unwrap_or(101);
+            let is_quiet = config.shell().verbosity() == Verbosity::Quiet;
+            Err(if is_quiet {
+                CliError::code(exit_code)
+            } else {
+                CliError::new(err.into(), exit_code)
+            })
+        }
+    }
+}
diff --git a/src/bin/cargo/commands/rustc.rs b/src/bin/cargo/commands/rustc.rs
new file mode 100644 (file)
index 0000000..35fb59e
--- /dev/null
@@ -0,0 +1,74 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode};
+
+pub fn cli() -> App {
+    subcommand("rustc")
+        .setting(AppSettings::TrailingVarArg)
+        .about("Compile a package and all of its dependencies")
+        .arg(Arg::with_name("args").multiple(true))
+        .arg_package("Package to build")
+        .arg_jobs()
+        .arg_targets_all(
+            "Build only this package's library",
+            "Build only the specified binary",
+            "Build all binaries",
+            "Build only the specified example",
+            "Build all examples",
+            "Build only the specified test target",
+            "Build all tests",
+            "Build only the specified bench target",
+            "Build all benches",
+            "Build all targets (lib and bin targets by default)",
+        )
+        .arg_release("Build artifacts in release mode, with optimizations")
+        .arg(opt("profile", "Profile to build the selected target for").value_name("PROFILE"))
+        .arg_features()
+        .arg_target_triple("Target triple which compiles will be for")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+The specified target for the current package (or package specified by SPEC if
+provided) will be compiled along with all of its dependencies. The specified
+<args>... will all be passed to the final compiler invocation, not any of the
+dependencies. Note that the compiler will still unconditionally receive
+arguments such as -L, --extern, and --crate-type, and the specified <args>...
+will simply be added to the compiler invocation.
+
+This command requires that only one target is being compiled. If more than one
+target is available for the current package the filters of --lib, --bin, etc,
+must be used to select which target is compiled. To pass flags to all compiler
+processes spawned by Cargo, use the $RUSTFLAGS environment variable or the
+`build.rustflags` configuration option.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let mode = match args.value_of("profile") {
+        Some("dev") | None => CompileMode::Build,
+        Some("test") => CompileMode::Test,
+        Some("bench") => CompileMode::Bench,
+        Some("check") => CompileMode::Check { test: false },
+        Some(mode) => {
+            let err = format_err!(
+                "unknown profile: `{}`, use dev,
+                                   test, or bench",
+                mode
+            );
+            return Err(CliError::new(err, 101));
+        }
+    };
+    let mut compile_opts = args.compile_options_for_single_package(config, mode)?;
+    let target_args = values(args, "args");
+    compile_opts.target_rustc_args = if target_args.is_empty() {
+        None
+    } else {
+        Some(target_args)
+    };
+    ops::compile(&ws, &compile_opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/rustdoc.rs b/src/bin/cargo/commands/rustdoc.rs
new file mode 100644 (file)
index 0000000..301e654
--- /dev/null
@@ -0,0 +1,66 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode, DocOptions};
+
+pub fn cli() -> App {
+    subcommand("rustdoc")
+        .setting(AppSettings::TrailingVarArg)
+        .about("Build a package's documentation, using specified custom flags.")
+        .arg(Arg::with_name("args").multiple(true))
+        .arg(opt(
+            "open",
+            "Opens the docs in a browser after the operation",
+        ))
+        .arg_package("Package to document")
+        .arg_jobs()
+        .arg_targets_all(
+            "Build only this package's library",
+            "Build only the specified binary",
+            "Build all binaries",
+            "Build only the specified example",
+            "Build all examples",
+            "Build only the specified test target",
+            "Build all tests",
+            "Build only the specified bench target",
+            "Build all benches",
+            "Build all targets (default)",
+        )
+        .arg_release("Build artifacts in release mode, with optimizations")
+        .arg_features()
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+The specified target for the current package (or package specified by SPEC if
+provided) will be documented with the specified <opts>... being passed to the
+final rustdoc invocation. Dependencies will not be documented as part of this
+command.  Note that rustdoc will still unconditionally receive arguments such
+as -L, --extern, and --crate-type, and the specified <opts>...  will simply be
+added to the rustdoc invocation.
+
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be documented. If it is not given, then the
+current package is documented. For more information on SPEC and its format, see
+the `cargo help pkgid` command.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let mut compile_opts =
+        args.compile_options_for_single_package(config, CompileMode::Doc { deps: false })?;
+    let target_args = values(args, "args");
+    compile_opts.target_rustdoc_args = if target_args.is_empty() {
+        None
+    } else {
+        Some(target_args)
+    };
+    let doc_opts = DocOptions {
+        open_result: args.is_present("open"),
+        compile_opts,
+    };
+    ops::doc(&ws, &doc_opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/search.rs b/src/bin/cargo/commands/search.rs
new file mode 100644 (file)
index 0000000..0501d8e
--- /dev/null
@@ -0,0 +1,30 @@
+use command_prelude::*;
+
+use std::cmp::min;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("search")
+        .about("Search packages in crates.io")
+        .arg(Arg::with_name("query").multiple(true))
+        .arg_index()
+        .arg(
+            opt(
+                "limit",
+                "Limit the number of results (default: 10, max: 100)",
+            ).value_name("LIMIT"),
+        )
+        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let registry = args.registry(config)?;
+    let index = args.index(config)?;
+    let limit = args.value_of_u32("limit")?;
+    let limit = min(100, limit.unwrap_or(10));
+    let query: Vec<&str> = args.values_of("query").unwrap_or_default().collect();
+    let query: String = query.join("+");
+    ops::search(&query, config, index, limit, registry)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/test.rs b/src/bin/cargo/commands/test.rs
new file mode 100644 (file)
index 0000000..a25f62f
--- /dev/null
@@ -0,0 +1,137 @@
+use command_prelude::*;
+
+use cargo::ops::{self, CompileMode};
+
+pub fn cli() -> App {
+    subcommand("test")
+        .alias("t")
+        .setting(AppSettings::TrailingVarArg)
+        .about("Execute all unit and integration tests of a local package")
+        .arg(
+            Arg::with_name("TESTNAME")
+                .help("If specified, only run tests containing this string in their names"),
+        )
+        .arg(
+            Arg::with_name("args")
+                .help("Arguments for the test binary")
+                .multiple(true)
+                .last(true),
+        )
+        .arg_targets_all(
+            "Test only this package's library",
+            "Test only the specified binary",
+            "Test all binaries",
+            "Check that the specified examples compile",
+            "Check that all examples compile",
+            "Test only the specified test target",
+            "Test all tests",
+            "Test only the specified bench target",
+            "Test all benches",
+            "Test all targets (default)",
+        )
+        .arg(opt("doc", "Test only this library's documentation"))
+        .arg(opt("no-run", "Compile, but don't run tests"))
+        .arg(opt("no-fail-fast", "Run all tests regardless of failure"))
+        .arg_package_spec(
+            "Package to run tests for",
+            "Test all packages in the workspace",
+            "Exclude packages from the test",
+        )
+        .arg_jobs()
+        .arg_release("Build artifacts in release mode, with optimizations")
+        .arg_features()
+        .arg_target_triple("Build for the target triple")
+        .arg_target_dir()
+        .arg_manifest_path()
+        .arg_message_format()
+        .after_help(
+            "\
+The test filtering argument `TESTNAME` and all the arguments following the
+two dashes (`--`) are passed to the test binaries and thus to libtest
+(rustc's built in unit-test and micro-benchmarking framework).  If you're
+passing arguments to both Cargo and the binary, the ones after `--` go to the
+binary, the ones before go to Cargo.  For details about libtest's arguments see
+the output of `cargo test -- --help`.  As an example, this will run all
+tests with `foo` in their name on 3 threads in parallel:
+
+    cargo test foo -- --test-threads 3
+
+If the --package argument is given, then SPEC is a package id specification
+which indicates which package should be tested. If it is not given, then the
+current package is tested. For more information on SPEC and its format, see the
+`cargo help pkgid` command.
+
+All packages in the workspace are tested if the `--all` flag is supplied. The
+`--all` flag is automatically assumed for a virtual manifest.
+Note that `--exclude` has to be specified in conjunction with the `--all` flag.
+
+The --jobs argument affects the building of the test executable but does
+not affect how many jobs are used when running the tests. The default value
+for the --jobs argument is the number of CPUs. If you want to control the
+number of simultaneous running test cases, pass the `--test-threads` option
+to the test binaries:
+
+    cargo test -- --test-threads=1
+
+Compilation can be configured via the `test` profile in the manifest.
+
+By default the rust test harness hides output from test execution to
+keep results readable. Test output can be recovered (e.g. for debugging)
+by passing `--nocapture` to the test binaries:
+
+    cargo test -- --nocapture
+
+To get the list of all options available for the test binaries use this:
+
+    cargo test -- --help
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+
+    let mut compile_opts = args.compile_options(config, CompileMode::Test)?;
+    let doc = args.is_present("doc");
+    if doc {
+        compile_opts.mode = ops::CompileMode::Doctest;
+        compile_opts.filter = ops::CompileFilter::new(
+            true,
+            Vec::new(),
+            false,
+            Vec::new(),
+            false,
+            Vec::new(),
+            false,
+            Vec::new(),
+            false,
+            false,
+        );
+    }
+
+    let ops = ops::TestOptions {
+        no_run: args.is_present("no-run"),
+        no_fail_fast: args.is_present("no-fail-fast"),
+        only_doc: doc,
+        compile_opts,
+    };
+
+    // TESTNAME is actually an argument of the test binary, but it's
+    // important so we explicitly mention it and reconfigure
+    let mut test_args = vec![];
+    test_args.extend(args.value_of("TESTNAME").into_iter().map(|s| s.to_string()));
+    test_args.extend(
+        args.values_of("args")
+            .unwrap_or_default()
+            .map(|s| s.to_string()),
+    );
+
+    let err = ops::run_tests(&ws, &ops, &test_args)?;
+    return match err {
+        None => Ok(()),
+        Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) {
+            Some(i) => CliError::new(format_err!("{}", err.hint(&ws)), i),
+            None => CliError::new(err.into(), 101),
+        }),
+    };
+}
diff --git a/src/bin/cargo/commands/uninstall.rs b/src/bin/cargo/commands/uninstall.rs
new file mode 100644 (file)
index 0000000..2031851
--- /dev/null
@@ -0,0 +1,26 @@
+use command_prelude::*;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("uninstall")
+        .about("Remove a Rust binary")
+        .arg(Arg::with_name("spec").multiple(true))
+        .arg(multi_opt("bin", "NAME", "Only uninstall the binary NAME"))
+        .arg(opt("root", "Directory to uninstall packages from").value_name("DIR"))
+        .after_help(
+            "\
+The argument SPEC is a package id specification (see `cargo help pkgid`) to
+specify which crate should be uninstalled. By default all binaries are
+uninstalled for a crate but the `--bin` and `--example` flags can be used to
+only uninstall particular binaries.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let root = args.value_of("root");
+    let specs = args.values_of("spec").unwrap_or_default().collect();
+    ops::uninstall(root, specs, &values(args, "bin"), config)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/update.rs b/src/bin/cargo/commands/update.rs
new file mode 100644 (file)
index 0000000..c5a992a
--- /dev/null
@@ -0,0 +1,51 @@
+use command_prelude::*;
+
+use cargo::ops::{self, UpdateOptions};
+
+pub fn cli() -> App {
+    subcommand("update")
+        .about("Update dependencies as recorded in the local lock file")
+        .arg_package_spec_simple("Package to update")
+        .arg(opt(
+            "aggressive",
+            "Force updating all dependencies of <name> as well",
+        ))
+        .arg(opt("precise", "Update a single dependency to exactly PRECISE").value_name("PRECISE"))
+        .arg_manifest_path()
+        .after_help(
+            "\
+This command requires that a `Cargo.lock` already exists as generated by
+`cargo build` or related commands.
+
+If SPEC is given, then a conservative update of the lockfile will be
+performed. This means that only the dependency specified by SPEC will be
+updated. Its transitive dependencies will be updated only if SPEC cannot be
+updated without updating dependencies.  All other dependencies will remain
+locked at their currently recorded versions.
+
+If PRECISE is specified, then --aggressive must not also be specified. The
+argument PRECISE is a string representing a precise revision that the package
+being updated should be updated to. For example, if the package comes from a git
+repository, then PRECISE would be the exact revision that the repository should
+be updated to.
+
+If SPEC is not given, then all dependencies will be re-resolved and
+updated.
+
+For more information about package id specifications, see `cargo help pkgid`.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+
+    let update_opts = UpdateOptions {
+        aggressive: args.is_present("aggressive"),
+        precise: args.value_of("precise"),
+        to_update: values(args, "package"),
+        config,
+    };
+    ops::update_lockfile(&ws, &update_opts)?;
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/verify_project.rs b/src/bin/cargo/commands/verify_project.rs
new file mode 100644 (file)
index 0000000..eea65c7
--- /dev/null
@@ -0,0 +1,45 @@
+use command_prelude::*;
+
+use std::collections::HashMap;
+use std::process;
+use std::fs::File;
+use std::io::Read;
+
+use toml;
+
+use cargo::print_json;
+
+pub fn cli() -> App {
+    subcommand("verify-project")
+        .about("Check correctness of crate manifest")
+        .arg_manifest_path()
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    fn fail(reason: &str, value: &str) -> ! {
+        let mut h = HashMap::new();
+        h.insert(reason.to_string(), value.to_string());
+        print_json(&h);
+        process::exit(1)
+    }
+
+    let mut contents = String::new();
+    let filename = match args.root_manifest(config) {
+        Ok(filename) => filename,
+        Err(e) => fail("invalid", &e.to_string()),
+    };
+
+    let file = File::open(&filename);
+    match file.and_then(|mut f| f.read_to_string(&mut contents)) {
+        Ok(_) => {}
+        Err(e) => fail("invalid", &format!("error reading file: {}", e)),
+    };
+    if contents.parse::<toml::Value>().is_err() {
+        fail("invalid", "invalid-format");
+    }
+
+    let mut h = HashMap::new();
+    h.insert("success".to_string(), "true".to_string());
+    print_json(&h);
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/version.rs b/src/bin/cargo/commands/version.rs
new file mode 100644 (file)
index 0000000..0e9d5be
--- /dev/null
@@ -0,0 +1,12 @@
+use command_prelude::*;
+
+use cargo;
+
+pub fn cli() -> App {
+    subcommand("version").about("Show version information")
+}
+
+pub fn exec(_config: &mut Config, _args: &ArgMatches) -> CliResult {
+    println!("{}", cargo::version());
+    Ok(())
+}
diff --git a/src/bin/cargo/commands/yank.rs b/src/bin/cargo/commands/yank.rs
new file mode 100644 (file)
index 0000000..150474b
--- /dev/null
@@ -0,0 +1,43 @@
+use command_prelude::*;
+
+use cargo::ops;
+
+pub fn cli() -> App {
+    subcommand("yank")
+        .about("Remove a pushed crate from the index")
+        .arg(Arg::with_name("crate"))
+        .arg(opt("vers", "The version to yank or un-yank").value_name("VERSION"))
+        .arg(opt(
+            "undo",
+            "Undo a yank, putting a version back into the index",
+        ))
+        .arg(opt("index", "Registry index to yank from").value_name("INDEX"))
+        .arg(opt("token", "API token to use when authenticating").value_name("TOKEN"))
+        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
+        .after_help(
+            "\
+The yank command removes a previously pushed crate's version from the server's
+index. This command does not delete any data, and the crate will still be
+available for download via the registry's download link.
+
+Note that existing crates locked to a yanked version will still be able to
+download the yanked version to use it. Cargo will, however, not allow any new
+crates to be locked to any yanked version.
+",
+        )
+}
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let registry = args.registry(config)?;
+
+    ops::yank(
+        config,
+        args.value_of("crate").map(|s| s.to_string()),
+        args.value_of("vers").map(|s| s.to_string()),
+        args.value_of("token").map(|s| s.to_string()),
+        args.value_of("index").map(|s| s.to_string()),
+        args.is_present("undo"),
+        registry,
+    )?;
+    Ok(())
+}
diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs
new file mode 100644 (file)
index 0000000..7d7c7db
--- /dev/null
@@ -0,0 +1,212 @@
+extern crate cargo;
+extern crate clap;
+extern crate env_logger;
+#[macro_use]
+extern crate failure;
+extern crate git2_curl;
+extern crate log;
+#[macro_use]
+extern crate serde_derive;
+extern crate serde_json;
+extern crate toml;
+
+use std::env;
+use std::fs;
+use std::path::{Path, PathBuf};
+use std::collections::BTreeSet;
+
+use cargo::core::shell::Shell;
+use cargo::util::{self, lev_distance, CargoResult, CliResult, Config};
+use cargo::util::{CliError, ProcessError};
+
+mod cli;
+mod command_prelude;
+mod commands;
+
+fn main() {
+    env_logger::init();
+
+    let mut config = match Config::default() {
+        Ok(cfg) => cfg,
+        Err(e) => {
+            let mut shell = Shell::new();
+            cargo::exit_with_error(e.into(), &mut shell)
+        }
+    };
+
+    let result = {
+        init_git_transports(&mut config);
+        let _token = cargo::util::job::setup();
+        cli::main(&mut config)
+    };
+
+    match result {
+        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
+        Ok(()) => {}
+    }
+}
+
+fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
+    let alias_name = format!("alias.{}", command);
+    let mut result = Ok(None);
+    match config.get_string(&alias_name) {
+        Ok(value) => {
+            if let Some(record) = value {
+                let alias_commands = record
+                    .val
+                    .split_whitespace()
+                    .map(|s| s.to_string())
+                    .collect();
+                result = Ok(Some(alias_commands));
+            }
+        }
+        Err(_) => {
+            let value = config.get_list(&alias_name)?;
+            if let Some(record) = value {
+                let alias_commands: Vec<String> =
+                    record.val.iter().map(|s| s.0.to_string()).collect();
+                result = Ok(Some(alias_commands));
+            }
+        }
+    }
+    result
+}
+
+/// List all runnable commands
+fn list_commands(config: &Config) -> BTreeSet<(String, Option<String>)> {
+    let prefix = "cargo-";
+    let suffix = env::consts::EXE_SUFFIX;
+    let mut commands = BTreeSet::new();
+    for dir in search_directories(config) {
+        let entries = match fs::read_dir(dir) {
+            Ok(entries) => entries,
+            _ => continue,
+        };
+        for entry in entries.filter_map(|e| e.ok()) {
+            let path = entry.path();
+            let filename = match path.file_name().and_then(|s| s.to_str()) {
+                Some(filename) => filename,
+                _ => continue,
+            };
+            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
+                continue;
+            }
+            if is_executable(entry.path()) {
+                let end = filename.len() - suffix.len();
+                commands.insert((
+                    filename[prefix.len()..end].to_string(),
+                    Some(path.display().to_string()),
+                ));
+            }
+        }
+    }
+
+    for cmd in commands::builtin() {
+        commands.insert((cmd.get_name().to_string(), None));
+    }
+
+    commands
+}
+
+fn find_closest(config: &Config, cmd: &str) -> Option<String> {
+    let cmds = list_commands(config);
+    // Only consider candidates with a lev_distance of 3 or less so we don't
+    // suggest out-of-the-blue options.
+    let mut filtered = cmds.iter()
+        .map(|&(ref c, _)| (lev_distance(c, cmd), c))
+        .filter(|&(d, _)| d < 4)
+        .collect::<Vec<_>>();
+    filtered.sort_by(|a, b| a.0.cmp(&b.0));
+    filtered.get(0).map(|slot| slot.1.clone())
+}
+
+fn execute_external_subcommand(config: &Config, cmd: &str, args: &[&str]) -> CliResult {
+    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
+    let path = search_directories(config)
+        .iter()
+        .map(|dir| dir.join(&command_exe))
+        .find(|file| is_executable(file));
+    let command = match path {
+        Some(command) => command,
+        None => {
+            let err = match find_closest(config, cmd) {
+                Some(closest) => format_err!(
+                    "no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
+                    cmd,
+                    closest
+                ),
+                None => format_err!("no such subcommand: `{}`", cmd),
+            };
+            return Err(CliError::new(err, 101));
+        }
+    };
+
+    let cargo_exe = config.cargo_exe()?;
+    let err = match util::process(&command)
+        .env(cargo::CARGO_ENV, cargo_exe)
+        .args(args)
+        .exec_replace()
+    {
+        Ok(()) => return Ok(()),
+        Err(e) => e,
+    };
+
+    if let Some(perr) = err.downcast_ref::<ProcessError>() {
+        if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
+            return Err(CliError::code(code));
+        }
+    }
+    Err(CliError::new(err, 101))
+}
+
+#[cfg(unix)]
+fn is_executable<P: AsRef<Path>>(path: P) -> bool {
+    use std::os::unix::prelude::*;
+    fs::metadata(path)
+        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
+        .unwrap_or(false)
+}
+#[cfg(windows)]
+fn is_executable<P: AsRef<Path>>(path: P) -> bool {
+    fs::metadata(path)
+        .map(|metadata| metadata.is_file())
+        .unwrap_or(false)
+}
+
+fn search_directories(config: &Config) -> Vec<PathBuf> {
+    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
+    if let Some(val) = env::var_os("PATH") {
+        dirs.extend(env::split_paths(&val));
+    }
+    dirs
+}
+
+fn init_git_transports(config: &Config) {
+    // Only use a custom transport if any HTTP options are specified,
+    // such as proxies or custom certificate authorities. The custom
+    // transport, however, is not as well battle-tested.
+
+    match cargo::ops::needs_custom_http_transport(config) {
+        Ok(true) => {}
+        _ => return,
+    }
+
+    let handle = match cargo::ops::http_handle(config) {
+        Ok(handle) => handle,
+        Err(..) => return,
+    };
+
+    // The unsafety of the registration function derives from two aspects:
+    //
+    // 1. This call must be synchronized with all other registration calls as
+    //    well as construction of new transports.
+    // 2. The argument is leaked.
+    //
+    // We're clear on point (1) because this is only called at the start of this
+    // binary (we know what the state of the world looks like) and we're mostly
+    // clear on point (2) because we'd only free it after everything is done
+    // anyway
+    unsafe {
+        git2_curl::register(handle);
+    }
+}
diff --git a/src/bin/cli.rs b/src/bin/cli.rs
deleted file mode 100644 (file)
index 9fbd12c..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-extern crate clap;
-
-use clap::{AppSettings, Arg, ArgMatches};
-
-use cargo::{self, CliResult, Config};
-
-use super::list_commands;
-use super::commands;
-use command_prelude::*;
-
-pub fn main(config: &mut Config) -> CliResult {
-    let args = cli().get_matches_safe()?;
-
-    if args.value_of("unstable-features") == Some("help") {
-        println!(
-            "
-Available unstable (nightly-only) flags:
-
-    -Z avoid-dev-deps   -- Avoid installing dev-dependencies if possible
-    -Z minimal-versions -- Install minimal dependency versions instead of maximum
-    -Z no-index-update  -- Do not update the registry, avoids a network request for benchmarking
-    -Z offline          -- Offline mode that does not perform network requests
-    -Z unstable-options -- Allow the usage of unstable options such as --registry
-
-Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
-        );
-        return Ok(());
-    }
-
-    let is_verbose = args.occurrences_of("verbose") > 0;
-    if args.is_present("version") {
-        let version = cargo::version();
-        println!("{}", version);
-        if is_verbose {
-            println!(
-                "release: {}.{}.{}",
-                version.major, version.minor, version.patch
-            );
-            if let Some(ref cfg) = version.cfg_info {
-                if let Some(ref ci) = cfg.commit_info {
-                    println!("commit-hash: {}", ci.commit_hash);
-                    println!("commit-date: {}", ci.commit_date);
-                }
-            }
-        }
-        return Ok(());
-    }
-
-    if let Some(ref code) = args.value_of("explain") {
-        let mut procss = config.rustc(None)?.process();
-        procss.arg("--explain").arg(code).exec()?;
-        return Ok(());
-    }
-
-    if args.is_present("list") {
-        println!("Installed Commands:");
-        for command in list_commands(config) {
-            let (command, path) = command;
-            if is_verbose {
-                match path {
-                    Some(p) => println!("    {:<20} {}", command, p),
-                    None => println!("    {:<20}", command),
-                }
-            } else {
-                println!("    {}", command);
-            }
-        }
-        return Ok(());
-    }
-
-    let args = expand_aliases(config, args)?;
-
-    execute_subcommand(config, args)
-}
-
-fn expand_aliases(
-    config: &mut Config,
-    args: ArgMatches<'static>,
-) -> Result<ArgMatches<'static>, CliError> {
-    if let (cmd, Some(args)) = args.subcommand() {
-        match (
-            commands::builtin_exec(cmd),
-            super::aliased_command(config, cmd)?,
-        ) {
-            (None, Some(mut alias)) => {
-                alias.extend(
-                    args.values_of("")
-                        .unwrap_or_default()
-                        .map(|s| s.to_string()),
-                );
-                let args = cli()
-                    .setting(AppSettings::NoBinaryName)
-                    .get_matches_from_safe(alias)?;
-                return expand_aliases(config, args);
-            }
-            (Some(_), Some(_)) => {
-                config.shell().warn(format!(
-                    "alias `{}` is ignored, because it is shadowed by a built in command",
-                    cmd
-                ))?;
-            }
-            (_, None) => {}
-        }
-    };
-    Ok(args)
-}
-
-fn execute_subcommand(config: &mut Config, args: ArgMatches) -> CliResult {
-    let (cmd, subcommand_args) = match args.subcommand() {
-        (cmd, Some(args)) => (cmd, args),
-        _ => {
-            cli().print_help()?;
-            return Ok(());
-        }
-    };
-
-    let arg_target_dir = &subcommand_args.value_of_path("target-dir", config);
-
-    config.configure(
-        args.occurrences_of("verbose") as u32,
-        if args.is_present("quiet") {
-            Some(true)
-        } else {
-            None
-        },
-        &args.value_of("color").map(|s| s.to_string()),
-        args.is_present("frozen"),
-        args.is_present("locked"),
-        arg_target_dir,
-        &args.values_of_lossy("unstable-features")
-            .unwrap_or_default(),
-    )?;
-
-    if let Some(exec) = commands::builtin_exec(cmd) {
-        return exec(config, subcommand_args);
-    }
-
-    let mut ext_args: Vec<&str> = vec![cmd];
-    ext_args.extend(subcommand_args.values_of("").unwrap_or_default());
-    super::execute_external_subcommand(config, cmd, &ext_args)
-}
-
-fn cli() -> App {
-    let app = App::new("cargo")
-        .settings(&[
-            AppSettings::UnifiedHelpMessage,
-            AppSettings::DeriveDisplayOrder,
-            AppSettings::VersionlessSubcommands,
-            AppSettings::AllowExternalSubcommands,
-        ])
-        .about("")
-        .template(
-            "\
-Rust's package manager
-
-USAGE:
-    {usage}
-
-OPTIONS:
-{unified}
-
-Some common cargo commands are (see all commands with --list):
-    build       Compile the current project
-    check       Analyze the current project and report errors, but don't build object files
-    clean       Remove the target directory
-    doc         Build this project's and its dependencies' documentation
-    new         Create a new cargo project
-    init        Create a new cargo project in an existing directory
-    run         Build and execute src/main.rs
-    test        Run the tests
-    bench       Run the benchmarks
-    update      Update dependencies listed in Cargo.lock
-    search      Search registry for crates
-    publish     Package and upload this project to the registry
-    install     Install a Rust binary
-    uninstall   Uninstall a Rust binary
-
-See 'cargo help <command>' for more information on a specific command.\n",
-        )
-        .arg(opt("version", "Print version info and exit").short("V"))
-        .arg(opt("list", "List installed commands"))
-        .arg(opt("explain", "Run `rustc --explain CODE`").value_name("CODE"))
-        .arg(
-            opt(
-                "verbose",
-                "Use verbose output (-vv very verbose/build.rs output)",
-            ).short("v")
-                .multiple(true)
-                .global(true),
-        )
-        .arg(
-            opt("quiet", "No output printed to stdout")
-                .short("q")
-                .global(true),
-        )
-        .arg(
-            opt("color", "Coloring: auto, always, never")
-                .value_name("WHEN")
-                .global(true),
-        )
-        .arg(opt("frozen", "Require Cargo.lock and cache are up to date").global(true))
-        .arg(opt("locked", "Require Cargo.lock is up to date").global(true))
-        .arg(
-            Arg::with_name("unstable-features")
-                .help("Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details")
-                .short("Z")
-                .value_name("FLAG")
-                .multiple(true)
-                .number_of_values(1)
-                .global(true),
-        )
-        .subcommands(commands::builtin());
-    app
-}
diff --git a/src/bin/command_prelude.rs b/src/bin/command_prelude.rs
deleted file mode 100644 (file)
index 2f6a046..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-use std::path::PathBuf;
-use std::fs;
-
-use clap::{self, SubCommand};
-use cargo::CargoResult;
-use cargo::core::Workspace;
-use cargo::ops::{CompileFilter, CompileMode, CompileOptions, MessageFormat, NewOptions, Packages,
-                 VersionControl};
-use cargo::util::paths;
-use cargo::util::important_paths::find_root_manifest_for_wd;
-
-pub use clap::{AppSettings, Arg, ArgMatches};
-pub use cargo::{CliError, CliResult, Config};
-
-pub type App = clap::App<'static, 'static>;
-
-pub trait AppExt: Sized {
-    fn _arg(self, arg: Arg<'static, 'static>) -> Self;
-
-    fn arg_package_spec(
-        self,
-        package: &'static str,
-        all: &'static str,
-        exclude: &'static str,
-    ) -> Self {
-        self.arg_package_spec_simple(package)
-            ._arg(opt("all", all))
-            ._arg(multi_opt("exclude", "SPEC", exclude))
-    }
-
-    fn arg_package_spec_simple(self, package: &'static str) -> Self {
-        self._arg(multi_opt("package", "SPEC", package).short("p"))
-    }
-
-    fn arg_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,
-        example: &'static str,
-        examples: &'static str,
-        test: &'static str,
-        tests: &'static str,
-        bench: &'static str,
-        benches: &'static str,
-        all: &'static str,
-    ) -> Self {
-        self.arg_targets_lib_bin(lib, bin, bins)
-            ._arg(multi_opt("example", "NAME", example))
-            ._arg(opt("examples", examples))
-            ._arg(multi_opt("test", "NAME", test))
-            ._arg(opt("tests", tests))
-            ._arg(multi_opt("bench", "NAME", bench))
-            ._arg(opt("benches", benches))
-            ._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(multi_opt("bin", "NAME", bin))
-            ._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(multi_opt("bin", "NAME", bin))
-            ._arg(opt("bins", bins))
-            ._arg(multi_opt("example", "NAME", example))
-            ._arg(opt("examples", examples))
-    }
-
-    fn arg_targets_bin_example(self, bin: &'static str, example: &'static str) -> Self {
-        self._arg(multi_opt("bin", "NAME", bin))
-            ._arg(multi_opt("example", "NAME", example))
-    }
-
-    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_doc(self, doc: &'static str) -> Self {
-        self._arg(opt("doc", doc))
-    }
-
-    fn arg_target_triple(self, target: &'static str) -> Self {
-        self._arg(opt("target", target).value_name("TRIPLE"))
-    }
-
-    fn arg_target_dir(self) -> Self {
-        self._arg(opt("target-dir", "Directory for all generated artifacts").value_name("DIRECTORY"))
-    }
-
-    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 AppExt 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 multi_opt(
-    name: &'static str,
-    value_name: &'static str,
-    help: &'static str,
-) -> Arg<'static, 'static> {
-    // Note that all `.multiple(true)` arguments in Cargo should specify
-    // `.number_of_values(1)` as well, so that `--foo val1 val2` is
-    // **not** parsed as `foo` with values ["val1", "val2"].
-    // `number_of_values` should become the default in clap 3.
-    opt(name, help)
-        .value_name(value_name)
-        .multiple(true)
-        .number_of_values(1)
-}
-
-pub fn subcommand(name: &'static str) -> App {
-    SubCommand::with_name(name).settings(&[
-        AppSettings::UnifiedHelpMessage,
-        AppSettings::DeriveDisplayOrder,
-        AppSettings::DontCollapseArgsInUsage,
-    ])
-}
-
-pub trait ArgMatchesExt {
-    fn value_of_u32(&self, name: &str) -> CargoResult<Option<u32>> {
-        let arg = match self._value_of(name) {
-            None => None,
-            Some(arg) => Some(arg.parse::<u32>().map_err(|_| {
-                clap::Error::value_validation_auto(format!("could not parse `{}` as a number", arg))
-            })?),
-        };
-        Ok(arg)
-    }
-
-    /// Returns value of the `name` command-line argument as an absolute path
-    fn value_of_path(&self, name: &str, config: &Config) -> Option<PathBuf> {
-        self._value_of(name).map(|path| config.cwd().join(path))
-    }
-
-    fn root_manifest(&self, config: &Config) -> CargoResult<PathBuf> {
-        if let Some(path) = self.value_of_path("manifest-path", config) {
-            // In general, we try to avoid normalizing paths in Cargo,
-            // but in this particular case we need it to fix #3586.
-            let path = paths::normalize_path(&path);
-            if !path.ends_with("Cargo.toml") {
-                bail!("the manifest-path must be a path to a Cargo.toml file")
-            }
-            if !fs::metadata(&path).is_ok() {
-                bail!(
-                    "manifest path `{}` does not exist",
-                    self._value_of("manifest-path").unwrap()
-                )
-            }
-            return Ok(path);
-        }
-        find_root_manifest_for_wd(config.cwd())
-    }
-
-    fn workspace<'a>(&self, config: &'a Config) -> CargoResult<Workspace<'a>> {
-        let root = self.root_manifest(config)?;
-        let mut ws = Workspace::new(&root, config)?;
-        if config.cli_unstable().avoid_dev_deps {
-            ws.set_require_optional_deps(false);
-        }
-        Ok(ws)
-    }
-
-    fn jobs(&self) -> CargoResult<Option<u32>> {
-        self.value_of_u32("jobs")
-    }
-
-    fn target(&self) -> Option<String> {
-        self._value_of("target").map(|s| s.to_string())
-    }
-
-    fn compile_options<'a>(
-        &self,
-        config: &'a Config,
-        mode: CompileMode,
-    ) -> CargoResult<CompileOptions<'a>> {
-        let spec = Packages::from_flags(
-            self._is_present("all"),
-            self._values_of("exclude"),
-            self._values_of("package"),
-        )?;
-
-        let message_format = match self._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: self.jobs()?,
-            target: self.target(),
-            features: self._values_of("features"),
-            all_features: self._is_present("all-features"),
-            no_default_features: self._is_present("no-default-features"),
-            spec,
-            mode,
-            release: self._is_present("release"),
-            filter: CompileFilter::new(
-                self._is_present("lib"),
-                self._values_of("bin"),
-                self._is_present("bins"),
-                self._values_of("test"),
-                self._is_present("tests"),
-                self._values_of("example"),
-                self._is_present("examples"),
-                self._values_of("bench"),
-                self._is_present("benches"),
-                self._is_present("all-targets"),
-            ),
-            message_format,
-            target_rustdoc_args: None,
-            target_rustc_args: None,
-            export_dir: None,
-        };
-        Ok(opts)
-    }
-
-    fn compile_options_for_single_package<'a>(
-        &self,
-        config: &'a Config,
-        mode: CompileMode,
-    ) -> CargoResult<CompileOptions<'a>> {
-        let mut compile_opts = self.compile_options(config, mode)?;
-        compile_opts.spec = Packages::Packages(self._values_of("package"));
-        Ok(compile_opts)
-    }
-
-    fn new_options(&self, config: &Config) -> CargoResult<NewOptions> {
-        let vcs = self._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,
-            self._is_present("bin"),
-            self._is_present("lib"),
-            self.value_of_path("path", config).unwrap(),
-            self._value_of("name").map(|s| s.to_string()),
-        )
-    }
-
-    fn registry(&self, config: &Config) -> CargoResult<Option<String>> {
-        match self._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),
-        }
-    }
-
-    fn index(&self, config: &Config) -> CargoResult<Option<String>> {
-        // 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 self._value_of("host") {
-            Some(host) => {
-                config.shell().warn(&msg)?;
-                Some(host.to_string())
-            }
-            None => self._value_of("index").map(|s| s.to_string()),
-        };
-        Ok(index)
-    }
-
-    fn _value_of(&self, name: &str) -> Option<&str>;
-
-    fn _values_of(&self, name: &str) -> Vec<String>;
-
-    fn _is_present(&self, name: &str) -> bool;
-}
-
-impl<'a> ArgMatchesExt for ArgMatches<'a> {
-    fn _value_of(&self, name: &str) -> Option<&str> {
-        self.value_of(name)
-    }
-
-    fn _values_of(&self, name: &str) -> Vec<String> {
-        self.values_of(name)
-            .unwrap_or_default()
-            .map(|s| s.to_string())
-            .collect()
-    }
-
-    fn _is_present(&self, name: &str) -> bool {
-        self.is_present(name)
-    }
-}
-
-pub fn values(args: &ArgMatches, name: &str) -> Vec<String> {
-    args.values_of(name)
-        .unwrap_or_default()
-        .map(|s| s.to_string())
-        .collect()
-}
diff --git a/src/bin/commands/bench.rs b/src/bin/commands/bench.rs
deleted file mode 100644 (file)
index 83e3ab5..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode, TestOptions};
-
-pub fn cli() -> App {
-    subcommand("bench")
-        .setting(AppSettings::TrailingVarArg)
-        .about("Execute all benchmarks of a local package")
-        .arg(
-            Arg::with_name("BENCHNAME")
-                .help("If specified, only run benches containing this string in their names"),
-        )
-        .arg(
-            Arg::with_name("args")
-                .help("Arguments for the bench binary")
-                .multiple(true)
-                .last(true),
-        )
-        .arg_targets_all(
-            "Benchmark only this package's library",
-            "Benchmark only the specified binary",
-            "Benchmark all binaries",
-            "Benchmark only the specified example",
-            "Benchmark all examples",
-            "Benchmark only the specified test target",
-            "Benchmark all tests",
-            "Benchmark only the specified bench target",
-            "Benchmark all benches",
-            "Benchmark all targets (default)",
-        )
-        .arg(opt("no-run", "Compile, but don't run benchmarks"))
-        .arg_package_spec(
-            "Package to run benchmarks for",
-            "Benchmark all packages in the workspace",
-            "Exclude packages from the benchmark",
-        )
-        .arg_jobs()
-        .arg_features()
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .arg(opt(
-            "no-fail-fast",
-            "Run all benchmarks regardless of failure",
-        ))
-        .after_help(
-            "\
-The benchmark filtering argument `BENCHNAME` and all the arguments following the
-two dashes (`--`) are passed to the benchmark binaries and thus to libtest
-(rustc's built in unit-test and micro-benchmarking framework).  If you're
-passing arguments to both Cargo and the binary, the ones after `--` go to the
-binary, the ones before go to Cargo.  For details about libtest's arguments see
-the output of `cargo bench -- --help`.
-
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package should be benchmarked. If it is not given, then
-the current package is benchmarked. For more information on SPEC and its format,
-see the `cargo help pkgid` command.
-
-All packages in the workspace are benchmarked if the `--all` flag is supplied. The
-`--all` flag is automatically assumed for a virtual manifest.
-Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-
-The --jobs argument affects the building of the benchmark executable but does
-not affect how many jobs are used when running the benchmarks.
-
-Compilation can be customized with the `bench` profile in the manifest.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let mut compile_opts = args.compile_options(config, CompileMode::Bench)?;
-    compile_opts.release = true;
-
-    let ops = TestOptions {
-        no_run: args.is_present("no-run"),
-        no_fail_fast: args.is_present("no-fail-fast"),
-        only_doc: false,
-        compile_opts,
-    };
-
-    let mut bench_args = vec![];
-    bench_args.extend(
-        args.value_of("BENCHNAME")
-            .into_iter()
-            .map(|s| s.to_string()),
-    );
-    bench_args.extend(
-        args.values_of("args")
-            .unwrap_or_default()
-            .map(|s| s.to_string()),
-    );
-
-    let err = ops::run_benches(&ws, &ops, &bench_args)?;
-    match err {
-        None => Ok(()),
-        Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) {
-            Some(i) => CliError::new(format_err!("bench failed"), i),
-            None => CliError::new(err.into(), 101),
-        }),
-    }
-}
diff --git a/src/bin/commands/build.rs b/src/bin/commands/build.rs
deleted file mode 100644 (file)
index 0ab86aa..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode};
-
-pub fn cli() -> App {
-    subcommand("build")
-        .alias("b")
-        .about("Compile a local package and all of its dependencies")
-        .arg_package_spec(
-            "Package to build",
-            "Build all packages in the workspace",
-            "Exclude packages from the build",
-        )
-        .arg_jobs()
-        .arg_targets_all(
-            "Build only this package's library",
-            "Build only the specified binary",
-            "Build all binaries",
-            "Build only the specified example",
-            "Build all examples",
-            "Build only the specified test target",
-            "Build all tests",
-            "Build only the specified bench target",
-            "Build all benches",
-            "Build all targets (lib and bin targets by default)",
-        )
-        .arg_release("Build artifacts in release mode, with optimizations")
-        .arg_features()
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg(opt("out-dir", "Copy final artifacts to this directory").value_name("PATH"))
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package should be built. If it is not given, then the
-current package is built. For more information on SPEC and its format, see the
-`cargo help pkgid` command.
-
-All packages in the workspace are built if the `--all` flag is supplied. The
-`--all` flag is automatically assumed for a virtual manifest.
-Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-
-Compilation can be configured via the use of profiles which are configured in
-the manifest. The default profile for this command is `dev`, but passing
-the --release flag will use the `release` profile instead.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let mut compile_opts = args.compile_options(config, CompileMode::Build)?;
-    compile_opts.export_dir = args.value_of_path("out-dir", config);
-    if compile_opts.export_dir.is_some() && !config.cli_unstable().unstable_options {
-        Err(format_err!(
-            "`--out-dir` flag is unstable, pass `-Z unstable-options` to enable it"
-        ))?;
-    };
-    ops::compile(&ws, &compile_opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/check.rs b/src/bin/commands/check.rs
deleted file mode 100644 (file)
index e4295c5..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode};
-
-pub fn cli() -> App {
-    subcommand("check")
-        .about("Check a local package and all of its dependencies for errors")
-        .arg_package_spec(
-            "Package(s) to check",
-            "Check all packages in the workspace",
-            "Exclude packages from the check",
-        )
-        .arg_jobs()
-        .arg_targets_all(
-            "Check only this package's library",
-            "Check only the specified binary",
-            "Check all binaries",
-            "Check only the specified example",
-            "Check all examples",
-            "Check only the specified test target",
-            "Check all tests",
-            "Check only the specified bench target",
-            "Check all benches",
-            "Check all targets (lib and bin targets by default)",
-        )
-        .arg_release("Check artifacts in release mode, with optimizations")
-        .arg(opt("profile", "Profile to build the selected target for").value_name("PROFILE"))
-        .arg_features()
-        .arg_target_triple("Check for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package should be built. If it is not given, then the
-current package is built. For more information on SPEC and its format, see the
-`cargo help pkgid` command.
-
-All packages in the workspace are checked if the `--all` flag is supplied. The
-`--all` flag is automatically assumed for a virtual manifest.
-Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-
-Compilation can be configured via the use of profiles which are configured in
-the manifest. The default profile for this command is `dev`, but passing
-the --release flag will use the `release` profile instead.
-
-The `--profile test` flag can be used to check unit tests with the
-`#[cfg(test)]` attribute.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let test = match args.value_of("profile") {
-        Some("test") => true,
-        None => false,
-        Some(profile) => {
-            let err = format_err!(
-                "unknown profile: `{}`, only `test` is \
-                 currently supported",
-                profile
-            );
-            return Err(CliError::new(err, 101));
-        }
-    };
-    let mode = CompileMode::Check { test };
-    let compile_opts = args.compile_options(config, mode)?;
-    ops::compile(&ws, &compile_opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/clean.rs b/src/bin/commands/clean.rs
deleted file mode 100644 (file)
index a7606a6..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CleanOptions};
-
-pub fn cli() -> App {
-    subcommand("clean")
-        .about("Remove artifacts that cargo has generated in the past")
-        .arg_package_spec_simple("Package to clean artifacts for")
-        .arg_manifest_path()
-        .arg_target_triple("Target triple to clean output for (default all)")
-        .arg_target_dir()
-        .arg_release("Whether or not to clean release artifacts")
-        .arg_doc("Whether or not to clean just the documentation directory")
-        .after_help(
-            "\
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package's artifacts should be cleaned out. If it is not
-given, then all packages' artifacts are removed. For more information on SPEC
-and its format, see the `cargo help pkgid` command.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let opts = CleanOptions {
-        config,
-        spec: values(args, "package"),
-        target: args.target(),
-        release: args.is_present("release"),
-        doc: args.is_present("doc"),
-    };
-    ops::clean(&ws, &opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/doc.rs b/src/bin/commands/doc.rs
deleted file mode 100644 (file)
index 54ba967..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode, DocOptions};
-
-pub fn cli() -> App {
-    subcommand("doc")
-        .about("Build a package's documentation")
-        .arg(opt(
-            "open",
-            "Opens the docs in a browser after the operation",
-        ))
-        .arg_package_spec(
-            "Package to document",
-            "Document all packages in the workspace",
-            "Exclude packages from the build",
-        )
-        .arg(opt("no-deps", "Don't build documentation for dependencies"))
-        .arg_jobs()
-        .arg_targets_lib_bin(
-            "Document only this package's library",
-            "Document only the specified binary",
-            "Document all binaries",
-        )
-        .arg_release("Build artifacts in release mode, with optimizations")
-        .arg_features()
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-By default the documentation for the local package and all dependencies is
-built. The output is all placed in `target/doc` in rustdoc's usual format.
-
-All packages in the workspace are documented if the `--all` flag is supplied. The
-`--all` flag is automatically assumed for a virtual manifest.
-Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package should be documented. If it is not given, then the
-current package is documented. For more information on SPEC and its format, see
-the `cargo help pkgid` command.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let mode = CompileMode::Doc {
-        deps: !args.is_present("no-deps"),
-    };
-    let compile_opts = args.compile_options(config, mode)?;
-    let doc_opts = DocOptions {
-        open_result: args.is_present("open"),
-        compile_opts,
-    };
-    ops::doc(&ws, &doc_opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/fetch.rs b/src/bin/commands/fetch.rs
deleted file mode 100644 (file)
index f69ed25..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-use cargo::ops::FetchOptions;
-
-pub fn cli() -> App {
-    subcommand("fetch")
-        .about("Fetch dependencies of a package from the network")
-        .arg_manifest_path()
-        .arg_target_triple("Fetch dependencies for the target triple")
-        .after_help(
-            "\
-If a lockfile is available, this command will ensure that all of the git
-dependencies and/or registries dependencies are downloaded and locally
-available. The network is never touched after a `cargo fetch` unless
-the lockfile changes.
-
-If the lockfile is not available, then this is the equivalent of
-`cargo generate-lockfile`. A lockfile is generated and dependencies are also
-all updated.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-
-    let opts = FetchOptions {
-        config,
-        target: args.target(),
-    };
-    ops::fetch(&ws, &opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/generate_lockfile.rs b/src/bin/commands/generate_lockfile.rs
deleted file mode 100644 (file)
index f730872..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("generate-lockfile")
-        .about("Generate the lockfile for a project")
-        .arg_manifest_path()
-        .after_help(
-            "\
-If a lockfile is available, this command will ensure that all of the git
-dependencies and/or registries dependencies are downloaded and locally
-available. The network is never touched after a `cargo fetch` unless
-the lockfile changes.
-
-If the lockfile is not available, then this is the equivalent of
-`cargo generate-lockfile`. A lockfile is generated and dependencies are also
-all updated.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    ops::generate_lockfile(&ws)?;
-    Ok(())
-}
diff --git a/src/bin/commands/git_checkout.rs b/src/bin/commands/git_checkout.rs
deleted file mode 100644 (file)
index a9401f1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-use command_prelude::*;
-
-use cargo::core::{GitReference, Source, SourceId};
-use cargo::sources::GitSource;
-use cargo::util::ToUrl;
-
-pub fn cli() -> App {
-    subcommand("git-checkout")
-        .about("Checkout a copy of a Git repository")
-        .arg(
-            Arg::with_name("url")
-                .long("url")
-                .value_name("URL")
-                .required(true),
-        )
-        .arg(
-            Arg::with_name("reference")
-                .long("reference")
-                .value_name("REF")
-                .required(true),
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let url = args.value_of("url").unwrap().to_url()?;
-    let reference = args.value_of("reference").unwrap();
-
-    let reference = GitReference::Branch(reference.to_string());
-    let source_id = SourceId::for_git(&url, reference)?;
-
-    let mut source = GitSource::new(&source_id, config)?;
-
-    source.update()?;
-
-    Ok(())
-}
diff --git a/src/bin/commands/init.rs b/src/bin/commands/init.rs
deleted file mode 100644 (file)
index c32dead..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("init")
-        .about("Create a new cargo package in an existing directory")
-        .arg(Arg::with_name("path").default_value("."))
-        .arg_new_opts()
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let opts = args.new_options(config)?;
-    ops::init(&opts, config)?;
-    config
-        .shell()
-        .status("Created", format!("{} project", opts.kind))?;
-    Ok(())
-}
diff --git a/src/bin/commands/install.rs b/src/bin/commands/install.rs
deleted file mode 100644 (file)
index 0acdd02..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-use command_prelude::*;
-
-use cargo::core::{GitReference, SourceId};
-use cargo::ops::{self, CompileMode};
-use cargo::util::ToUrl;
-
-pub fn cli() -> App {
-    subcommand("install")
-        .about("Install a Rust binary")
-        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
-        .arg(
-            opt("version", "Specify a version to install from crates.io")
-                .alias("vers")
-                .value_name("VERSION"),
-        )
-        .arg(opt("git", "Git URL to install the specified crate from").value_name("URL"))
-        .arg(opt("branch", "Branch to use when installing from git").value_name("BRANCH"))
-        .arg(opt("tag", "Tag to use when installing from git").value_name("TAG"))
-        .arg(opt("rev", "Specific commit to use when installing from git").value_name("SHA"))
-        .arg(opt("path", "Filesystem path to local crate to install").value_name("PATH"))
-        .arg(opt(
-            "list",
-            "list all installed packages and their versions",
-        ))
-        .arg_jobs()
-        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
-        .arg_features()
-        .arg(opt("debug", "Build in debug mode instead of release mode"))
-        .arg_targets_bins_examples(
-            "Install only the specified binary",
-            "Install all binaries",
-            "Install only the specified example",
-            "Install all examples",
-        )
-        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
-        .after_help(
-            "\
-This command manages Cargo's local set of installed binary crates. Only packages
-which have [[bin]] targets can be installed, and all binaries are installed into
-the installation root's `bin` folder. The installation root is determined, in
-order of precedence, by `--root`, `$CARGO_INSTALL_ROOT`, the `install.root`
-configuration key, and finally the home directory (which is either
-`$CARGO_HOME` if set or `$HOME/.cargo` by default).
-
-There are multiple sources from which a crate can be installed. The default
-location is crates.io but the `--git` and `--path` flags can change this source.
-If the source contains more than one package (such as crates.io or a git
-repository with multiple crates) the `<crate>` argument is required to indicate
-which crate should be installed.
-
-Crates from crates.io can optionally specify the version they wish to install
-via the `--vers` flags, and similarly packages from git repositories can
-optionally specify the branch, tag, or revision that should be installed. If a
-crate has multiple binaries, the `--bin` argument can selectively install only
-one of them, and if you'd rather install examples the `--example` argument can
-be used as well.
-
-By default cargo will refuse to overwrite existing binaries. The `--force` flag
-enables overwriting existing binaries. Thus you can reinstall a crate with
-`cargo install --force <crate>`.
-
-As a special convenience, omitting the <crate> specification entirely will
-install the crate in the current directory. That is, `install` is equivalent to
-the more explicit `install --path .`.
-
-If the source is crates.io or `--git` then by default the crate will be built
-in a temporary target directory.  To avoid this, the target directory can be
-specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
-path.  In particular, this can be useful for caching build artifacts on
-continuous integration systems.",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let mut compile_opts = args.compile_options(config, CompileMode::Build)?;
-    compile_opts.release = !args.is_present("debug");
-
-    let krates = args.values_of("crate")
-        .unwrap_or_default()
-        .collect::<Vec<_>>();
-
-    let mut from_cwd = false;
-
-    let source = if let Some(url) = args.value_of("git") {
-        let url = url.to_url()?;
-        let gitref = if let Some(branch) = args.value_of("branch") {
-            GitReference::Branch(branch.to_string())
-        } else if let Some(tag) = args.value_of("tag") {
-            GitReference::Tag(tag.to_string())
-        } else if let Some(rev) = args.value_of("rev") {
-            GitReference::Rev(rev.to_string())
-        } else {
-            GitReference::Branch("master".to_string())
-        };
-        SourceId::for_git(&url, gitref)?
-    } else if let Some(path) = args.value_of_path("path", config) {
-        SourceId::for_path(&path)?
-    } else if krates.is_empty() {
-        from_cwd = true;
-        SourceId::for_path(config.cwd())?
-    } else {
-        SourceId::crates_io(config)?
-    };
-
-    let version = args.value_of("version");
-    let root = args.value_of("root");
-
-    if args.is_present("list") {
-        ops::install_list(root, config)?;
-    } else {
-        ops::install(
-            root,
-            krates,
-            &source,
-            from_cwd,
-            version,
-            &compile_opts,
-            args.is_present("force"),
-        )?;
-    }
-    Ok(())
-}
diff --git a/src/bin/commands/locate_project.rs b/src/bin/commands/locate_project.rs
deleted file mode 100644 (file)
index 2e20ccf..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-use command_prelude::*;
-
-use cargo::print_json;
-
-pub fn cli() -> App {
-    subcommand("locate-project")
-        .about("Print a JSON representation of a Cargo.toml file's location")
-        .arg_manifest_path()
-}
-
-#[derive(Serialize)]
-pub struct ProjectLocation {
-    root: String,
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let root = args.root_manifest(config)?;
-
-    let root = root.to_str()
-        .ok_or_else(|| {
-            format_err!(
-                "your project path contains characters \
-                 not representable in Unicode"
-            )
-        })
-        .map_err(|e| CliError::new(e, 1))?
-        .to_string();
-
-    let location = ProjectLocation { root };
-
-    print_json(&location);
-    Ok(())
-}
diff --git a/src/bin/commands/login.rs b/src/bin/commands/login.rs
deleted file mode 100644 (file)
index 1999510..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-use command_prelude::*;
-
-use std::io::{self, BufRead};
-
-use cargo::core::{Source, SourceId};
-use cargo::sources::RegistrySource;
-use cargo::util::{CargoError, CargoResultExt};
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("login")
-        .about(
-            "Save an api token from the registry locally. \
-             If token is not specified, it will be read from stdin.",
-        )
-        .arg(Arg::with_name("token"))
-        .arg(opt("host", "Host to set the token for").value_name("HOST"))
-        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let registry = args.registry(config)?;
-
-    let token = match args.value_of("token") {
-        Some(token) => token.to_string(),
-        None => {
-            let host = match registry {
-                Some(ref _registry) => {
-                    return Err(format_err!(
-                        "token must be provided when \
-                         --registry is provided."
-                    ).into());
-                }
-                None => {
-                    let src = SourceId::crates_io(config)?;
-                    let mut src = RegistrySource::remote(&src, config);
-                    src.update()?;
-                    let config = src.config()?.unwrap();
-                    args.value_of("host")
-                        .map(|s| s.to_string())
-                        .unwrap_or(config.api.unwrap())
-                }
-            };
-            println!("please visit {}me and paste the API Token below", host);
-            let mut line = String::new();
-            let input = io::stdin();
-            input
-                .lock()
-                .read_line(&mut line)
-                .chain_err(|| "failed to read stdin")
-                .map_err(CargoError::from)?;
-            line.trim().to_string()
-        }
-    };
-
-    ops::registry_login(config, token, registry)?;
-    Ok(())
-}
diff --git a/src/bin/commands/metadata.rs b/src/bin/commands/metadata.rs
deleted file mode 100644 (file)
index b701acd..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, OutputMetadataOptions};
-use cargo::print_json;
-
-pub fn cli() -> App {
-    subcommand("metadata")
-        .about(
-            "Output the resolved dependencies of a project, \
-             the concrete used versions including overrides, \
-             in machine-readable format",
-        )
-        .arg_features()
-        .arg(opt(
-            "no-deps",
-            "Output information only about the root package \
-             and don't fetch dependencies",
-        ))
-        .arg_manifest_path()
-        .arg(
-            opt("format-version", "Format version")
-                .value_name("VERSION")
-                .possible_value("1"),
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-
-    let version = match args.value_of("format-version") {
-        None => {
-            config.shell().warn(
-                "\
-                 please specify `--format-version` flag explicitly \
-                 to avoid compatibility problems",
-            )?;
-            1
-        }
-        Some(version) => version.parse().unwrap(),
-    };
-
-    let options = OutputMetadataOptions {
-        features: values(args, "features"),
-        all_features: args.is_present("all-features"),
-        no_default_features: args.is_present("no-default-features"),
-        no_deps: args.is_present("no-deps"),
-        version,
-    };
-
-    let result = ops::output_metadata(&ws, &options)?;
-    print_json(&result);
-    Ok(())
-}
diff --git a/src/bin/commands/mod.rs b/src/bin/commands/mod.rs
deleted file mode 100644 (file)
index fc829a8..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-use command_prelude::*;
-
-pub fn builtin() -> Vec<App> {
-    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(),
-    ]
-}
-
-pub fn builtin_exec(cmd: &str) -> Option<fn(&mut Config, &ArgMatches) -> CliResult> {
-    let f = match cmd {
-        "bench" => bench::exec,
-        "build" => build::exec,
-        "check" => check::exec,
-        "clean" => clean::exec,
-        "doc" => doc::exec,
-        "fetch" => fetch::exec,
-        "generate-lockfile" => generate_lockfile::exec,
-        "git-checkout" => git_checkout::exec,
-        "init" => init::exec,
-        "install" => install::exec,
-        "locate-project" => locate_project::exec,
-        "login" => login::exec,
-        "metadata" => metadata::exec,
-        "new" => new::exec,
-        "owner" => owner::exec,
-        "package" => package::exec,
-        "pkgid" => pkgid::exec,
-        "publish" => publish::exec,
-        "read-manifest" => read_manifest::exec,
-        "run" => run::exec,
-        "rustc" => rustc::exec,
-        "rustdoc" => rustdoc::exec,
-        "search" => search::exec,
-        "test" => test::exec,
-        "uninstall" => uninstall::exec,
-        "update" => update::exec,
-        "verify-project" => verify_project::exec,
-        "version" => version::exec,
-        "yank" => yank::exec,
-        _ => return None,
-    };
-    Some(f)
-}
-
-pub mod bench;
-pub mod build;
-pub mod check;
-pub mod clean;
-pub mod doc;
-pub mod fetch;
-pub mod generate_lockfile;
-pub mod git_checkout;
-pub mod init;
-pub mod install;
-pub mod locate_project;
-pub mod login;
-pub mod metadata;
-pub mod new;
-pub mod owner;
-pub mod package;
-pub mod pkgid;
-pub mod publish;
-pub mod read_manifest;
-pub mod run;
-pub mod rustc;
-pub mod rustdoc;
-pub mod search;
-pub mod test;
-pub mod uninstall;
-pub mod update;
-pub mod verify_project;
-pub mod version;
-pub mod yank;
diff --git a/src/bin/commands/new.rs b/src/bin/commands/new.rs
deleted file mode 100644 (file)
index ff84722..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("new")
-        .about("Create a new cargo package at <path>")
-        .arg(Arg::with_name("path").required(true))
-        .arg_new_opts()
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let opts = args.new_options(config)?;
-
-    ops::new(&opts, config)?;
-    let path = args.value_of("path").unwrap();
-    let project_name = if let Some(name) = args.value_of("name") {
-        name
-    } else {
-        path
-    };
-    config
-        .shell()
-        .status("Created", format!("{} `{}` project", opts.kind, project_name))?;
-    Ok(())
-}
diff --git a/src/bin/commands/owner.rs b/src/bin/commands/owner.rs
deleted file mode 100644 (file)
index f20be31..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, OwnersOptions};
-
-pub fn cli() -> App {
-    subcommand("owner")
-        .about("Manage the owners of a crate on the registry")
-        .arg(Arg::with_name("crate"))
-        .arg(multi_opt("add", "LOGIN", "Name of a user or team to add as an owner").short("a"))
-        .arg(
-            multi_opt(
-                "remove",
-                "LOGIN",
-                "Name of a user or team to remove as an owner",
-            ).short("r"),
-        )
-        .arg(opt("list", "List owners of a crate").short("l"))
-        .arg(opt("index", "Registry index to modify owners for").value_name("INDEX"))
-        .arg(opt("token", "API token to use when authenticating").value_name("TOKEN"))
-        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
-        .after_help(
-            "\
-    This command will modify the owners for a package
-    on the specified registry(or
-    default).Note that owners of a package can upload new versions, yank old
-    versions.Explicitly named owners can also modify the set of owners, so take
-    caution!
-
-        See http://doc.crates.io/crates-io.html#cargo-owner for detailed documentation
-        and troubleshooting.",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let registry = args.registry(config)?;
-    let opts = OwnersOptions {
-        krate: args.value_of("crate").map(|s| s.to_string()),
-        token: args.value_of("token").map(|s| s.to_string()),
-        index: args.value_of("index").map(|s| s.to_string()),
-        to_add: args.values_of("add")
-            .map(|xs| xs.map(|s| s.to_string()).collect()),
-        to_remove: args.values_of("remove")
-            .map(|xs| xs.map(|s| s.to_string()).collect()),
-        list: args.is_present("list"),
-        registry,
-    };
-    ops::modify_owners(config, &opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/package.rs b/src/bin/commands/package.rs
deleted file mode 100644 (file)
index f5e9d91..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, PackageOpts};
-
-pub fn cli() -> App {
-    subcommand("package")
-        .about("Assemble the local package into a distributable tarball")
-        .arg(
-            opt(
-                "list",
-                "Print files included in a package without making one",
-            ).short("l"),
-        )
-        .arg(opt(
-            "no-verify",
-            "Don't verify the contents by building them",
-        ))
-        .arg(opt(
-            "no-metadata",
-            "Ignore warnings about a lack of human-usable metadata",
-        ))
-        .arg(opt(
-            "allow-dirty",
-            "Allow dirty working directories to be packaged",
-        ))
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_jobs()
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    ops::package(
-        &ws,
-        &PackageOpts {
-            config,
-            verify: !args.is_present("no-verify"),
-            list: args.is_present("list"),
-            check_metadata: !args.is_present("no-metadata"),
-            allow_dirty: args.is_present("allow-dirty"),
-            target: args.target(),
-            jobs: args.jobs()?,
-            registry: None,
-        },
-    )?;
-    Ok(())
-}
diff --git a/src/bin/commands/pkgid.rs b/src/bin/commands/pkgid.rs
deleted file mode 100644 (file)
index 7010092..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("pkgid")
-        .about("Print a fully qualified package specification")
-        .arg(Arg::with_name("spec"))
-        .arg_package("Argument to get the package id specifier for")
-        .arg_manifest_path()
-        .after_help(
-            "\
-Given a <spec> argument, print out the fully qualified package id specifier.
-This command will generate an error if <spec> is ambiguous as to which package
-it refers to in the dependency graph. If no <spec> is given, then the pkgid for
-the local package is printed.
-
-This command requires that a lockfile is available and dependencies have been
-fetched.
-
-Example Package IDs
-
-           pkgid                  |  name  |  version  |          url
-    |-----------------------------|--------|-----------|---------------------|
-     foo                          | foo    | *         | *
-     foo:1.2.3                    | foo    | 1.2.3     | *
-     crates.io/foo                | foo    | *         | *://crates.io/foo
-     crates.io/foo#1.2.3          | foo    | 1.2.3     | *://crates.io/foo
-     crates.io/bar#foo:1.2.3      | foo    | 1.2.3     | *://crates.io/bar
-     http://crates.io/foo#1.2.3   | foo    | 1.2.3     | http://crates.io/foo
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let spec = args.value_of("spec").or(args.value_of("package"));
-    let spec = ops::pkgid(&ws, spec)?;
-    println!("{}", spec);
-    Ok(())
-}
diff --git a/src/bin/commands/publish.rs b/src/bin/commands/publish.rs
deleted file mode 100644 (file)
index b50d361..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, PublishOpts};
-
-pub fn cli() -> App {
-    subcommand("publish")
-        .about("Upload a package to the registry")
-        .arg_index()
-        .arg(opt("token", "Token to use when uploading").value_name("TOKEN"))
-        .arg(opt(
-            "no-verify",
-            "Don't verify the contents by building them",
-        ))
-        .arg(opt(
-            "allow-dirty",
-            "Allow dirty working directories to be packaged",
-        ))
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_jobs()
-        .arg(opt("dry-run", "Perform all checks without uploading"))
-        .arg(opt("registry", "Registry to publish to").value_name("REGISTRY"))
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let registry = args.registry(config)?;
-    let ws = args.workspace(config)?;
-    let index = args.index(config)?;
-
-    ops::publish(
-        &ws,
-        &PublishOpts {
-            config,
-            token: args.value_of("token").map(|s| s.to_string()),
-            index,
-            verify: !args.is_present("no-verify"),
-            allow_dirty: args.is_present("allow-dirty"),
-            target: args.target(),
-            jobs: args.jobs()?,
-            dry_run: args.is_present("dry-run"),
-            registry,
-        },
-    )?;
-    Ok(())
-}
diff --git a/src/bin/commands/read_manifest.rs b/src/bin/commands/read_manifest.rs
deleted file mode 100644 (file)
index 1e54c79..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-use command_prelude::*;
-
-use cargo::print_json;
-
-pub fn cli() -> App {
-    subcommand("read-manifest")
-        .about(
-            "Deprecated, use `cargo metadata --no-deps` instead.
-Print a JSON representation of a Cargo.toml manifest.",
-        )
-        .arg_manifest_path()
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    print_json(&ws.current()?);
-    Ok(())
-}
diff --git a/src/bin/commands/run.rs b/src/bin/commands/run.rs
deleted file mode 100644 (file)
index 763263d..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-use command_prelude::*;
-
-use cargo::core::Verbosity;
-use cargo::ops::{self, CompileFilter, CompileMode};
-
-pub fn cli() -> App {
-    subcommand("run")
-        .alias("r")
-        .setting(AppSettings::TrailingVarArg)
-        .about("Run the main binary of the local package (src/main.rs)")
-        .arg(Arg::with_name("args").multiple(true))
-        .arg_targets_bin_example(
-            "Name of the bin target to run",
-            "Name of the example target to run",
-        )
-        .arg_package("Package with the target to run")
-        .arg_jobs()
-        .arg_release("Build artifacts in release mode, with optimizations")
-        .arg_features()
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-If neither `--bin` nor `--example` are given, then if the project only has one
-bin target it will be run. Otherwise `--bin` specifies the bin target to run,
-and `--example` specifies the example target to run. At most one of `--bin` or
-`--example` can be provided.
-
-All the arguments following the two dashes (`--`) are passed to the binary to
-run. If you're passing arguments to both Cargo and the binary, the ones after
-`--` go to the binary, the ones before go to Cargo.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-
-    let mut compile_opts = args.compile_options_for_single_package(config, CompileMode::Build)?;
-    if !args.is_present("example") && !args.is_present("bin") {
-        compile_opts.filter = CompileFilter::Default {
-            required_features_filterable: false,
-        };
-    };
-    match ops::run(&ws, &compile_opts, &values(args, "args"))? {
-        None => Ok(()),
-        Some(err) => {
-            // If we never actually spawned the process then that sounds pretty
-            // bad and we always want to forward that up.
-            let exit = match err.exit {
-                Some(exit) => exit,
-                None => return Err(CliError::new(err.into(), 101)),
-            };
-
-            // If `-q` was passed then we suppress extra error information about
-            // a failed process, we assume the process itself printed out enough
-            // information about why it failed so we don't do so as well
-            let exit_code = exit.code().unwrap_or(101);
-            let is_quiet = config.shell().verbosity() == Verbosity::Quiet;
-            Err(if is_quiet {
-                CliError::code(exit_code)
-            } else {
-                CliError::new(err.into(), exit_code)
-            })
-        }
-    }
-}
diff --git a/src/bin/commands/rustc.rs b/src/bin/commands/rustc.rs
deleted file mode 100644 (file)
index 35fb59e..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode};
-
-pub fn cli() -> App {
-    subcommand("rustc")
-        .setting(AppSettings::TrailingVarArg)
-        .about("Compile a package and all of its dependencies")
-        .arg(Arg::with_name("args").multiple(true))
-        .arg_package("Package to build")
-        .arg_jobs()
-        .arg_targets_all(
-            "Build only this package's library",
-            "Build only the specified binary",
-            "Build all binaries",
-            "Build only the specified example",
-            "Build all examples",
-            "Build only the specified test target",
-            "Build all tests",
-            "Build only the specified bench target",
-            "Build all benches",
-            "Build all targets (lib and bin targets by default)",
-        )
-        .arg_release("Build artifacts in release mode, with optimizations")
-        .arg(opt("profile", "Profile to build the selected target for").value_name("PROFILE"))
-        .arg_features()
-        .arg_target_triple("Target triple which compiles will be for")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-The specified target for the current package (or package specified by SPEC if
-provided) will be compiled along with all of its dependencies. The specified
-<args>... will all be passed to the final compiler invocation, not any of the
-dependencies. Note that the compiler will still unconditionally receive
-arguments such as -L, --extern, and --crate-type, and the specified <args>...
-will simply be added to the compiler invocation.
-
-This command requires that only one target is being compiled. If more than one
-target is available for the current package the filters of --lib, --bin, etc,
-must be used to select which target is compiled. To pass flags to all compiler
-processes spawned by Cargo, use the $RUSTFLAGS environment variable or the
-`build.rustflags` configuration option.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let mode = match args.value_of("profile") {
-        Some("dev") | None => CompileMode::Build,
-        Some("test") => CompileMode::Test,
-        Some("bench") => CompileMode::Bench,
-        Some("check") => CompileMode::Check { test: false },
-        Some(mode) => {
-            let err = format_err!(
-                "unknown profile: `{}`, use dev,
-                                   test, or bench",
-                mode
-            );
-            return Err(CliError::new(err, 101));
-        }
-    };
-    let mut compile_opts = args.compile_options_for_single_package(config, mode)?;
-    let target_args = values(args, "args");
-    compile_opts.target_rustc_args = if target_args.is_empty() {
-        None
-    } else {
-        Some(target_args)
-    };
-    ops::compile(&ws, &compile_opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/rustdoc.rs b/src/bin/commands/rustdoc.rs
deleted file mode 100644 (file)
index 301e654..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode, DocOptions};
-
-pub fn cli() -> App {
-    subcommand("rustdoc")
-        .setting(AppSettings::TrailingVarArg)
-        .about("Build a package's documentation, using specified custom flags.")
-        .arg(Arg::with_name("args").multiple(true))
-        .arg(opt(
-            "open",
-            "Opens the docs in a browser after the operation",
-        ))
-        .arg_package("Package to document")
-        .arg_jobs()
-        .arg_targets_all(
-            "Build only this package's library",
-            "Build only the specified binary",
-            "Build all binaries",
-            "Build only the specified example",
-            "Build all examples",
-            "Build only the specified test target",
-            "Build all tests",
-            "Build only the specified bench target",
-            "Build all benches",
-            "Build all targets (default)",
-        )
-        .arg_release("Build artifacts in release mode, with optimizations")
-        .arg_features()
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-The specified target for the current package (or package specified by SPEC if
-provided) will be documented with the specified <opts>... being passed to the
-final rustdoc invocation. Dependencies will not be documented as part of this
-command.  Note that rustdoc will still unconditionally receive arguments such
-as -L, --extern, and --crate-type, and the specified <opts>...  will simply be
-added to the rustdoc invocation.
-
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package should be documented. If it is not given, then the
-current package is documented. For more information on SPEC and its format, see
-the `cargo help pkgid` command.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-    let mut compile_opts =
-        args.compile_options_for_single_package(config, CompileMode::Doc { deps: false })?;
-    let target_args = values(args, "args");
-    compile_opts.target_rustdoc_args = if target_args.is_empty() {
-        None
-    } else {
-        Some(target_args)
-    };
-    let doc_opts = DocOptions {
-        open_result: args.is_present("open"),
-        compile_opts,
-    };
-    ops::doc(&ws, &doc_opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/search.rs b/src/bin/commands/search.rs
deleted file mode 100644 (file)
index 0501d8e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-use command_prelude::*;
-
-use std::cmp::min;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("search")
-        .about("Search packages in crates.io")
-        .arg(Arg::with_name("query").multiple(true))
-        .arg_index()
-        .arg(
-            opt(
-                "limit",
-                "Limit the number of results (default: 10, max: 100)",
-            ).value_name("LIMIT"),
-        )
-        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let registry = args.registry(config)?;
-    let index = args.index(config)?;
-    let limit = args.value_of_u32("limit")?;
-    let limit = min(100, limit.unwrap_or(10));
-    let query: Vec<&str> = args.values_of("query").unwrap_or_default().collect();
-    let query: String = query.join("+");
-    ops::search(&query, config, index, limit, registry)?;
-    Ok(())
-}
diff --git a/src/bin/commands/test.rs b/src/bin/commands/test.rs
deleted file mode 100644 (file)
index a25f62f..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, CompileMode};
-
-pub fn cli() -> App {
-    subcommand("test")
-        .alias("t")
-        .setting(AppSettings::TrailingVarArg)
-        .about("Execute all unit and integration tests of a local package")
-        .arg(
-            Arg::with_name("TESTNAME")
-                .help("If specified, only run tests containing this string in their names"),
-        )
-        .arg(
-            Arg::with_name("args")
-                .help("Arguments for the test binary")
-                .multiple(true)
-                .last(true),
-        )
-        .arg_targets_all(
-            "Test only this package's library",
-            "Test only the specified binary",
-            "Test all binaries",
-            "Check that the specified examples compile",
-            "Check that all examples compile",
-            "Test only the specified test target",
-            "Test all tests",
-            "Test only the specified bench target",
-            "Test all benches",
-            "Test all targets (default)",
-        )
-        .arg(opt("doc", "Test only this library's documentation"))
-        .arg(opt("no-run", "Compile, but don't run tests"))
-        .arg(opt("no-fail-fast", "Run all tests regardless of failure"))
-        .arg_package_spec(
-            "Package to run tests for",
-            "Test all packages in the workspace",
-            "Exclude packages from the test",
-        )
-        .arg_jobs()
-        .arg_release("Build artifacts in release mode, with optimizations")
-        .arg_features()
-        .arg_target_triple("Build for the target triple")
-        .arg_target_dir()
-        .arg_manifest_path()
-        .arg_message_format()
-        .after_help(
-            "\
-The test filtering argument `TESTNAME` and all the arguments following the
-two dashes (`--`) are passed to the test binaries and thus to libtest
-(rustc's built in unit-test and micro-benchmarking framework).  If you're
-passing arguments to both Cargo and the binary, the ones after `--` go to the
-binary, the ones before go to Cargo.  For details about libtest's arguments see
-the output of `cargo test -- --help`.  As an example, this will run all
-tests with `foo` in their name on 3 threads in parallel:
-
-    cargo test foo -- --test-threads 3
-
-If the --package argument is given, then SPEC is a package id specification
-which indicates which package should be tested. If it is not given, then the
-current package is tested. For more information on SPEC and its format, see the
-`cargo help pkgid` command.
-
-All packages in the workspace are tested if the `--all` flag is supplied. The
-`--all` flag is automatically assumed for a virtual manifest.
-Note that `--exclude` has to be specified in conjunction with the `--all` flag.
-
-The --jobs argument affects the building of the test executable but does
-not affect how many jobs are used when running the tests. The default value
-for the --jobs argument is the number of CPUs. If you want to control the
-number of simultaneous running test cases, pass the `--test-threads` option
-to the test binaries:
-
-    cargo test -- --test-threads=1
-
-Compilation can be configured via the `test` profile in the manifest.
-
-By default the rust test harness hides output from test execution to
-keep results readable. Test output can be recovered (e.g. for debugging)
-by passing `--nocapture` to the test binaries:
-
-    cargo test -- --nocapture
-
-To get the list of all options available for the test binaries use this:
-
-    cargo test -- --help
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-
-    let mut compile_opts = args.compile_options(config, CompileMode::Test)?;
-    let doc = args.is_present("doc");
-    if doc {
-        compile_opts.mode = ops::CompileMode::Doctest;
-        compile_opts.filter = ops::CompileFilter::new(
-            true,
-            Vec::new(),
-            false,
-            Vec::new(),
-            false,
-            Vec::new(),
-            false,
-            Vec::new(),
-            false,
-            false,
-        );
-    }
-
-    let ops = ops::TestOptions {
-        no_run: args.is_present("no-run"),
-        no_fail_fast: args.is_present("no-fail-fast"),
-        only_doc: doc,
-        compile_opts,
-    };
-
-    // TESTNAME is actually an argument of the test binary, but it's
-    // important so we explicitly mention it and reconfigure
-    let mut test_args = vec![];
-    test_args.extend(args.value_of("TESTNAME").into_iter().map(|s| s.to_string()));
-    test_args.extend(
-        args.values_of("args")
-            .unwrap_or_default()
-            .map(|s| s.to_string()),
-    );
-
-    let err = ops::run_tests(&ws, &ops, &test_args)?;
-    return match err {
-        None => Ok(()),
-        Some(err) => Err(match err.exit.as_ref().and_then(|e| e.code()) {
-            Some(i) => CliError::new(format_err!("{}", err.hint(&ws)), i),
-            None => CliError::new(err.into(), 101),
-        }),
-    };
-}
diff --git a/src/bin/commands/uninstall.rs b/src/bin/commands/uninstall.rs
deleted file mode 100644 (file)
index 2031851..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("uninstall")
-        .about("Remove a Rust binary")
-        .arg(Arg::with_name("spec").multiple(true))
-        .arg(multi_opt("bin", "NAME", "Only uninstall the binary NAME"))
-        .arg(opt("root", "Directory to uninstall packages from").value_name("DIR"))
-        .after_help(
-            "\
-The argument SPEC is a package id specification (see `cargo help pkgid`) to
-specify which crate should be uninstalled. By default all binaries are
-uninstalled for a crate but the `--bin` and `--example` flags can be used to
-only uninstall particular binaries.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let root = args.value_of("root");
-    let specs = args.values_of("spec").unwrap_or_default().collect();
-    ops::uninstall(root, specs, &values(args, "bin"), config)?;
-    Ok(())
-}
diff --git a/src/bin/commands/update.rs b/src/bin/commands/update.rs
deleted file mode 100644 (file)
index c5a992a..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops::{self, UpdateOptions};
-
-pub fn cli() -> App {
-    subcommand("update")
-        .about("Update dependencies as recorded in the local lock file")
-        .arg_package_spec_simple("Package to update")
-        .arg(opt(
-            "aggressive",
-            "Force updating all dependencies of <name> as well",
-        ))
-        .arg(opt("precise", "Update a single dependency to exactly PRECISE").value_name("PRECISE"))
-        .arg_manifest_path()
-        .after_help(
-            "\
-This command requires that a `Cargo.lock` already exists as generated by
-`cargo build` or related commands.
-
-If SPEC is given, then a conservative update of the lockfile will be
-performed. This means that only the dependency specified by SPEC will be
-updated. Its transitive dependencies will be updated only if SPEC cannot be
-updated without updating dependencies.  All other dependencies will remain
-locked at their currently recorded versions.
-
-If PRECISE is specified, then --aggressive must not also be specified. The
-argument PRECISE is a string representing a precise revision that the package
-being updated should be updated to. For example, if the package comes from a git
-repository, then PRECISE would be the exact revision that the repository should
-be updated to.
-
-If SPEC is not given, then all dependencies will be re-resolved and
-updated.
-
-For more information about package id specifications, see `cargo help pkgid`.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let ws = args.workspace(config)?;
-
-    let update_opts = UpdateOptions {
-        aggressive: args.is_present("aggressive"),
-        precise: args.value_of("precise"),
-        to_update: values(args, "package"),
-        config,
-    };
-    ops::update_lockfile(&ws, &update_opts)?;
-    Ok(())
-}
diff --git a/src/bin/commands/verify_project.rs b/src/bin/commands/verify_project.rs
deleted file mode 100644 (file)
index eea65c7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-use command_prelude::*;
-
-use std::collections::HashMap;
-use std::process;
-use std::fs::File;
-use std::io::Read;
-
-use toml;
-
-use cargo::print_json;
-
-pub fn cli() -> App {
-    subcommand("verify-project")
-        .about("Check correctness of crate manifest")
-        .arg_manifest_path()
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    fn fail(reason: &str, value: &str) -> ! {
-        let mut h = HashMap::new();
-        h.insert(reason.to_string(), value.to_string());
-        print_json(&h);
-        process::exit(1)
-    }
-
-    let mut contents = String::new();
-    let filename = match args.root_manifest(config) {
-        Ok(filename) => filename,
-        Err(e) => fail("invalid", &e.to_string()),
-    };
-
-    let file = File::open(&filename);
-    match file.and_then(|mut f| f.read_to_string(&mut contents)) {
-        Ok(_) => {}
-        Err(e) => fail("invalid", &format!("error reading file: {}", e)),
-    };
-    if contents.parse::<toml::Value>().is_err() {
-        fail("invalid", "invalid-format");
-    }
-
-    let mut h = HashMap::new();
-    h.insert("success".to_string(), "true".to_string());
-    print_json(&h);
-    Ok(())
-}
diff --git a/src/bin/commands/version.rs b/src/bin/commands/version.rs
deleted file mode 100644 (file)
index 0e9d5be..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-use command_prelude::*;
-
-use cargo;
-
-pub fn cli() -> App {
-    subcommand("version").about("Show version information")
-}
-
-pub fn exec(_config: &mut Config, _args: &ArgMatches) -> CliResult {
-    println!("{}", cargo::version());
-    Ok(())
-}
diff --git a/src/bin/commands/yank.rs b/src/bin/commands/yank.rs
deleted file mode 100644 (file)
index 150474b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-use command_prelude::*;
-
-use cargo::ops;
-
-pub fn cli() -> App {
-    subcommand("yank")
-        .about("Remove a pushed crate from the index")
-        .arg(Arg::with_name("crate"))
-        .arg(opt("vers", "The version to yank or un-yank").value_name("VERSION"))
-        .arg(opt(
-            "undo",
-            "Undo a yank, putting a version back into the index",
-        ))
-        .arg(opt("index", "Registry index to yank from").value_name("INDEX"))
-        .arg(opt("token", "API token to use when authenticating").value_name("TOKEN"))
-        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
-        .after_help(
-            "\
-The yank command removes a previously pushed crate's version from the server's
-index. This command does not delete any data, and the crate will still be
-available for download via the registry's download link.
-
-Note that existing crates locked to a yanked version will still be able to
-download the yanked version to use it. Cargo will, however, not allow any new
-crates to be locked to any yanked version.
-",
-        )
-}
-
-pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
-    let registry = args.registry(config)?;
-
-    ops::yank(
-        config,
-        args.value_of("crate").map(|s| s.to_string()),
-        args.value_of("vers").map(|s| s.to_string()),
-        args.value_of("token").map(|s| s.to_string()),
-        args.value_of("index").map(|s| s.to_string()),
-        args.is_present("undo"),
-        registry,
-    )?;
-    Ok(())
-}