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 26, 2016
1 parent 7f311dd commit 990347e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ Command | Description
`rustup target add arm-linux-androideabi` | Install the Android target
`rustup target remove arm-linux-androideabi` | Remove the Android target
`rustup run nightly rustc foo.rs` | Run the nightly regardless of the active toolchain
`rustc +nightly foo.rs` | Shorthand way to run a nightly compiler
`rustup run nightly bash` | Run a shell configured for the nightly compiler
`rustup default stable-msvc` | On Windows, use the MSVC toolchain instead of GNU
`rustup override nightly-2015-04-01` | For the current directory, use a nightly from a specific date
Expand Down
10 changes: 9 additions & 1 deletion src/rustup-cli/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,15 @@ r"
Configures an environment to use the given toolchain and then runs
the specified program. The command may be any program, not just
rustc or cargo. This can be used for testing arbitrary toolchains
without setting an override.";
without setting an override.
Commands explicitly proxied by `rustup` (such as `rustc` and `cargo`)
also have a shorthand for this available. The toolchain can be set by
using `+toolchain` as the first argument. These are equivalent:
cargo +nightly build
rustup run nightly cargo build";

pub static DOC_HELP: &'static str =
r"
Expand Down
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 990347e

Please sign in to comment.