Skip to content

Commit

Permalink
Implement the rustup cli
Browse files Browse the repository at this point in the history
This adds the `rustup` command as described in rust-lang#129.

Major changes:

* A bare `rustup` updates all tracked channels and self-updates.
* All the `--copy-local`, `--link local` and `--installer` options
  are gone. There is just `rustup channel link`, which covers the
  most common reason for creating custom toolchains.
* `add-target`, `list-targets`, and `remove-targets` are all under
  the `target` subcommand, and all operate on the current toolchain
  instead of needing to specify it explicitly.
* Override comands are all under the `override` subcommand.
* Lesser commands for modifying toolchains are under the `toolchain`
  subcommand, but I decided `multirust update` and `multirust update
  nightly` were useful enough to stay its own subcommand.
* The UI for updating all channels is changed from `multirust-rs`
  slightly: both the update status and channel revision are displayed
  in the same place.
* I've removed green from 'info' logging and used it only for
  successful updates to make it more impactful.

Note there are several ways to update now: `rustup` updates
everything, `rustup update` updates the current toolchain, and `rustup
update [toolchain]` updates a specific toolchain.
  • Loading branch information
brson committed Mar 20, 2016
1 parent c34904b commit 5f93275
Show file tree
Hide file tree
Showing 14 changed files with 723 additions and 201 deletions.
1 change: 0 additions & 1 deletion src/multirust-cli/cli.rs
Expand Up @@ -188,7 +188,6 @@ r"Upgrades the ~/.multirust directory from previous versions.
.subcommand(
SubCommand::with_name("update")
.about("Updates multirust.")
.arg(Arg::with_name("no-prompt").short("y").help("Disable confirmation prompt."))
)
)
.subcommand(
Expand Down
89 changes: 88 additions & 1 deletion src/multirust-cli/common.rs
Expand Up @@ -99,7 +99,6 @@ pub fn run_inner<S: AsRef<OsStr>>(mut command: Command,
}

pub fn show_channel_version(cfg: &Cfg, name: &str) -> Result<()> {
println!("");
let mut t = term::stdout().unwrap();
if tty::stdout_isatty() { let _ = t.fg(term::color::BRIGHT_WHITE); }
if tty::stdout_isatty() { let _ = t.bg(term::color::BLACK); }
Expand All @@ -112,6 +111,48 @@ pub fn show_channel_version(cfg: &Cfg, name: &str) -> Result<()> {
Ok(())
}

pub fn show_channel_update(cfg: &Cfg, name: &str,
updated: Result<bool>) -> Result<()> {
let tty = tty::stdout_isatty();
let mut t = term::stdout().unwrap();
match updated {
Ok(true) => {
if tty { let _ = t.fg(term::color::BRIGHT_GREEN); }
let _ = write!(t, "{} updated", name);
}
Ok(false) => {
if tty { let _ = t.fg(term::color::BRIGHT_WHITE); }
let _ = write!(t, "{} unchanged", name);
}
Err(_) => {
if tty { let _ = t.fg(term::color::BRIGHT_RED); }
let _ = write!(t, "{} update failed", name);
}
}
if tty {let _ = t.reset(); }
println!(":");
println!("");
try!(show_tool_versions(&try!(cfg.get_toolchain(&name, false))));
println!("");
Ok(())
}

pub fn update_all_channels(cfg: &Cfg) -> Result<()> {
let toolchains = try!(cfg.update_all_channels());

if toolchains.is_empty() {
info!("no updatable toolchains installed");
return Ok(());
}

println!("");

for (name, result) in toolchains {
try!(show_channel_update(cfg, &name, result));
}
Ok(())
}

pub fn show_tool_versions(toolchain: &Toolchain) -> Result<()> {
if toolchain.exists() {
let rustc_path = toolchain.binary_file("rustc");
Expand Down Expand Up @@ -150,3 +191,49 @@ pub fn show_tool_versions(toolchain: &Toolchain) -> Result<()> {
Ok(())
}

pub fn list_targets(toolchain: &Toolchain) -> Result<()> {
for component in try!(toolchain.list_components()) {
if component.component.pkg == "rust-std" {
if component.required {
println!("{} (default)", component.component.target);
} else if component.installed {
println!("{} (installed)", component.component.target);
} else {
println!("{}", component.component.target);
}
}
}

Ok(())
}

pub fn list_toolchains(cfg: &Cfg) -> Result<()> {
let mut toolchains = try!(cfg.list_toolchains());

toolchains.sort();

if toolchains.is_empty() {
println!("no installed toolchains");
} else {
for toolchain in toolchains {
println!("{}", &toolchain);
}
}
Ok(())
}

pub fn list_overrides(cfg: &Cfg) -> Result<()> {
let mut overrides = try!(cfg.override_db.list());

overrides.sort();

if overrides.is_empty() {
println!("no overrides");
} else {
for o in overrides {
println!("{}", o);
}
}
Ok(())
}

2 changes: 1 addition & 1 deletion src/multirust-cli/log.rs
Expand Up @@ -36,7 +36,7 @@ pub fn err_fmt(args: fmt::Arguments) {

pub fn info_fmt(args: fmt::Arguments) {
let mut t = term::stderr().unwrap();
if tty::stderr_isatty() { let _ = t.fg(term::color::BRIGHT_GREEN); }
if tty::stderr_isatty() { let _ = t.fg(term::color::BRIGHT_CYAN); }
let _ = write!(t, "info: ");
if tty::stderr_isatty() { let _ = t.reset(); }
let _ = t.write_fmt(args);
Expand Down
7 changes: 6 additions & 1 deletion src/multirust-cli/main.rs
Expand Up @@ -35,6 +35,7 @@ mod download_tracker;
mod multirust_mode;
mod proxy_mode;
mod setup_mode;
mod rustup_mode;
mod self_update;
mod tty;
mod job;
Expand Down Expand Up @@ -64,10 +65,14 @@ fn run_multirust() -> Result<()> {
.and_then(|a| a.file_stem())
.and_then(|a| a.to_str());
match name {
Some("rustup") => {
rustup_mode::main()
}
Some("multirust") => {
multirust_mode::main()
}
Some(n) if n.starts_with("multirust-setup") => {
Some(n) if n.starts_with("multirust-setup")||
n.starts_with("rustup-setup") => {
// NB: The above check is only for the prefix of the file
// name. Browsers rename duplicates to
// e.g. multirust-setup(2), and this allows all variations
Expand Down
101 changes: 9 additions & 92 deletions src/multirust-cli/multirust_mode.rs
@@ -1,16 +1,13 @@
use clap::ArgMatches;
use cli;
use common::{confirm, show_channel_version,
use common::{self, confirm, show_channel_version,
set_globals, run_inner,
show_tool_versions};
show_tool_versions, update_all_channels};
use multirust::*;
use multirust_dist::manifest::Component;
use self_update;
use std::env;
use std::io::Write;
use std::iter;
use std::path::{Path, PathBuf};
use term;
use job;

pub fn main() -> Result<()> {
Expand Down Expand Up @@ -39,8 +36,8 @@ pub fn main() -> Result<()> {
("override", Some(m)) => override_(&cfg, m),
("show-default", Some(_)) => show_default(&cfg),
("show-override", Some(_)) => show_override(&cfg),
("list-overrides", Some(_)) => list_overrides(&cfg),
("list-toolchains", Some(_)) => list_toolchains(&cfg),
("list-overrides", Some(_)) => common::list_overrides(&cfg),
("list-toolchains", Some(_)) => common::list_toolchains(&cfg),
("remove-override", Some(m)) => remove_override(&cfg, m),
("remove-toolchain", Some(m)) => remove_toolchain_args(&cfg, m),
("list-targets", Some(m)) => list_targets(&cfg, m),
Expand Down Expand Up @@ -137,8 +134,8 @@ fn default_(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
}
}


try!(toolchain.make_default());
println!("");
try!(show_channel_version(cfg, toolchain.name()));

Ok(())
Expand All @@ -149,11 +146,12 @@ fn update(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
let toolchain = try!(cfg.get_toolchain(name, true));
if !try!(common_install_args(&toolchain, m)) {
if !toolchain.is_custom() {
try!(toolchain.install_from_dist())
try!(toolchain.install_from_dist());
} else if !toolchain.exists() {
return Err(Error::ToolchainNotInstalled(toolchain.name().to_string()));
}
}
println!("");
try!(show_channel_version(cfg, name));
} else {
try!(update_all_channels(cfg))
Expand All @@ -170,6 +168,7 @@ fn override_(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
}

try!(toolchain.make_override(&try!(utils::current_dir())));
println!("");
try!(show_channel_version(cfg, toolchain.name()));
Ok(())
}
Expand Down Expand Up @@ -286,92 +285,10 @@ fn show_override(cfg: &Cfg) -> Result<()> {
Ok(())
}

fn list_overrides(cfg: &Cfg) -> Result<()> {
let mut overrides = try!(cfg.override_db.list());

overrides.sort();

if overrides.is_empty() {
println!("no overrides");
} else {
for o in overrides {
println!("{}", o);
}
}
Ok(())
}

fn list_toolchains(cfg: &Cfg) -> Result<()> {
let mut toolchains = try!(cfg.list_toolchains());

toolchains.sort();

if toolchains.is_empty() {
println!("no installed toolchains");
} else {
for toolchain in toolchains {
println!("{}", &toolchain);
}
}
Ok(())
}

fn update_all_channels(cfg: &Cfg) -> Result<()> {
let toolchains = try!(cfg.update_all_channels());

let max_name_length = toolchains.iter().map(|&(ref n, _)| n.len()).max().unwrap_or(0);
let padding_str: String = iter::repeat(' ').take(max_name_length).collect();

println!("");
let mut t = term::stdout().unwrap();
for &(ref name, ref result) in &toolchains {
let _ = t.fg(term::color::BRIGHT_WHITE);
let _ = t.bg(term::color::BLACK);
let _ = write!(t,
"{}{}",
&padding_str[0..(max_name_length - name.len())],
name);
let _ = t.reset();
let _ = write!(t, " update ");
if result.is_ok() {
let _ = t.fg(term::color::BRIGHT_GREEN);
let _ = writeln!(t, "succeeded");
let _ = t.reset();
} else {
let _ = t.fg(term::color::BRIGHT_RED);
let _ = writeln!(t, "FAILED");
let _ = t.reset();
}
}
println!("");

for (name, _) in toolchains {
let _ = t.fg(term::color::BRIGHT_WHITE);
let _ = t.bg(term::color::BLACK);
let _ = write!(t, "{}", name);
let _ = t.reset();
let _ = writeln!(t, " revision:");
println!("");
try!(show_tool_versions(&try!(cfg.get_toolchain(&name, false))));
println!("");
}
Ok(())
}

fn list_targets(cfg: &Cfg, m: &ArgMatches) -> Result<()> {
let toolchain = m.value_of("toolchain").unwrap();
let toolchain = try!(cfg.get_toolchain(toolchain, false));
for component in try!(toolchain.list_components()) {
if component.component.pkg == "rust-std" {
if component.required {
println!("{} (default)", component.component.target);
} else if component.installed {
println!("{} (installed)", component.component.target);
} else {
println!("{}", component.component.target);
}
}
}
try!(common::list_targets(&toolchain));

Ok(())
}
Expand Down

0 comments on commit 5f93275

Please sign in to comment.