Skip to content

Commit

Permalink
feat: Update/check after installation
Browse files Browse the repository at this point in the history
In order to make things slightly more useful for people, we want to
update existing toolchains and/or check to see if updates are available
but only if the installer didn't just do the only toolchain already.

In interactive mode we default to update, in non-interactive mode to
check, and the user is at liberty to override.

Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
  • Loading branch information
kinnison committed May 19, 2020
1 parent 615376c commit 1d9f443
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 30 deletions.
92 changes: 68 additions & 24 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub struct InstallOpts<'a> {
pub no_modify_path: bool,
pub components: &'a [&'a str],
pub targets: &'a [&'a str],
pub post_install: Option<String>,
}

#[cfg(feature = "no-self-update")]
Expand Down Expand Up @@ -289,13 +290,13 @@ pub fn install(no_prompt: bool, verbose: bool, quiet: bool, mut opts: InstallOpt
}
}

let install_res: Result<()> = (|| {
let install_res: Result<usize> = (|| {
install_bins()?;
if !opts.no_modify_path {
do_add_to_path(&get_add_path_methods())?;
}
utils::create_rustup_home()?;
maybe_install_rust(
let previous_toolchain_count = maybe_install_rust(
opts.default_toolchain.as_deref(),
&opts.profile,
opts.default_host_triple.as_deref(),
Expand All @@ -311,24 +312,53 @@ pub fn install(no_prompt: bool, verbose: bool, quiet: bool, mut opts: InstallOpt
utils::write_file("env", &env_file, &env_str)?;
}

Ok(())
Ok(previous_toolchain_count)
})();

if let Err(ref e) = install_res {
common::report_error(e);
match install_res {
Err(ref e) => {
common::report_error(e);

// On windows, where installation happens in a console
// that may have opened just for this purpose, give
// the user an opportunity to see the error before the
// window closes.
if cfg!(windows) && !no_prompt {
println!();
println!("Press the Enter key to continue.");
common::read_line()?;
}

// On windows, where installation happens in a console
// that may have opened just for this purpose, give
// the user an opportunity to see the error before the
// window closes.
if cfg!(windows) && !no_prompt {
println!();
println!("Press the Enter key to continue.");
common::read_line()?;
process::exit(1);
}

process::exit(1);
}
Ok(prev_count) if prev_count > 0 => {
// Next we use the newly installed rustup to either do a check or an update
// we run this directly using the path we installed into and we'll report if
// there was a problem doing it.

if let Some(cmd) = opts.post_install.as_deref() {
let rustup = PathBuf::from(utils::cargo_home()?)
.join("bin")
.join(format!("rustup{}", EXE_SUFFIX));
let mut rustup = Command::new(rustup);
rustup.arg(cmd);
if cmd == "update" {
// No point in self-updating at this point
rustup.arg("--no-self-update");
}
let mut output = rustup.spawn()?;
let code = output.wait()?;
if !code.success() {
println!();
println!(
"Running `rustup {}` did not succeed, you may wish to check your system",
cmd
);
}
}
}
_ => {}
};

let cargo_home = canonical_cargo_home()?;
#[cfg(windows)]
Expand Down Expand Up @@ -594,10 +624,11 @@ fn current_install_opts(opts: &InstallOpts) -> String {
format!(
r"Current installation options:
- ` `default host triple: `{}`
- ` `default toolchain: `{}`
- ` `profile: `{}`
- modify PATH variable: `{}`
- ` `default host triple: `{}`
- ` `default toolchain: `{}`
- ` `profile: `{}`
- ` `modify PATH variable: `{}`
- post installation command: `{}`
",
opts.default_host_triple
.as_ref()
Expand All @@ -607,7 +638,8 @@ fn current_install_opts(opts: &InstallOpts) -> String {
.as_deref()
.unwrap_or("stable (default)"),
opts.profile,
if !opts.no_modify_path { "yes" } else { "no" }
if !opts.no_modify_path { "yes" } else { "no" },
opts.post_install.as_deref().unwrap_or("none"),
)
}

Expand Down Expand Up @@ -643,6 +675,18 @@ fn customize_install(mut opts: InstallOpts) -> Result<InstallOpts> {
opts.no_modify_path =
!common::question_bool("Modify PATH variable? (y/n)", !opts.no_modify_path)?;

opts.post_install = {
let s = common::question_str(
"Post installation command to run? (update/check/none)",
opts.post_install.as_deref().unwrap_or("none"),
)?;
if s == "none" {
None
} else {
Some(s)
}
};

Ok(opts)
}

Expand Down Expand Up @@ -749,10 +793,10 @@ fn maybe_install_rust(
targets: &[&str],
verbose: bool,
quiet: bool,
) -> Result<()> {
) -> Result<usize> {
let mut cfg = common::set_globals(verbose, quiet)?;
cfg.set_profile(profile_str)?;

let toolchain_count = cfg.list_toolchains()?.len();
if let Some(default_host_triple) = default_host_triple {
// Set host triple now as it will affect resolution of toolchain_str
info!("setting default host triple to {}", default_host_triple);
Expand Down Expand Up @@ -802,7 +846,7 @@ fn maybe_install_rust(
println!();
}

Ok(())
Ok(toolchain_count)
}

pub fn uninstall(no_prompt: bool) -> Result<()> {
Expand Down
19 changes: 19 additions & 0 deletions src/cli/setup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ pub fn main() -> Result<()> {
.short("y")
.help("Disable confirmation prompt."),
)
.arg(
Arg::with_name("post-install")
.long("post-install")
.short("p")
.help("operation to run after installation")
.takes_value(true)
.possible_values(&["update-if-interactive", "update", "check", "none"])
.default_value("update-if-interactive"),
)
.arg(
Arg::with_name("default-host")
.long("default-host")
Expand Down Expand Up @@ -96,6 +105,15 @@ pub fn main() -> Result<()> {
.expect("Unreachable: Clap should supply a default");
let no_modify_path = matches.is_present("no-modify-path");

let post_install = match (no_prompt, matches.value_of("post-install").unwrap()) {
(_, "none") => None,
(_, "check") => Some("check"),
(_, "update") => Some("update"),
(true, _) => Some("check"),
(false, _) => Some("update"),
}
.map(String::from);

let components: Vec<_> = matches
.values_of("components")
.map(|v| v.collect())
Expand All @@ -113,6 +131,7 @@ pub fn main() -> Result<()> {
no_modify_path,
components: &components,
targets: &targets,
post_install,
};

if profile == "complete" {
Expand Down
21 changes: 15 additions & 6 deletions tests/cli-inst-interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ use std::io::Write;
use std::process::Stdio;
use std::sync::Mutex;

macro_rules! for_host {
($s: expr) => {
&format!($s, this_host_triple())
};
}

pub fn setup_(complex: bool, f: &dyn Fn(&Config)) {
let scenario = if complex {
Scenario::UnavailableRls
Expand Down Expand Up @@ -128,15 +134,18 @@ fn blank_lines_around_stderr_log_output_update() {
println!("-- stdout --\n {}", out.stdout);
println!("-- stderr --\n {}", out.stderr);

assert!(out.stdout.contains(
assert!(out.stdout.contains(for_host!(
r"
3) Cancel installation
>
stable-{} unchanged - 1.1.0 (hash-stable-1.1.0)
Rust is installed now. Great!
"
));
)));
});
}

Expand Down Expand Up @@ -206,7 +215,7 @@ fn with_non_release_channel_non_default_toolchain() {
#[test]
fn set_nightly_toolchain() {
setup(&|config| {
let out = run_input(config, &["rustup-init"], "2\n\nnightly\n\n\n\n\n");
let out = run_input(config, &["rustup-init"], "2\n\nnightly\n\n\n\n\n\n");
assert!(out.ok);

expect_stdout_ok(config, &["rustup", "show"], "nightly");
Expand All @@ -216,7 +225,7 @@ fn set_nightly_toolchain() {
#[test]
fn set_no_modify_path() {
setup(&|config| {
let out = run_input(config, &["rustup-init"], "2\n\n\n\nno\n\n\n");
let out = run_input(config, &["rustup-init"], "2\n\n\n\nno\n\n\n\n");
assert!(out.ok);

if cfg!(unix) {
Expand All @@ -231,7 +240,7 @@ fn set_nightly_toolchain_and_unset() {
let out = run_input(
config,
&["rustup-init"],
"2\n\nnightly\n\n\n2\n\nbeta\n\n\n\n\n",
"2\n\nnightly\n\n\n\n2\n\nbeta\n\n\n\n\n\n",
);
assert!(out.ok);

Expand All @@ -242,7 +251,7 @@ fn set_nightly_toolchain_and_unset() {
#[test]
fn user_says_nope_after_advanced_install() {
setup(&|config| {
let out = run_input(config, &["rustup-init"], "2\n\n\n\n\nn\n\n\n");
let out = run_input(config, &["rustup-init"], "2\n\n\n\n\n\nn\n\n\n");
assert!(out.ok);
assert!(!config.cargodir.join("bin").exists());
});
Expand Down

0 comments on commit 1d9f443

Please sign in to comment.