Skip to content

Commit

Permalink
Introduce +TOOLCHAIN syntax for proxies.
Browse files Browse the repository at this point in the history
If the first argument to a proxy is of the form `+TOOLCHAIN`, then this
will be interpreted as the toolchain the user wants.  That is,

    cargo +nightly build

will be equivalent to

    rustup run nightly cargo build

This is purely an ergonomic feature designed to reduce typing for people
who frequently switch toolchains (particularly for testing).  It is
inspired by a similar feature in the Python launcher.

**Why `+TOOLCHAIN`?**

The obvious candidate (used by Python) of `-TOOLCHAIN` was a no-go.
The issue is that because toolchains can have arbitrary names, it is
difficult to distinguish between a toolchain and an actual argument to
the proxied program in the general case.

`@TOOLCHAIN` was also considered, as it reads somewhat naturally in
English.  However, it turns out that `@` is a meta character in
Powershell, which causes the next word to simply *disappear* from the
command line.  Presumably, there is a reason for this.

`+TOOLCHAIN` was tested and found to not need escaping with CMD,
Powershell, bash, and fish.
  • Loading branch information
DanielKeep committed Jul 25, 2016
1 parent 7f311dd commit c2c52a6
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 6 deletions.
34 changes: 28 additions & 6 deletions src/rustup-cli/proxy_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use errors::*;
use rustup_utils::utils;
use rustup::command::run_command_for_dir;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use job;

Expand All @@ -12,23 +13,44 @@ pub fn main() -> Result<()> {

job::setup();

let arg0 = env::args().next().map(|a| PathBuf::from(a));
let mut args = env::args();

let arg0 = args.next().map(|a| PathBuf::from(a));
let arg0 = arg0.as_ref()
.and_then(|a| a.file_name())
.and_then(|a| a.to_str());
let ref arg0 = try!(arg0.ok_or(ErrorKind::NoExeName));

// Check for a toolchain specifier.
let arg1 = args.next();
let toolchain = arg1.as_ref()
.and_then(|arg1| {
if arg1.starts_with("+") {
Some(&arg1[1..])
} else {
None
}
});

// Build command args now while we know whether or not to skip arg 1.
let cmd_args: Vec<_> = if toolchain.is_none() {
env::args_os().collect()
} else {
env::args_os().take(1).chain(env::args_os().skip(2)).collect()
};

let cfg = try!(set_globals(false));
try!(cfg.check_metadata_version());
try!(direct_proxy(&cfg, arg0));
try!(direct_proxy(&cfg, arg0, toolchain, &cmd_args));

Ok(())
}

fn direct_proxy(cfg: &Cfg, arg0: &str) -> Result<()> {
let cmd = try!(cfg.create_command_for_dir(&try!(utils::current_dir()), arg0));
let args: Vec<_> = env::args_os().collect();

fn direct_proxy(cfg: &Cfg, arg0: &str, toolchain: Option<&str>, args: &[OsString]) -> Result<()> {
let cmd = match toolchain {
None => try!(cfg.create_command_for_dir(&try!(utils::current_dir()), arg0)),
Some(tc) => try!(cfg.create_command_for_toolchain(tc, arg0)),
};
Ok(try!(run_command_for_dir(cmd, &args, &cfg)))
}

11 changes: 11 additions & 0 deletions tests/cli-rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,14 @@ fn toolchain_update_is_like_update_except_that_bare_install_is_an_error() {
"arguments were not provided");
});
}

#[test]
fn proxy_toolchain_shorthand() {
setup(&|config| {
expect_ok(config, &["rustup", "default", "stable"]);
expect_ok(config, &["rustup", "toolchain", "update" , "nightly"]);
expect_stdout_ok(config, &["rustc", "--version"], "hash-s-2");
expect_stdout_ok(config, &["rustc", "+stable", "--version"], "hash-s-2");
expect_stdout_ok(config, &["rustc", "+nightly", "--version"], "hash-n-2");
});
}

0 comments on commit c2c52a6

Please sign in to comment.