extern crate failure;
extern crate git2_curl;
extern crate toml;
-#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate clap;
-use std::collections::BTreeSet;
-use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
mod cli;
-#[derive(Deserialize)]
-pub struct Flags {
- flag_list: bool,
- flag_version: bool,
- flag_verbose: u32,
- flag_quiet: Option<bool>,
- flag_color: Option<String>,
- flag_explain: Option<String>,
- arg_command: String,
- arg_args: Vec<String>,
- flag_locked: bool,
- flag_frozen: bool,
- #[serde(rename = "flag_Z")]
- flag_z: Vec<String>,
-}
-
-const USAGE: &'static str = "
-Rust's package manager
-
-Usage:
- cargo <command> [<args>...]
- cargo [options]
-
-Options:
- -h, --help Display this message
- -V, --version Print version info and exit
- --list List installed commands
- --explain CODE Run `rustc --explain CODE`
- -v, --verbose ... Use verbose output (-vv very verbose/build.rs output)
- -q, --quiet No output printed to stdout
- --color WHEN Coloring: auto, always, never
- --frozen Require Cargo.lock and cache are up to date
- --locked Require Cargo.lock is up to date
- -Z FLAG ... Unstable (nightly-only) flags to Cargo
-
-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.
-";
-
fn main() {
env_logger::init();
cli::do_main(config)
}
-macro_rules! each_subcommand{
- ($mac:ident) => {
- }
-}
-
-macro_rules! declare_mod {
- ($name:ident) => ( pub mod $name; )
-}
-each_subcommand!(declare_mod);
-
-/**
- The top-level `cargo` command handles configuration and project location
- because they are fundamental (and intertwined). Other commands can rely
- on this top-level information.
-*/
-fn execute(flags: Flags, config: &mut Config) -> CliResult {
- config.configure(flags.flag_verbose,
- flags.flag_quiet,
- &flags.flag_color,
- flags.flag_frozen,
- flags.flag_locked,
- &flags.flag_z)?;
-
- init_git_transports(config);
- let _token = cargo::util::job::setup();
-
- if flags.flag_version {
- let version = cargo::version();
- println!("{}", version);
- if flags.flag_verbose > 0 {
- 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 flags.flag_list {
- println!("Installed Commands:");
- for command in list_commands(config) {
- let (command, path) = command;
- if flags.flag_verbose > 0 {
- match path {
- Some(p) => println!(" {:<20} {}", command, p),
- None => println!(" {:<20}", command),
- }
- } else {
- println!(" {}", command);
- }
- }
- return Ok(());
- }
-
- if let Some(ref code) = flags.flag_explain {
- let mut procss = config.rustc()?.process();
- procss.arg("--explain").arg(code).exec()?;
- return Ok(());
- }
-
- let args = match &flags.arg_command[..] {
- // For the commands `cargo` and `cargo help`, re-execute ourselves as
- // `cargo -h` so we can go through the normal process of printing the
- // help message.
- "" | "help" if flags.arg_args.is_empty() => {
- config.shell().set_verbosity(Verbosity::Verbose);
- let args = &["cargo".to_string(), "-h".to_string()];
- return cargo::call_main_without_stdin(execute, config, USAGE, args, false);
- }
-
- // For `cargo help -h` and `cargo help --help`, print out the help
- // message for `cargo help`
- "help" if flags.arg_args[0] == "-h" || flags.arg_args[0] == "--help" => {
- vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
- }
-
- // For `cargo help foo`, print out the usage message for the specified
- // subcommand by executing the command with the `-h` flag.
- "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(), "-h".to_string()],
-
- // For all other invocations, we're of the form `cargo foo args...`. We
- // use the exact environment arguments to preserve tokens like `--` for
- // example.
- _ => {
- let mut default_alias = HashMap::new();
- default_alias.insert("b", "build".to_string());
- default_alias.insert("t", "test".to_string());
- default_alias.insert("r", "run".to_string());
- let mut args: Vec<String> = env::args().collect();
- if let Some(new_command) = default_alias.get(&args[1][..]) {
- args[1] = new_command.clone();
- }
- args
- }
- };
-
- if let Some(r) = try_execute_builtin_command(config, &args) {
- return r;
- }
-
- let alias_list = aliased_command(config, &args[1])?;
- let args = match alias_list {
- Some(alias_command) => {
- let chain = args.iter()
- .take(1)
- .chain(alias_command.iter())
- .chain(args.iter().skip(2))
- .map(|s| s.to_string())
- .collect::<Vec<_>>();
- if let Some(r) = try_execute_builtin_command(config, &chain) {
- return r;
- } else {
- chain
- }
- }
- None => args,
- };
- unimplemented!()
-// execute_external_subcommand(config, &args[1], &args)
-}
-
-fn try_execute_builtin_command(config: &mut Config, args: &[String]) -> Option<CliResult> {
- macro_rules! cmd {
- ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
- config.shell().set_verbosity(Verbosity::Verbose);
- let r = cargo::call_main_without_stdin($name::execute,
- config,
- $name::USAGE,
- &args,
- false);
- return Some(r);
- })
- }
- each_subcommand!(cmd);
-
- None
-}
-
fn aliased_command(config: &Config, command: &str) -> CargoResult<Option<Vec<String>>> {
let alias_name = format!("alias.{}", command);
let mut result = Ok(None);
}
fn find_closest(config: &Config, cmd: &str) -> Option<String> {
- let cmds = list_commands(config);
+ let cmds = cli::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()
Err(CliError::new(err, 101))
}
-/// 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()))
- );
- }
- }
- }
-
- macro_rules! add_cmd {
- ($cmd:ident) => ({ commands.insert((stringify!($cmd).replace("_", "-"), None)); })
- }
- each_subcommand!(add_cmd);
- commands
-}
-
#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
use std::os::unix::prelude::*;