From a07ee8c0e3b7634bd0b5725348780c19c82f1446 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 22 Nov 2016 04:30:50 +0000 Subject: [PATCH] Set up ~/.multirust as a temporary symlink to ~/.rustup --- src/rustup-cli/self_update.rs | 6 ++++ src/rustup-mock/src/clitools.rs | 4 +-- src/rustup-utils/src/utils.rs | 55 ++++++++++++++++++++++++++++++++- tests/cli-rustup.rs | 49 +++++++++++++++++++++-------- tests/cli-self-upd.rs | 38 +++++++++++++++++++++-- 5 files changed, 134 insertions(+), 18 deletions(-) diff --git a/src/rustup-cli/self_update.rs b/src/rustup-cli/self_update.rs index 68135847cd..00fc26619e 100644 --- a/src/rustup-cli/self_update.rs +++ b/src/rustup-cli/self_update.rs @@ -228,6 +228,10 @@ pub fn install(no_prompt: bool, verbose: bool, if !opts.no_modify_path { try!(do_add_to_path(&get_add_path_methods())); } + // Create ~/.rustup and a compatibility ~/.multirust symlink. + // FIXME: Someday we can stop setting up the symlink, and when + // we do that we can stop creating ~/.rustup as well. + try!(utils::create_rustup_home()); try!(maybe_install_rust(&opts.default_toolchain, &opts.default_host_triple, verbose)); if cfg!(unix) { @@ -607,6 +611,8 @@ pub fn uninstall(no_prompt: bool) -> Result<()> { info!("removing rustup home"); + try!(utils::delete_legacy_multirust_symlink()); + // Delete RUSTUP_HOME let ref rustup_dir = try!(utils::multirust_home()); if rustup_dir.exists() { diff --git a/src/rustup-mock/src/clitools.rs b/src/rustup-mock/src/clitools.rs index c1790cd0b9..f04417d51a 100644 --- a/src/rustup-mock/src/clitools.rs +++ b/src/rustup-mock/src/clitools.rs @@ -259,9 +259,9 @@ pub fn env(config: &Config, cmd: &mut Command) { cmd.env("CARGO_HOME", config.cargodir.to_string_lossy().to_string()); cmd.env("RUSTUP_OVERRIDE_HOST_TRIPLE", this_host_triple()); - // This is only used for some installation tests on unix where CARGO_HOME - // above is unset + // These are used in some installation tests that unset RUSTUP_HOME/CARGO_HOME cmd.env("HOME", config.homedir.to_string_lossy().to_string()); + cmd.env("USERPROFILE", config.homedir.to_string_lossy().to_string()); // Setting HOME will confuse the sudo check for rustup-init. Override it cmd.env("RUSTUP_INIT_SKIP_SUDO_CHECK", "yes"); diff --git a/src/rustup-utils/src/utils.rs b/src/rustup-utils/src/utils.rs index 7ae21f2672..ffbf69164a 100644 --- a/src/rustup-utils/src/utils.rs +++ b/src/rustup-utils/src/utils.rs @@ -598,10 +598,14 @@ pub fn do_rustup_home_upgrade() -> bool { old_rustup_dir_removed && if multirust_dir_exists() { if rustup_dir_exists() { // There appears to be both a ~/.multirust dir and a valid ~/.rustup - // dir. Weird situation. Pick ~/.rustup. + // dir. Most likely because one is a symlink to the other, as configured + // below. true } else { if rename_multirust_dir_to_rustup().is_ok() { + // Finally, making the hardlink from ~/.multirust back to + // ~/.rustup, for temporary compatibility. + let _ = create_legacy_multirust_symlink(); true } else { false @@ -612,6 +616,51 @@ pub fn do_rustup_home_upgrade() -> bool { } } +// Creates a ~/.rustup folder and a ~/.multirust symlink +pub fn create_rustup_home() -> Result<()> { + // If RUSTUP_HOME is set then don't make any assumptions about where it's + // ok to put ~/.multirust + if env::var_os("RUSTUP_HOME").is_some() { return Ok(()) } + + let home = rustup_home_in_user_dir()?; + fs::create_dir_all(&home) + .chain_err(|| "unable to create ~/.rustup")?; + + // This is a temporary compatibility symlink + create_legacy_multirust_symlink()?; + + Ok(()) +} + +// Create a symlink from ~/.multirust to ~/.rustup to temporarily +// accomodate old tools that are expecting that directory +fn create_legacy_multirust_symlink() -> Result<()> { + let newhome = rustup_home_in_user_dir()?; + let oldhome = legacy_multirust_home()?; + + raw::symlink_dir(&newhome, &oldhome) + .chain_err(|| format!("unable to symlink {} from {}", + newhome.display(), oldhome.display()))?; + + Ok(()) +} + +pub fn delete_legacy_multirust_symlink() -> Result<()> { + let oldhome = legacy_multirust_home()?; + + if oldhome.exists() { + let meta = fs::symlink_metadata(&oldhome) + .chain_err(|| "unable to get metadata for ~/.multirust")?; + if meta.file_type().is_symlink() { + // remove_dir handles unlinking symlinks + raw::remove_dir(&oldhome) + .chain_err(|| format!("unable to delete legacy symlink {}", oldhome.display()))?; + } + } + + Ok(()) +} + fn dot_dir(name: &str) -> Option { home_dir().map(|p| p.join(name)) } @@ -620,6 +669,10 @@ pub fn legacy_multirust_home() -> Result { dot_dir(".multirust").ok_or(ErrorKind::MultirustHome.into()) } +pub fn rustup_home_in_user_dir() -> Result { + dot_dir(".rustup").ok_or(ErrorKind::MultirustHome.into()) +} + pub fn multirust_home() -> Result { let use_rustup_dir = do_rustup_home_upgrade(); diff --git a/tests/cli-rustup.rs b/tests/cli-rustup.rs index 699ffb1c32..4679cc7dde 100644 --- a/tests/cli-rustup.rs +++ b/tests/cli-rustup.rs @@ -589,7 +589,7 @@ fn remove_component() { // Run without setting RUSTUP_HOME, with setting HOME and USERPROFILE fn run_no_home(config: &Config, args: &[&str], env: &[(&str, &str)]) -> process::Output { let home_dir_str = &format!("{}", config.homedir.display()); - let mut cmd = clitools::cmd(config, "rustup", args); + let mut cmd = clitools::cmd(config, args[0], &args[1..]); clitools::env(config, &mut cmd); cmd.env_remove("RUSTUP_HOME"); cmd.env("HOME", home_dir_str); @@ -612,9 +612,9 @@ fn multirust_dir_upgrade_rename_multirust_dir_to_rustup() { let multirust_dir_str = &format!("{}", multirust_dir.display()); // First write data into ~/.multirust - run_no_home(config, &["default", "stable"], + run_no_home(config, &["rustup", "default", "stable"], &[("RUSTUP_HOME", multirust_dir_str)]); - let out = run_no_home(config, &["toolchain", "list"], + let out = run_no_home(config, &["rustup", "toolchain", "list"], &[("RUSTUP_HOME", multirust_dir_str)]); assert!(String::from_utf8(out.stdout).unwrap().contains("stable")); @@ -624,10 +624,11 @@ fn multirust_dir_upgrade_rename_multirust_dir_to_rustup() { // Next run without RUSTUP_DIR, but with HOME/USERPROFILE set so rustup // can infer RUSTUP_DIR. It will silently move ~/.multirust to // ~/.rustup. - let out = run_no_home(config, &["toolchain", "list"], &[]); + let out = run_no_home(config, &["rustup", "toolchain", "list"], &[]); assert!(String::from_utf8(out.stdout).unwrap().contains("stable")); - assert!(!multirust_dir.exists()); + assert!(multirust_dir.exists()); + assert!(fs::symlink_metadata(&multirust_dir).unwrap().file_type().is_symlink()); assert!(rustup_dir.exists()); }); } @@ -645,9 +646,9 @@ fn multirust_dir_upgrade_old_rustup_exists() { let new_rustup_sh_version_file = rustup_sh_dir.join("rustup-version"); // First write data into ~/.multirust - run_no_home(config, &["default", "stable"], + run_no_home(config, &["rustup", "default", "stable"], &[("RUSTUP_HOME", multirust_dir_str)]); - let out = run_no_home(config, &["toolchain", "list"], + let out = run_no_home(config, &["rustup", "toolchain", "list"], &[("RUSTUP_HOME", multirust_dir_str)]); assert!(String::from_utf8(out.stdout).unwrap().contains("stable")); @@ -660,10 +661,11 @@ fn multirust_dir_upgrade_old_rustup_exists() { assert!(old_rustup_sh_version_file.exists()); // Now do the upgrade, and ~/.rustup will be moved to ~/.rustup.sh - let out = run_no_home(config, &["toolchain", "list"], &[]); + let out = run_no_home(config, &["rustup", "toolchain", "list"], &[]); assert!(String::from_utf8(out.stdout).unwrap().contains("stable")); - assert!(!multirust_dir.exists()); + assert!(multirust_dir.exists()); + assert!(fs::symlink_metadata(&multirust_dir).unwrap().file_type().is_symlink()); assert!(rustup_dir.exists()); assert!(!old_rustup_sh_version_file.exists()); assert!(new_rustup_sh_version_file.exists()); @@ -684,9 +686,9 @@ fn multirust_dir_upgrade_old_rustup_existsand_new_rustup_sh_exists() { let new_rustup_sh_version_file = rustup_sh_dir.join("rustup-version"); // First write data into ~/.multirust - run_no_home(config, &["default", "stable"], + run_no_home(config, &["rustup", "default", "stable"], &[("RUSTUP_HOME", multirust_dir_str)]); - let out = run_no_home(config, &["toolchain", "list"], + let out = run_no_home(config, &["rustup", "toolchain", "list"], &[("RUSTUP_HOME", multirust_dir_str)]); assert!(String::from_utf8(out.stdout).unwrap().contains("stable")); @@ -708,12 +710,33 @@ fn multirust_dir_upgrade_old_rustup_existsand_new_rustup_sh_exists() { assert!(new_rustup_sh_version_file.exists()); // Now do the upgrade, and ~/.rustup will be moved to ~/.rustup.sh - let out = run_no_home(config, &["toolchain", "list"], &[]); + let out = run_no_home(config, &["rustup", "toolchain", "list"], &[]); assert!(String::from_utf8(out.stdout).unwrap().contains("stable")); - assert!(!multirust_dir.exists()); + // .multirust is now a symlink to .rustup + assert!(multirust_dir.exists()); + assert!(fs::symlink_metadata(&multirust_dir).unwrap().file_type().is_symlink()); + assert!(rustup_dir.exists()); assert!(!old_rustup_sh_version_file.exists()); assert!(new_rustup_sh_version_file.exists()); }); } + +#[test] +fn multirust_upgrade_works_with_proxy() { + setup(&|config| { + let multirust_dir = config.homedir.join(".multirust"); + let rustup_dir = config.homedir.join(".rustup"); + + // Put data in ~/.multirust + run_no_home(config, &["rustup", "default", "stable"], + &[("RUSTUP_HOME", &format!("{}", multirust_dir.display()))]); + + run_no_home(config, &["rustc", "--version"], &[]); + + assert!(multirust_dir.exists()); + assert!(fs::symlink_metadata(&multirust_dir).unwrap().file_type().is_symlink()); + assert!(rustup_dir.exists()); + }); +} diff --git a/tests/cli-self-upd.rs b/tests/cli-self-upd.rs index 13e4556c19..e3013cff07 100644 --- a/tests/cli-self-upd.rs +++ b/tests/cli-self-upd.rs @@ -802,9 +802,9 @@ fn install_sets_up_stable_unless_there_is_already_a_default() { #[cfg(unix)] fn install_deletes_legacy_multirust_bins() { setup(&|config| { - let ref multirust_bin_dir = config.rustupdir.join("bin"); + let ref multirust_bin_dir = config.homedir.join(".multirust/bin"); fs::create_dir_all(multirust_bin_dir).unwrap(); - let ref multirust_bin = multirust_bin_dir.join("rustup"); + let ref multirust_bin = multirust_bin_dir.join("multirust"); let ref rustc_bin = multirust_bin_dir.join("rustc"); raw::write_file(multirust_bin, "").unwrap(); raw::write_file(rustc_bin, "").unwrap(); @@ -1076,3 +1076,37 @@ fn legacy_upgrade_removes_multirust_bin() { assert!(!multirust_bin.exists()); }); } + +// Create a ~/.multirust symlink to ~/.rustup +#[test] +fn install_creates_legacy_home_symlink() { + setup(&|config| { + let mut cmd = clitools::cmd(config, "rustup-init", &["-y"]); + // It'll only do this behavior when RUSTUP_HOME isn't set + cmd.env_remove("RUSTUP_HOME"); + + assert!(cmd.output().unwrap().status.success()); + + let rustup_dir = config.homedir.join(".rustup"); + assert!(rustup_dir.exists()); + let multirust_dir = config.homedir.join(".multirust"); + assert!(multirust_dir.exists()); + assert!(fs::symlink_metadata(&multirust_dir).unwrap().file_type().is_symlink()); + }); +} + +#[test] +fn uninstall_removes_legacy_home_symlink() { + setup(&|config| { + let mut cmd = clitools::cmd(config, "rustup-init", &["-y"]); + // It'll only do this behavior when RUSTUP_HOME isn't set + cmd.env_remove("RUSTUP_HOME"); + assert!(cmd.output().unwrap().status.success()); + + let multirust_dir = config.homedir.join(".multirust"); + assert!(multirust_dir.exists()); + + expect_ok(config, &["rustup", "self", "uninstall", "-y"]); + assert!(!multirust_dir.exists()); + }); +}