Skip to content

Commit c2c52a6

Browse files
committed
Introduce +TOOLCHAIN syntax for proxies.
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.
1 parent 7f311dd commit c2c52a6

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/rustup-cli/proxy_mode.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use errors::*;
44
use rustup_utils::utils;
55
use rustup::command::run_command_for_dir;
66
use std::env;
7+
use std::ffi::OsString;
78
use std::path::PathBuf;
89
use job;
910

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

1314
job::setup();
1415

15-
let arg0 = env::args().next().map(|a| PathBuf::from(a));
16+
let mut args = env::args();
17+
18+
let arg0 = args.next().map(|a| PathBuf::from(a));
1619
let arg0 = arg0.as_ref()
1720
.and_then(|a| a.file_name())
1821
.and_then(|a| a.to_str());
1922
let ref arg0 = try!(arg0.ok_or(ErrorKind::NoExeName));
2023

24+
// Check for a toolchain specifier.
25+
let arg1 = args.next();
26+
let toolchain = arg1.as_ref()
27+
.and_then(|arg1| {
28+
if arg1.starts_with("+") {
29+
Some(&arg1[1..])
30+
} else {
31+
None
32+
}
33+
});
34+
35+
// Build command args now while we know whether or not to skip arg 1.
36+
let cmd_args: Vec<_> = if toolchain.is_none() {
37+
env::args_os().collect()
38+
} else {
39+
env::args_os().take(1).chain(env::args_os().skip(2)).collect()
40+
};
41+
2142
let cfg = try!(set_globals(false));
2243
try!(cfg.check_metadata_version());
23-
try!(direct_proxy(&cfg, arg0));
44+
try!(direct_proxy(&cfg, arg0, toolchain, &cmd_args));
2445

2546
Ok(())
2647
}
2748

28-
fn direct_proxy(cfg: &Cfg, arg0: &str) -> Result<()> {
29-
let cmd = try!(cfg.create_command_for_dir(&try!(utils::current_dir()), arg0));
30-
let args: Vec<_> = env::args_os().collect();
31-
49+
fn direct_proxy(cfg: &Cfg, arg0: &str, toolchain: Option<&str>, args: &[OsString]) -> Result<()> {
50+
let cmd = match toolchain {
51+
None => try!(cfg.create_command_for_dir(&try!(utils::current_dir()), arg0)),
52+
Some(tc) => try!(cfg.create_command_for_toolchain(tc, arg0)),
53+
};
3254
Ok(try!(run_command_for_dir(cmd, &args, &cfg)))
3355
}
3456

tests/cli-rustup.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,3 +501,14 @@ fn toolchain_update_is_like_update_except_that_bare_install_is_an_error() {
501501
"arguments were not provided");
502502
});
503503
}
504+
505+
#[test]
506+
fn proxy_toolchain_shorthand() {
507+
setup(&|config| {
508+
expect_ok(config, &["rustup", "default", "stable"]);
509+
expect_ok(config, &["rustup", "toolchain", "update" , "nightly"]);
510+
expect_stdout_ok(config, &["rustc", "--version"], "hash-s-2");
511+
expect_stdout_ok(config, &["rustc", "+stable", "--version"], "hash-s-2");
512+
expect_stdout_ok(config, &["rustc", "+nightly", "--version"], "hash-n-2");
513+
});
514+
}

0 commit comments

Comments
 (0)