Skip to content

Commit f45cd9f

Browse files
committed
#370 Support for explicit channel argument
1 parent 0f1941e commit f45cd9f

File tree

4 files changed

+67
-14
lines changed

4 files changed

+67
-14
lines changed

src/cli.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
use std::{env, path::PathBuf};
22

3+
use rustc_version::Channel;
4+
35
use crate::Target;
46
use crate::cargo::Subcommand;
5-
use crate::rustc::TargetList;
7+
use crate::errors::Result;
8+
use crate::rustc::{ChannelExt, TargetList};
69

10+
#[derive(Debug)]
711
pub struct Args {
812
pub all: Vec<String>,
913
pub subcommand: Option<Subcommand>,
14+
pub channel: Option<Channel>,
1015
pub target: Option<Target>,
1116
pub target_dir: Option<PathBuf>,
1217
}
1318

14-
pub fn parse(target_list: &TargetList) -> Args {
19+
pub fn parse(target_list: &TargetList) -> Result<Args> {
20+
let mut channel = None;
1521
let mut target = None;
1622
let mut target_dir = None;
1723
let mut sc = None;
@@ -20,7 +26,9 @@ pub fn parse(target_list: &TargetList) -> Args {
2026
{
2127
let mut args = env::args().skip(1);
2228
while let Some(arg) = args.next() {
23-
if arg == "--target" {
29+
if arg.starts_with("+") {
30+
channel = Some(Channel::from_str(&arg[1..])?);
31+
} else if arg == "--target" {
2432
all.push(arg);
2533
if let Some(t) = args.next() {
2634
target = Some(Target::from(&t, target_list));
@@ -50,10 +58,11 @@ pub fn parse(target_list: &TargetList) -> Args {
5058
}
5159
}
5260

53-
Args {
61+
Ok(Args {
5462
all,
5563
subcommand: sc,
64+
channel,
5665
target,
5766
target_dir,
58-
}
67+
})
5968
}

src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ error_chain! {
77
Io(std::io::Error);
88
Which(which::Error);
99
}
10+
11+
errors {
12+
InvalidChannelName(channel: String) {
13+
description("invalid channel name")
14+
display("invalid channel name: '{}'", channel)
15+
}
16+
}
1017
}

src/main.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use toml::{Value, value::Table};
2020

2121
use self::cargo::{Root, Subcommand};
2222
use self::errors::*;
23-
use self::rustc::{TargetList, VersionMetaExt};
23+
use self::rustc::{ChannelExt, TargetList, VersionMetaExt};
2424

2525
#[allow(non_camel_case_types)]
2626
#[derive(Debug, Clone, PartialEq)]
@@ -208,7 +208,7 @@ pub fn main() {
208208

209209
fn run() -> Result<ExitStatus> {
210210
let target_list = rustc::target_list(false)?;
211-
let args = cli::parse(&target_list);
211+
let args = cli::parse(&target_list)?;
212212

213213
if args.all.iter().any(|a| a == "--version" || a == "-V") &&
214214
args.subcommand.is_none() {
@@ -228,9 +228,19 @@ fn run() -> Result<ExitStatus> {
228228
.unwrap_or_else(|| Target::from(host.triple(), &target_list));
229229
let toml = toml(&root)?;
230230

231-
let sysroot = rustc::sysroot(&host, &target, verbose)?;
232-
let toolchain = sysroot.file_name().and_then(|file_name| file_name.to_str())
231+
let mut sysroot = rustc::sysroot(&host, &target, verbose)?;
232+
let default_toolchain = sysroot.file_name().and_then(|file_name| file_name.to_str())
233233
.ok_or("couldn't get toolchain name")?;
234+
let toolchain = if let Some(channel) = args.channel {
235+
[channel.to_string()].iter().map(|c| c.as_str()).chain(
236+
default_toolchain.splitn(2, '-').skip(1)
237+
)
238+
.collect::<Vec<_>>()
239+
.join("-")
240+
} else {
241+
default_toolchain.to_string()
242+
};
243+
sysroot.set_file_name(&toolchain);
234244

235245
let installed_toolchains = rustup::installed_toolchains(verbose)?;
236246

@@ -250,13 +260,13 @@ fn run() -> Result<ExitStatus> {
250260

251261
if !uses_xargo && !available_targets.is_installed(&target) {
252262
rustup::install(&target, &toolchain, verbose)?;
253-
} else if !rustup::component_is_installed("rust-src", toolchain, verbose)? {
254-
rustup::install_component("rust-src", toolchain, verbose)?;
263+
} else if !rustup::component_is_installed("rust-src", &toolchain, verbose)? {
264+
rustup::install_component("rust-src", &toolchain, verbose)?;
255265
}
256266

257267
if args.subcommand.map(|sc| sc == Subcommand::Clippy).unwrap_or(false) &&
258-
!rustup::component_is_installed("clippy", toolchain, verbose)? {
259-
rustup::install_component("clippy", toolchain, verbose)?;
268+
!rustup::component_is_installed("clippy", &toolchain, verbose)? {
269+
rustup::install_component("clippy", &toolchain, verbose)?;
260270
}
261271

262272
let needs_interpreter = args.subcommand.map(|sc| sc.needs_interpreter()).unwrap_or(false);

src/rustc.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::PathBuf;
22
use std::process::Command;
33

4-
use rustc_version::{Version, VersionMeta};
4+
use rustc_version::{Channel, Version, VersionMeta};
55

66
use crate::{Host, Target};
77
use crate::errors::*;
@@ -38,6 +38,33 @@ impl VersionMetaExt for VersionMeta {
3838
}
3939
}
4040

41+
pub(crate) trait ChannelExt {
42+
fn from_str(chan: &str) -> Result<Channel>;
43+
fn to_string(&self) -> String;
44+
}
45+
46+
impl ChannelExt for Channel {
47+
fn from_str(chan: &str) -> Result<Channel> {
48+
Ok(match chan {
49+
"stable" => Channel::Stable,
50+
"nightly" => Channel::Nightly,
51+
"dev" => Channel::Dev,
52+
"beta" => Channel::Beta,
53+
_ => return Err(
54+
ErrorKind::InvalidChannelName(chan.to_string()).into()
55+
),
56+
})
57+
}
58+
fn to_string(&self) -> String {
59+
match self {
60+
Channel::Stable => "stable",
61+
Channel::Nightly => "nightly",
62+
Channel::Dev => "dev",
63+
Channel::Beta => "beta",
64+
}.to_string()
65+
}
66+
}
67+
4168
pub fn target_list(verbose: bool) -> Result<TargetList> {
4269
Command::new("rustc")
4370
.args(&["--print", "target-list"])

0 commit comments

Comments
 (0)