File per command
authorAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 12 Mar 2018 21:06:04 +0000 (00:06 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 12 Mar 2018 21:06:04 +0000 (00:06 +0300)
32 files changed:
src/bin/cli.rs
src/bin/command_prelude.rs
src/bin/commands/bench.rs
src/bin/commands/build.rs
src/bin/commands/check.rs
src/bin/commands/clean.rs
src/bin/commands/doc.rs
src/bin/commands/fetch.rs
src/bin/commands/generate_lockfile.rs
src/bin/commands/git_checkout.rs
src/bin/commands/init.rs
src/bin/commands/install.rs
src/bin/commands/locate_project.rs
src/bin/commands/login.rs
src/bin/commands/metadata.rs
src/bin/commands/mod.rs
src/bin/commands/new.rs
src/bin/commands/owner.rs
src/bin/commands/package.rs
src/bin/commands/pkgid.rs
src/bin/commands/publish.rs
src/bin/commands/read_manifest.rs
src/bin/commands/run.rs
src/bin/commands/rustc.rs
src/bin/commands/rustdoc.rs
src/bin/commands/search.rs
src/bin/commands/test.rs
src/bin/commands/uninstall.rs
src/bin/commands/update.rs
src/bin/commands/verify_project.rs
src/bin/commands/version.rs
src/bin/commands/yank.rs

index 1b8b1e4ac018f3493dbf0093c4d418fabffcb355..5d21d020c3ad358a142fb834098849ad9d9bf987 100644 (file)
@@ -1,19 +1,8 @@
 extern crate clap;
 
-use std::cmp::min;
-use std::collections::HashMap;
-use std::fs::File;
-use std::io::{self, Read, BufRead};
-use std::process;
-
 use clap::{AppSettings, Arg, ArgMatches};
-use toml;
 
-use cargo::{self, Config, CargoError, CliResult, CliError};
-use cargo::core::{Source, SourceId, GitReference, Package, Verbosity};
-use cargo::ops::{self, CompileMode, OutputMetadataOptions};
-use cargo::sources::{GitSource, RegistrySource};
-use cargo::util::{ToUrl, CargoResultExt};
+use cargo::{self, Config, CliResult};
 
 use super::list_commands;
 use super::commands;
@@ -63,8 +52,6 @@ pub fn main(config: &mut Config) -> CliResult {
     }
 
     if args.subcommand_name().is_none() {
-        cli().print_help()?;
-        return Ok(());
     }
 
     execute_subcommand(config, args)
@@ -80,481 +67,28 @@ fn execute_subcommand(config: &mut Config, args: ArgMatches) -> CliResult {
         &args.values_of_lossy("unstable-features").unwrap_or_default(),
     )?;
 
-    match args.subcommand() {
-        ("bench", Some(args)) => {
-            let ws = args.workspace(config)?;
-            let mut compile_opts = args.compile_options(config, CompileMode::Bench)?;
-            compile_opts.release = true;
-
-            let ops = 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)
-                    })
-                }
-            }
-        }
-        ("build", Some(args)) => {
-            let mut ws = args.workspace(config)?;
-            let compile_opts = args.compile_options(config, CompileMode::Build)?;
-            ops::compile(&ws, &compile_opts)?;
-            Ok(())
-        }
-        ("check", Some(args)) => {
-            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(())
-        }
-        ("clean", Some(args)) => {
-            let ws = args.workspace(config)?;
-            let opts = ops::CleanOptions {
-                config,
-                spec: values(args, "package"),
-                target: args.target(),
-                release: args.is_present("release"),
-            };
-            ops::clean(&ws, &opts)?;
-            Ok(())
-        }
-        ("doc", Some(args)) => {
-            let ws = args.workspace(config)?;
-            let mode = ops::CompileMode::Doc { deps: !args.is_present("no-deps") };
-            let compile_opts = args.compile_options(config, mode)?;
-            let doc_opts = ops::DocOptions {
-                open_result: args.is_present("open"),
-                compile_opts,
-            };
-            ops::doc(&ws, &doc_opts)?;
-            Ok(())
-        }
-        ("fetch", Some(args)) => {
-            let ws = args.workspace(config)?;
-            ops::fetch(&ws)?;
-            Ok(())
-        }
-        ("generate-lockfile", Some(args)) => {
-            let ws = args.workspace(config)?;
-            ops::generate_lockfile(&ws)?;
-            Ok(())
-        }
-        ("git-checkout", Some(args)) => {
-            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(())
-        }
-        ("init", Some(args)) => {
-            let opts = args.new_options()?;
-            ops::init(&opts, config)?;
-            config.shell().status("Created", format!("{} project", opts.kind))?;
-            Ok(())
-        }
-        ("install", Some(args)) => {
-            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 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") {
-                SourceId::for_path(&config.cwd().join(path))?
-            } else if krates.is_empty() {
-                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, version, &compile_opts, args.is_present("force"))?;
-            }
-            Ok(())
-        }
-        ("locate-project", Some(args)) => {
-            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();
-
-            #[derive(Serialize)]
-            pub struct ProjectLocation {
-                root: String
-            }
-
-            let location = ProjectLocation { root };
-
-            cargo::print_json(&location);
-            Ok(())
-        }
-        ("login", Some(args)) => {
-            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(())
+    let (cmd, args) = match args.subcommand() {
+        (cmd, Some(args)) => (cmd, args),
+        _ => {
+            cli().print_help()?;
+            return Ok(());
         }
-        ("metadata", Some(args)) => {
-            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)?;
-            cargo::print_json(&result);
-            Ok(())
-        }
-        ("new", Some(args)) => {
-            let opts = args.new_options()?;
-            ops::new(&opts, config)?;
-            let path = args.value_of("path").unwrap();
-            config.shell().status("Created", format!("{} `{}` project", opts.kind, path))?;
-            Ok(())
-        }
-        ("owner", Some(args)) => {
-            let registry = args.registry(config)?;
-            let opts = ops::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(())
-        }
-        ("package", Some(args)) => {
-            let ws = args.workspace(config)?;
-            ops::package(&ws, &ops::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(())
-        }
-        ("pkgid", Some(args)) => {
-            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(())
-        }
-        ("publish", Some(args)) => {
-            let registry = args.registry(config)?;
-            let ws = args.workspace(config)?;
-            let index = args.index(config)?;
-
-            ops::publish(&ws, &ops::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(())
-        }
-        ("read-manifest", Some(args)) => {
-            let root = args.root_manifest(config)?;
-            let pkg = Package::for_path(&root, config)?;
-            cargo::print_json(&pkg);
-            Ok(())
-        }
-        ("run", Some(args)) => {
-            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 = ops::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)
-                    })
-                }
-            }
-        }
-        ("rustc", Some(args)) => {
-            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,
-            )?;
-            compile_opts.target_rustc_args = Some(values(args, "args"));
-            ops::compile(&ws, &compile_opts)?;
-            Ok(())
-        }
-        ("rustdoc", Some(args)) => {
-            let ws = args.workspace(config)?;
-            let mut compile_opts = args.compile_options_for_single_package(
-                config, CompileMode::Doc { deps: false },
-            )?;
-            compile_opts.target_rustdoc_args = Some(values(args, "args"));
-            let doc_opts = ops::DocOptions {
-                open_result: args.is_present("open"),
-                compile_opts,
-            };
-            ops::doc(&ws, &doc_opts)?;
-            Ok(())
-        }
-        ("search", Some(args)) => {
-            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(())
-        }
-        ("test", Some(args)) => {
-            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),
-                    })
-                }
-            };
-        }
-        ("uninstall", Some(args)) => {
-            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(())
-        }
-        ("update", Some(args)) => {
-            let ws = args.workspace(config)?;
-
-            let update_opts = ops::UpdateOptions {
-                aggressive: args.is_present("aggressive"),
-                precise: args.value_of("precise"),
-                to_update: values(args, "package"),
-                config,
-            };
-            ops::update_lockfile(&ws, &update_opts)?;
-            Ok(())
-        }
-        ("verify-project", Some(args)) => {
-            fn fail(reason: &str, value: &str) -> ! {
-                let mut h = HashMap::new();
-                h.insert(reason.to_string(), value.to_string());
-                cargo::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());
-            cargo::print_json(&h);
-            Ok(())
-        }
-        ("version", _) => {
-            println!("{}", cargo::version());
-            Ok(())
-        }
-        ("yank", Some(args)) => {
-            let registry = args.registry(config)?;
+    if let Some(exec) = commands::builtin_exec(cmd) {
+        return exec(config, args);
+    }
 
-            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(())
-        }
-        (cmd, Some(args)) => {
-            if let Some(mut alias) = super::aliased_command(config, cmd)? {
-                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 execute_subcommand(config, args);
-            }
-            let mut ext_args: Vec<&str> = vec![cmd];
-            ext_args.extend(args.values_of("").unwrap_or_default());
-            super::execute_external_subcommand(config, cmd, &ext_args)
-        }
-        _ => Ok(())
+    if let Some(mut alias) = super::aliased_command(config, cmd)? {
+        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 execute_subcommand(config, args);
     }
+    let mut ext_args: Vec<&str> = vec![cmd];
+    ext_args.extend(args.values_of("").unwrap_or_default());
+    super::execute_external_subcommand(config, cmd, &ext_args)
 }
 
 
index 7f125b1516d8df9fa517fe06539c1b99be58e4f8..6f55ac19b651904c5ba98bd43f3db5bd757f6a4b 100644 (file)
@@ -1,13 +1,14 @@
 use std::path::PathBuf;
 
-use clap::{self, SubCommand, AppSettings, ArgMatches};
-use cargo::{Config, CargoResult};
+use clap::{self, SubCommand};
+use cargo::CargoResult;
 use cargo::core::Workspace;
 use cargo::ops::{CompileMode, CompileOptions, CompileFilter, Packages, MessageFormat,
                  VersionControl, NewOptions};
 use cargo::util::important_paths::find_root_manifest_for_wd;
 
-pub use clap::Arg;
+pub use clap::{Arg, ArgMatches, AppSettings};
+pub use cargo::{Config, CliResult, CliError};
 
 pub type App = clap::App<'static, 'static>;
 
index df43b78018d8d8791dbb26cf6d2c8096eb9cb3bb..e396e2bc70f3f66de35c198970289833ed0f30f7 100644 (file)
@@ -1,5 +1,6 @@
 use command_prelude::*;
-use clap::AppSettings;
+
+use cargo::ops::{self, CompileMode, TestOptions};
 
 pub fn cli() -> App {
     subcommand("bench")
@@ -65,3 +66,31 @@ 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)
+            })
+        }
+    }
+}
index 9eddd651b085856d0fa67c9bee19aabc9f863ca4..a7312a03354c57a2b39f72103e908ff7b1cb0758 100644 (file)
@@ -1,5 +1,7 @@
 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")
@@ -42,3 +44,10 @@ the --release flag will use the `release` profile instead.
 ")
 
 }
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    let compile_opts = args.compile_options(config, CompileMode::Build)?;
+    ops::compile(&ws, &compile_opts)?;
+    Ok(())
+}
index ecf7fe6cea7774fc95736a1ae0ab4afaecb0e434..7b141bb02dcb6291032acea0cfccd5fd87924167 100644 (file)
@@ -1,5 +1,7 @@
 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")
@@ -48,3 +50,20 @@ 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(())
+}
index 7852c3c5c9796c3a7252c0f1b559517ed54d0dbe..7159e2dfe08717bd333523d27985f1fd2a5ac492 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops::{self, CleanOptions};
+
 pub fn cli() -> App {
     subcommand("clean")
         .about("Remove artifacts that cargo has generated in the past")
@@ -17,3 +19,15 @@ 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"),
+    };
+    ops::clean(&ws, &opts)?;
+    Ok(())
+}
index bcb709b2934b0c201a6780c864676d76d3002d46..5059457321ce9b5a2b35c3afdd063b46c3a7510b 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops::{self, CompileMode, DocOptions};
+
 pub fn cli() -> App {
     subcommand("doc")
         .about("Build a package's documentation")
@@ -39,3 +41,15 @@ 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(())
+}
index bb4a946ab5e406945422b24440fc5b5ba7b9a4f6..1ccc2893f338b13e674a1dc316207f8e7bc733c8 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops;
+
 pub fn cli() -> App {
     subcommand("fetch")
         .about("Fetch dependencies of a package from the network")
@@ -15,3 +17,9 @@ If the lockfile is not available, then this is the equivalent of
 all updated.
 ")
 }
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    ops::fetch(&ws)?;
+    Ok(())
+}
index 56ab283f4d6b8599c5bf10aea8e6e47e24dd86e2..e1ad63bcd3c8b59b068615427cab0df82e256c92 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops;
+
 pub fn cli() -> App {
     subcommand("generate-lockfile")
         .about("Generate the lockfile for a project")
@@ -15,3 +17,9 @@ If the lockfile is not available, then this is the equivalent of
 all updated.
 ")
 }
+
+pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
+    let ws = args.workspace(config)?;
+    ops::generate_lockfile(&ws)?;
+    Ok(())
+}
index 4bbcba13326951ecba3b6493a7c49f34aa9e3891..1125e9b422a3a3312d40f16acbc22878f0cecc38 100644 (file)
@@ -1,8 +1,26 @@
 use command_prelude::*;
 
+use cargo::core::{GitReference, SourceId, Source};
+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(())
+}
index 945ab9a748ae1df09de9668624fbd1dbaff27e93..24929000c395cdeed8a32adc0bf5cd5728aeb407 100644 (file)
@@ -1,8 +1,17 @@
 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()?;
+    ops::init(&opts, config)?;
+    config.shell().status("Created", format!("{} project", opts.kind))?;
+    Ok(())
+}
index ce1834d9d4f6db625b23efee4630e489cfd7f85e..813487950af2d34baa6fbe80d5d184da80756dfb 100644 (file)
@@ -1,5 +1,9 @@
 use command_prelude::*;
 
+use cargo::core::{GitReference, SourceId};
+use cargo::ops::{self, CompileMode};
+use cargo::util::ToUrl;
+
 pub fn cli() -> App {
     subcommand("install")
         .about("Create a new cargo package in an existing directory")
@@ -84,3 +88,40 @@ 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 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") {
+        SourceId::for_path(&config.cwd().join(path))?
+    } else if krates.is_empty() {
+        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, version, &compile_opts, args.is_present("force"))?;
+    }
+    Ok(())
+}
index 1bddac4c25cbd2a1fd01d766c59cbc0265b26e88..b4662930ccead2a124c92b728bbf2c328406d8b7 100644 (file)
@@ -1,7 +1,29 @@
 use command_prelude::*;
 
+use cargo::print_json;
+
 pub fn cli() -> App {
     subcommand("locate-project")
         .about("Checkout a copy of a Git repository")
         .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(())
+}
index 045770181933019d9118b3454fe52ae28c9292c1..7f26ea2e8f025baa9ff15282a5ac72c3becf3258 100644 (file)
@@ -1,5 +1,12 @@
 use command_prelude::*;
 
+use std::io::{self, BufRead};
+
+use cargo::core::{SourceId, Source};
+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. \
@@ -8,3 +15,37 @@ pub fn cli() -> App {
         .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(())
+}
index 7f4904c1441762644025140fe4ebcb90936392d4..e3ebaff82effe39f5ddee49e087855cfd670a61e 100644 (file)
@@ -1,5 +1,8 @@
 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, \
@@ -16,3 +19,30 @@ pub fn cli() -> App {
                 .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(())
+}
index 6dea3eb16f62d60200c31fd96ad83c8dd7e3a8e0..6d8cb64a4ec30e973c8a04f9e96330656639ecb2 100644 (file)
@@ -34,33 +34,68 @@ pub fn builtin() -> Vec<App> {
     ]
 }
 
+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)
+}
 
-mod bench;
-mod build;
-mod check;
-mod clean;
-mod doc;
-mod fetch;
-mod generate_lockfile;
-mod git_checkout;
-mod init;
-mod install;
-mod locate_project;
-mod login;
-mod metadata;
-mod new;
-mod owner;
-mod package;
-mod pkgid;
-mod publish;
-mod read_manifest;
-mod run;
-mod rustc;
-mod rustdoc;
-mod search;
-mod test;
-mod uninstall;
-mod update;
-mod verify_project;
-mod version;
-mod yank;
+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;
index eb03e37d564eafc98b1da9ece8e32659b807a0d9..d41f8cce42c4847b7421256f3b424f73f8eddaa7 100644 (file)
@@ -1,8 +1,18 @@
 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()?;
+    ops::new(&opts, config)?;
+    let path = args.value_of("path").unwrap();
+    config.shell().status("Created", format!("{} `{}` project", opts.kind, path))?;
+    Ok(())
+}
index dd7c5adf1aa791457eda4842e5a9f5506cef3b26..41823de9e36261e092224a6205799caec8beabe8 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops::{self, OwnersOptions};
+
 pub fn cli() -> App {
     subcommand("owner")
         .about("Manage the owners of a crate on the registry")
@@ -26,3 +28,20 @@ pub fn cli() -> App {
         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(())
+}
index 59ba384b7e1e53682c655cc8c87074bba4971568..eb2306192a450a6e69473742529538d68f09820a 100644 (file)
@@ -1,5 +1,8 @@
 use command_prelude::*;
 
+use cargo::ops::{self, PackageOpts};
+
+
 pub fn cli() -> App {
     subcommand("package")
         .about("Assemble the local package into a distributable tarball")
@@ -11,3 +14,18 @@ pub fn cli() -> App {
         .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(())
+}
index 26335735aa43be8cea1b6007001a6b74509ed15e..9777915d07e4ee788326e509842062da4910fd86 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops;
+
 pub fn cli() -> App {
     subcommand("pkgid")
         .about("Print a fully qualified package specification")
@@ -27,3 +29,11 @@ Example Package IDs
      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(())
+}
index fc4ead218db6fdc6ca795529e68764be0d702961..31c7c9522924674a942a9b66d256cbc283212346 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops::{self, PublishOpts};
+
 pub fn cli() -> App {
     subcommand("publish")
         .about("Upload a package to the registry")
@@ -15,3 +17,22 @@ pub fn cli() -> App {
         )
         .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(())
+}
index ec6ffec836c81aac4ef9f9331bc3406bac257f59..d89fe5b7a01894c145c5cd48f774face80ab1e5e 100644 (file)
@@ -1,8 +1,18 @@
 use command_prelude::*;
 
+use cargo::core::Package;
+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 root = args.root_manifest(config)?;
+    let pkg = Package::for_path(&root, config)?;
+    print_json(&pkg);
+    Ok(())
+}
index dae6c9de26f9b00a93a1219459b5cd68633bed38..535ae5addf573955d752f638013fabcfb417beb6 100644 (file)
@@ -1,7 +1,8 @@
-use clap::AppSettings;
-
 use command_prelude::*;
 
+use cargo::core::Verbosity;
+use cargo::ops::{self, CompileMode, CompileFilter};
+
 pub fn cli() -> App {
     subcommand("run").alias("r")
         .setting(AppSettings::TrailingVarArg)
@@ -29,3 +30,38 @@ 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)
+            })
+        }
+    }
+}
index 8074a551e44336e28a16c11dade28901b155cf6d..ea4c71b6183ca1c8735a79e168b926fb42886ad6 100644 (file)
@@ -1,7 +1,7 @@
-use clap::AppSettings;
-
 use command_prelude::*;
 
+use cargo::ops::{self, CompileMode};
+
 pub fn cli() -> App {
     subcommand("rustc")
         .setting(AppSettings::TrailingVarArg)
@@ -45,3 +45,24 @@ 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,
+    )?;
+    compile_opts.target_rustc_args = Some(values(args, "args"));
+    ops::compile(&ws, &compile_opts)?;
+    Ok(())
+}
index 5db6ca9dd73efaa661e461fb52fe96c51f7bf0ff..5b4fbd6888523f7aa4a92fdbe483a7edddb01c60 100644 (file)
@@ -1,7 +1,7 @@
-use clap::AppSettings;
-
 use command_prelude::*;
 
+use cargo::ops::{self, CompileMode, DocOptions};
+
 pub fn cli() -> App {
     subcommand("rustdoc")
         .setting(AppSettings::TrailingVarArg)
@@ -39,3 +39,17 @@ 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 },
+    )?;
+    compile_opts.target_rustdoc_args = Some(values(args, "args"));
+    let doc_opts = DocOptions {
+        open_result: args.is_present("open"),
+        compile_opts,
+    };
+    ops::doc(&ws, &doc_opts)?;
+    Ok(())
+}
index 62d023b0fbe7665cbc59c4c353e1a02ccc1956bc..9b28e1f7855192764dcc73a9038833cd0c394211 100644 (file)
@@ -1,5 +1,9 @@
 use command_prelude::*;
 
+use std::cmp::min;
+
+use cargo::ops;
+
 pub fn cli() -> App {
     subcommand("search")
         .about("Search packages in crates.io")
@@ -11,3 +15,14 @@ pub fn cli() -> App {
         )
         .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(())
+}
index 9c0ae57b7b4f86b4e51aa4c61c6e43f6f699a527..83be8de24207bcb2c2af3a5c2e55dbbb97eeeeaf 100644 (file)
@@ -1,5 +1,6 @@
 use command_prelude::*;
-use clap::AppSettings;
+
+use cargo::ops::{self, CompileMode};
 
 pub fn cli() -> App {
     subcommand("test").alias("t")
@@ -82,3 +83,43 @@ 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),
+            })
+        }
+    };
+}
index 5ab7513e5a7b63dc3394f24776d1489956f748d5..cf62c4c79d3275782ec9583dd141c2d1cdd22aeb 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops;
+
 pub fn cli() -> App {
     subcommand("uninstall")
         .about("Remove a Rust binary")
@@ -19,3 +21,10 @@ 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(())
+}
index 523051c2576f54f1bac569f8cc5b1a5c0e326f93..c857234bffee959dff3979af7b96b77797f1498e 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops::{self, UpdateOptions};
+
 pub fn cli() -> App {
     subcommand("update")
         .about("Update dependencies as recorded in the local lock file")
@@ -35,3 +37,16 @@ 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(())
+}
index 926d8014cc1f87ba22124da5c875938f695daf1a..93afa4bef3e1533b25fe467e941c6ba835a1b2ce 100644 (file)
@@ -1,7 +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(())
+}
index 0d7de9a6cde005eb6d23056b3eb8af36210f2295..9f753886654d5ecc481765941509f8ec0b147aab 100644 (file)
@@ -1,6 +1,13 @@
 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(())
+}
index 54039a3b1b5bd5fd565172f833858d8d7ff80d64..2defd080c3b66441f00247e4585d76f153ad2e14 100644 (file)
@@ -1,5 +1,7 @@
 use command_prelude::*;
 
+use cargo::ops;
+
 pub fn cli() -> App {
     subcommand("yank")
         .about("Remove a pushed crate from the index")
@@ -21,3 +23,16 @@ 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(())
+}