Skip to content

Commit 4656d95

Browse files
authored
Merge pull request #2214 from sollyucko/patch-1
Allow installing alongside existing Rust (with warning)
2 parents bd2d51e + 1e0a497 commit 4656d95

File tree

5 files changed

+160
-20
lines changed

5 files changed

+160
-20
lines changed

src/cli/common.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,17 @@ pub fn report_error(e: &Error) {
522522
}
523523
}
524524
}
525+
526+
pub fn ignorable_error(error: crate::errors::Error, no_prompt: bool) -> Result<()> {
527+
report_error(&error);
528+
if no_prompt {
529+
warn!("continuing (because the -y flag is set and the error is ignorable)");
530+
Ok(())
531+
} else {
532+
if confirm("\nContinue? (y/N)", false).unwrap_or(false) {
533+
Ok(())
534+
} else {
535+
Err(error)
536+
}
537+
}
538+
}

src/cli/self_update.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
//! Deleting the running binary during uninstall is tricky
3131
//! and racy on Windows.
3232
33-
use crate::common::{self, Confirm};
33+
use crate::common::{self, ignorable_error, Confirm};
3434
use crate::errors::*;
3535
use crate::markdown::md;
3636
use crate::term2;
@@ -236,9 +236,16 @@ fn canonical_cargo_home() -> Result<String> {
236236
/// `CARGO_HOME`/bin, hard-linking the various Rust tools to it,
237237
/// and adding `CARGO_HOME`/bin to PATH.
238238
pub fn install(no_prompt: bool, verbose: bool, quiet: bool, mut opts: InstallOpts) -> Result<()> {
239-
do_pre_install_sanity_checks()?;
239+
if !env::var_os("RUSTUP_INIT_SKIP_EXISTENCE_CHECKS").map_or(false, |s| s == "yes") {
240+
do_pre_install_sanity_checks(no_prompt)?;
241+
}
242+
240243
do_pre_install_options_sanity_checks(&opts)?;
241-
check_existence_of_rustc_or_cargo_in_path(no_prompt)?;
244+
245+
if !env::var_os("RUSTUP_INIT_SKIP_EXISTENCE_CHECKS").map_or(false, |s| s == "yes") {
246+
check_existence_of_rustc_or_cargo_in_path(no_prompt)?;
247+
}
248+
242249
#[cfg(unix)]
243250
do_anti_sudo_check(no_prompt)?;
244251

@@ -379,25 +386,25 @@ fn check_existence_of_rustc_or_cargo_in_path(no_prompt: bool) -> Result<()> {
379386
// Only the test runner should set this
380387
let skip_check = env::var_os("RUSTUP_INIT_SKIP_PATH_CHECK");
381388

382-
// Ignore this check if called with no prompt (-y) or if the environment variable is set
383-
if no_prompt || skip_check == Some("yes".into()) {
389+
// Skip this if the environment variable is set
390+
if skip_check == Some("yes".into()) {
384391
return Ok(());
385392
}
386393

387394
if let Err(path) = rustc_or_cargo_exists_in_path() {
388-
err!("it looks like you have an existing installation of Rust at:");
389-
err!("{}", path);
390-
err!("rustup should not be installed alongside Rust. Please uninstall your existing Rust first.");
391-
err!("Otherwise you may have confusion unless you are careful with your PATH");
392-
err!("If you are sure that you want both rustup and your already installed Rust");
393-
err!("then please restart the installation and pass `-y' to bypass this check.");
394-
Err("cannot install while Rust is installed".into())
395-
} else {
396-
Ok(())
395+
warn!("it looks like you have an existing installation of Rust at:");
396+
warn!("{}", path);
397+
warn!("rustup should not be installed alongside Rust. Please uninstall your existing Rust first.");
398+
warn!("Otherwise you may have confusion unless you are careful with your PATH");
399+
warn!("If you are sure that you want both rustup and your already installed Rust");
400+
warn!("then please reply `y' or `yes' or set RUSTUP_INIT_SKIP_PATH_CHECK to yes");
401+
warn!("or pass `-y' to ignore all ignorable checks.");
402+
ignorable_error("cannot install while Rust is installed".into(), no_prompt)?;
397403
}
404+
Ok(())
398405
}
399406

400-
fn do_pre_install_sanity_checks() -> Result<()> {
407+
fn do_pre_install_sanity_checks(no_prompt: bool) -> Result<()> {
401408
let rustc_manifest_path = PathBuf::from("/usr/local/lib/rustlib/manifest-rustc");
402409
let uninstaller_path = PathBuf::from("/usr/local/lib/rustlib/uninstall.sh");
403410
let rustup_sh_path = utils::home_dir().unwrap().join(".rustup");
@@ -413,7 +420,7 @@ fn do_pre_install_sanity_checks() -> Result<()> {
413420
"run `{}` as root to uninstall Rust",
414421
uninstaller_path.display()
415422
);
416-
return Err("cannot install while Rust is installed".into());
423+
ignorable_error("cannot install while Rust is installed".into(), no_prompt)?;
417424
}
418425

419426
if rustup_sh_exists {
@@ -423,7 +430,10 @@ fn do_pre_install_sanity_checks() -> Result<()> {
423430
warn!("or, if you already have rustup installed, you can run");
424431
warn!("`rustup self update` and `rustup toolchain list` to upgrade");
425432
warn!("your directory structure");
426-
return Err("cannot install while rustup.sh is installed".into());
433+
ignorable_error(
434+
"cannot install while rustup.sh is installed".into(),
435+
no_prompt,
436+
)?;
427437
}
428438

429439
Ok(())

tests/cli-inst-interactive.rs

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use crate::mock::clitools::{
88
};
99
use crate::mock::{get_path, restore_path};
1010
use lazy_static::lazy_static;
11+
use rustup::utils::raw;
12+
use std::fs;
1113
use std::io::Write;
1214
use std::process::Stdio;
1315
use std::sync::Mutex;
@@ -39,9 +41,22 @@ pub fn setup(f: &dyn Fn(&Config)) {
3941
}
4042

4143
fn run_input(config: &Config, args: &[&str], input: &str) -> SanitizedOutput {
44+
run_input_with_env(config, args, input, &[])
45+
}
46+
47+
fn run_input_with_env(
48+
config: &Config,
49+
args: &[&str],
50+
input: &str,
51+
env: &[(&str, &str)],
52+
) -> SanitizedOutput {
4253
let mut cmd = clitools::cmd(config, args[0], &args[1..]);
4354
clitools::env(config, &mut cmd);
4455

56+
for (key, value) in env.iter() {
57+
cmd.env(key, value);
58+
}
59+
4560
cmd.stdin(Stdio::piped());
4661
cmd.stdout(Stdio::piped());
4762
cmd.stderr(Stdio::piped());
@@ -266,3 +281,104 @@ fn test_warn_if_complete_profile_is_used() {
266281
);
267282
});
268283
}
284+
285+
fn create_rustup_sh_metadata(config: &Config) {
286+
let rustup_dir = config.homedir.join(".rustup");
287+
fs::create_dir_all(&rustup_dir).unwrap();
288+
let version_file = rustup_dir.join("rustup-version");
289+
raw::write_file(&version_file, "").unwrap();
290+
}
291+
292+
#[test]
293+
fn test_prompt_fail_if_rustup_sh_already_installed_reply_nothing() {
294+
setup(&|config| {
295+
create_rustup_sh_metadata(&config);
296+
let out = run_input(config, &["rustup-init"], "\n");
297+
assert!(!out.ok);
298+
assert!(out
299+
.stderr
300+
.contains("warning: it looks like you have existing rustup.sh metadata"));
301+
assert!(out
302+
.stderr
303+
.contains("error: cannot install while rustup.sh is installed"));
304+
assert!(out.stdout.contains("Continue? (y/N)"));
305+
})
306+
}
307+
308+
#[test]
309+
fn test_prompt_fail_if_rustup_sh_already_installed_reply_no() {
310+
setup(&|config| {
311+
create_rustup_sh_metadata(&config);
312+
let out = run_input(config, &["rustup-init"], "no\n");
313+
assert!(!out.ok);
314+
assert!(out
315+
.stderr
316+
.contains("warning: it looks like you have existing rustup.sh metadata"));
317+
assert!(out
318+
.stderr
319+
.contains("error: cannot install while rustup.sh is installed"));
320+
assert!(out.stdout.contains("Continue? (y/N)"));
321+
})
322+
}
323+
324+
#[test]
325+
fn test_prompt_succeed_if_rustup_sh_already_installed_reply_yes() {
326+
setup(&|config| {
327+
create_rustup_sh_metadata(&config);
328+
let out = run_input(config, &["rustup-init"], "yes\n\n\n");
329+
assert!(out.ok);
330+
assert!(out
331+
.stderr
332+
.contains("warning: it looks like you have existing rustup.sh metadata"));
333+
assert!(out
334+
.stderr
335+
.contains("error: cannot install while rustup.sh is installed"));
336+
assert!(out.stdout.contains("Continue? (y/N)"));
337+
assert!(!out.stdout.contains(
338+
"warning: continuing (because the -y flag is set and the error is ignorable)"
339+
))
340+
})
341+
}
342+
343+
#[test]
344+
fn test_warn_succeed_if_rustup_sh_already_installed_y_flag() {
345+
setup(&|config| {
346+
create_rustup_sh_metadata(&config);
347+
let out = run_input(config, &["rustup-init", "-y"], "");
348+
assert!(out.ok);
349+
assert!(out
350+
.stderr
351+
.contains("warning: it looks like you have existing rustup.sh metadata"));
352+
assert!(out
353+
.stderr
354+
.contains("error: cannot install while rustup.sh is installed"));
355+
assert!(out.stderr.contains(
356+
"warning: continuing (because the -y flag is set and the error is ignorable)"
357+
));
358+
assert!(!out.stdout.contains("Continue? (y/N)"));
359+
})
360+
}
361+
362+
#[test]
363+
fn test_succeed_if_rustup_sh_already_installed_env_var_set() {
364+
setup(&|config| {
365+
create_rustup_sh_metadata(&config);
366+
let out = run_input_with_env(
367+
config,
368+
&["rustup-init", "-y"],
369+
"",
370+
&[("RUSTUP_INIT_SKIP_EXISTENCE_CHECKS", "yes")],
371+
);
372+
assert!(out.ok);
373+
assert!(!out
374+
.stderr
375+
.contains("warning: it looks like you have existing rustup.sh metadata"));
376+
assert!(!out
377+
.stderr
378+
.contains("error: cannot install while rustup.sh is installed"));
379+
assert!(!out.stderr.contains(
380+
"warning: continuing (because the -y flag is set and the error is ignorable)"
381+
));
382+
assert!(!out.stdout.contains("Continue? (y/N)"));
383+
})
384+
}

tests/cli-misc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ fn install_stops_if_rustc_exists() {
620620
.contains("it looks like you have an existing installation of Rust at:"));
621621
assert!(out
622622
.stderr
623-
.contains("restart the installation and pass `-y'"));
623+
.contains("If you are sure that you want both rustup and your already installed Rust"));
624624
});
625625
}
626626

@@ -652,7 +652,7 @@ fn install_stops_if_cargo_exists() {
652652
.contains("it looks like you have an existing installation of Rust at:"));
653653
assert!(out
654654
.stderr
655-
.contains("restart the installation and pass `-y'"));
655+
.contains("If you are sure that you want both rustup and your already installed Rust"));
656656
});
657657
}
658658

tests/cli-self-upd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ fn install_but_rustup_sh_is_installed() {
12091209
fs::create_dir_all(&rustup_dir).unwrap();
12101210
let version_file = rustup_dir.join("rustup-version");
12111211
raw::write_file(&version_file, "").unwrap();
1212-
expect_err(
1212+
expect_stderr_ok(
12131213
config,
12141214
&["rustup-init", "-y"],
12151215
"cannot install while rustup.sh is installed",

0 commit comments

Comments
 (0)