Skip to content

Commit c7e0012

Browse files
Extract Unix fn from self_update.rs
This introduces a strategy of defining a module that describes OS-specific functions and re-exports those functions from there.
1 parent 19d558c commit c7e0012

File tree

2 files changed

+157
-134
lines changed

2 files changed

+157
-134
lines changed

src/cli/self_update.rs

Lines changed: 15 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ use std::path::{Component, Path, PathBuf};
4949
use std::process::{self, Command};
5050
mod types;
5151
use types::PathUpdateMethod;
52+
#[cfg(unix)]
53+
mod unix;
54+
#[cfg(unix)]
55+
mod os {
56+
#[cfg(unix)]
57+
pub use crate::self_update::unix::*;
58+
}
59+
60+
#[cfg(unix)]
61+
pub use os::{
62+
complete_windows_uninstall, delete_rustup_and_cargo_home, run_update, self_replace,
63+
};
64+
#[cfg(unix)]
65+
use os::*;
5266

5367
pub struct InstallOpts<'a> {
5468
pub default_host_triple: Option<String>,
@@ -477,42 +491,6 @@ fn do_pre_install_options_sanity_checks(opts: &InstallOpts) -> Result<()> {
477491
Ok(())
478492
}
479493

480-
// If the user is trying to install with sudo, on some systems this will
481-
// result in writing root-owned files to the user's home directory, because
482-
// sudo is configured not to change $HOME. Don't let that bogosity happen.
483-
#[cfg(unix)]
484-
fn do_anti_sudo_check(no_prompt: bool) -> Result<()> {
485-
pub fn home_mismatch() -> (bool, PathBuf, PathBuf) {
486-
let fallback = || (false, PathBuf::new(), PathBuf::new());
487-
// test runner should set this, nothing else
488-
if env::var_os("RUSTUP_INIT_SKIP_SUDO_CHECK").map_or(false, |s| s == "yes") {
489-
return fallback();
490-
}
491-
492-
match (utils::home_dir_from_passwd(), env::var_os("HOME")) {
493-
(Some(pw), Some(eh)) if eh != pw => return (true, PathBuf::from(eh), pw),
494-
(None, _) => warn!("getpwuid_r: couldn't get user data"),
495-
_ => {}
496-
}
497-
fallback()
498-
}
499-
500-
match home_mismatch() {
501-
(false, _, _) => {}
502-
(true, env_home, euid_home) => {
503-
err!("$HOME differs from euid-obtained home directory: you may be using sudo");
504-
err!("$HOME directory: {}", env_home.display());
505-
err!("euid-obtained home directory: {}", euid_home.display());
506-
if !no_prompt {
507-
err!("if this is what you want, restart the installation with `-y'");
508-
process::exit(1);
509-
}
510-
}
511-
}
512-
513-
Ok(())
514-
}
515-
516494
// Provide guidance about setting up MSVC if it doesn't appear to be
517495
// installed
518496
#[cfg(windows)]
@@ -537,6 +515,7 @@ fn do_msvc_check(opts: &InstallOpts) -> Result<bool> {
537515
Ok(true)
538516
}
539517

518+
540519
#[cfg(not(windows))]
541520
fn do_msvc_check(_opts: &InstallOpts) -> Result<bool> {
542521
Ok(true)
@@ -897,14 +876,6 @@ pub fn uninstall(no_prompt: bool) -> Result<()> {
897876
process::exit(0);
898877
}
899878

900-
#[cfg(unix)]
901-
fn delete_rustup_and_cargo_home() -> Result<()> {
902-
let cargo_home = utils::cargo_home()?;
903-
utils::remove_dir("cargo_home", &cargo_home, &|_: Notification<'_>| ())?;
904-
905-
Ok(())
906-
}
907-
908879
// The last step of uninstallation is to delete *this binary*,
909880
// rustup.exe and the CARGO_HOME that contains it. On Unix, this
910881
// works fine. On Windows you can't delete files while they are open,
@@ -1115,11 +1086,6 @@ fn wait_for_parent() -> Result<()> {
11151086
Ok(())
11161087
}
11171088

1118-
#[cfg(unix)]
1119-
pub fn complete_windows_uninstall() -> Result<()> {
1120-
panic!("stop doing that")
1121-
}
1122-
11231089
/// Decide which rcfiles we're going to update, so we
11241090
/// can tell the user before they confirm.
11251091
fn get_add_path_methods() -> Vec<PathUpdateMethod> {
@@ -1157,30 +1123,6 @@ fn shell_export_string() -> Result<String> {
11571123
Ok(format!(r#"export PATH="{}:$PATH""#, path))
11581124
}
11591125

1160-
#[cfg(unix)]
1161-
fn do_add_to_path(methods: &[PathUpdateMethod]) -> Result<()> {
1162-
for method in methods {
1163-
if let PathUpdateMethod::RcFile(ref rcpath) = *method {
1164-
let file = if rcpath.exists() {
1165-
utils::read_file("rcfile", rcpath)?
1166-
} else {
1167-
String::new()
1168-
};
1169-
let addition = format!("\n{}", shell_export_string()?);
1170-
if !file.contains(&addition) {
1171-
utils::append_file("rcfile", rcpath, &addition).chain_err(|| {
1172-
ErrorKind::WritingShellProfile {
1173-
path: rcpath.to_path_buf(),
1174-
}
1175-
})?;
1176-
}
1177-
} else {
1178-
unreachable!()
1179-
}
1180-
}
1181-
1182-
Ok(())
1183-
}
11841126

11851127
#[cfg(windows)]
11861128
fn do_add_to_path(methods: &[PathUpdateMethod]) -> Result<()> {
@@ -1371,35 +1313,6 @@ fn do_remove_from_path(methods: &[PathUpdateMethod]) -> Result<()> {
13711313
Ok(())
13721314
}
13731315

1374-
#[cfg(unix)]
1375-
fn do_remove_from_path(methods: &[PathUpdateMethod]) -> Result<()> {
1376-
for method in methods {
1377-
if let PathUpdateMethod::RcFile(ref rcpath) = *method {
1378-
let file = utils::read_file("rcfile", rcpath)?;
1379-
let addition = format!("\n{}\n", shell_export_string()?);
1380-
1381-
let file_bytes = file.into_bytes();
1382-
let addition_bytes = addition.into_bytes();
1383-
1384-
let idx = file_bytes
1385-
.windows(addition_bytes.len())
1386-
.position(|w| w == &*addition_bytes);
1387-
if let Some(i) = idx {
1388-
let mut new_file_bytes = file_bytes[..i].to_vec();
1389-
new_file_bytes.extend(&file_bytes[i + addition_bytes.len()..]);
1390-
let new_file = String::from_utf8(new_file_bytes).unwrap();
1391-
utils::write_file("rcfile", rcpath, &new_file)?;
1392-
} else {
1393-
// Weird case. rcfile no longer needs to be modified?
1394-
}
1395-
} else {
1396-
unreachable!()
1397-
}
1398-
}
1399-
1400-
Ok(())
1401-
}
1402-
14031316
/// Self update downloads rustup-init to `CARGO_HOME`/bin/rustup-init
14041317
/// and runs it.
14051318
///
@@ -1576,28 +1489,6 @@ pub fn prepare_update() -> Result<Option<PathBuf>> {
15761489
Ok(Some(setup_path))
15771490
}
15781491

1579-
/// Tell the upgrader to replace the rustup bins, then delete
1580-
/// itself. Like with uninstallation, on Windows we're going to
1581-
/// have to jump through hoops to make everything work right.
1582-
///
1583-
/// On windows we're not going to wait for it to finish before exiting
1584-
/// successfully, so it should not do much, and it should try
1585-
/// really hard to succeed, because at this point the upgrade is
1586-
/// considered successful.
1587-
#[cfg(unix)]
1588-
pub fn run_update(setup_path: &Path) -> Result<()> {
1589-
let status = Command::new(setup_path)
1590-
.arg("--self-replace")
1591-
.status()
1592-
.chain_err(|| "unable to run updater")?;
1593-
1594-
if !status.success() {
1595-
return Err("self-updated failed to replace rustup executable".into());
1596-
}
1597-
1598-
process::exit(0);
1599-
}
1600-
16011492
#[cfg(windows)]
16021493
pub fn run_update(setup_path: &Path) -> Result<()> {
16031494
Command::new(setup_path)
@@ -1608,16 +1499,6 @@ pub fn run_update(setup_path: &Path) -> Result<()> {
16081499
process::exit(0);
16091500
}
16101501

1611-
/// This function is as the final step of a self-upgrade. It replaces
1612-
/// `CARGO_HOME`/bin/rustup with the running exe, and updates the the
1613-
/// links to it. On windows this will run *after* the original
1614-
/// rustup process exits.
1615-
#[cfg(unix)]
1616-
pub fn self_replace() -> Result<()> {
1617-
install_bins()?;
1618-
1619-
Ok(())
1620-
}
16211502

16221503
#[cfg(windows)]
16231504
pub fn self_replace() -> Result<()> {

src/cli/self_update/unix.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use super::*;
2+
use rustup::utils::utils;
3+
use rustup::utils::Notification;
4+
use std::env;
5+
use std::path::{Path, PathBuf};
6+
use std::process::{self, Command};
7+
8+
// If the user is trying to install with sudo, on some systems this will
9+
// result in writing root-owned files to the user's home directory, because
10+
// sudo is configured not to change $HOME. Don't let that bogosity happen.
11+
pub fn do_anti_sudo_check(no_prompt: bool) -> Result<()> {
12+
pub fn home_mismatch() -> (bool, PathBuf, PathBuf) {
13+
let fallback = || (false, PathBuf::new(), PathBuf::new());
14+
// test runner should set this, nothing else
15+
if env::var_os("RUSTUP_INIT_SKIP_SUDO_CHECK").map_or(false, |s| s == "yes") {
16+
return fallback();
17+
}
18+
19+
match (utils::home_dir_from_passwd(), env::var_os("HOME")) {
20+
(Some(pw), Some(eh)) if eh != pw => return (true, PathBuf::from(eh), pw),
21+
(None, _) => warn!("getpwuid_r: couldn't get user data"),
22+
_ => {}
23+
}
24+
fallback()
25+
}
26+
27+
match home_mismatch() {
28+
(false, _, _) => {}
29+
(true, env_home, euid_home) => {
30+
err!("$HOME differs from euid-obtained home directory: you may be using sudo");
31+
err!("$HOME directory: {}", env_home.display());
32+
err!("euid-obtained home directory: {}", euid_home.display());
33+
if !no_prompt {
34+
err!("if this is what you want, restart the installation with `-y'");
35+
process::exit(1);
36+
}
37+
}
38+
}
39+
40+
Ok(())
41+
}
42+
43+
pub fn delete_rustup_and_cargo_home() -> Result<()> {
44+
let cargo_home = utils::cargo_home()?;
45+
utils::remove_dir("cargo_home", &cargo_home, &|_: Notification<'_>| ())?;
46+
47+
Ok(())
48+
}
49+
50+
pub fn complete_windows_uninstall() -> Result<()> {
51+
panic!("stop doing that")
52+
}
53+
54+
pub fn do_remove_from_path(methods: &[PathUpdateMethod]) -> Result<()> {
55+
for method in methods {
56+
if let PathUpdateMethod::RcFile(ref rcpath) = *method {
57+
let file = utils::read_file("rcfile", rcpath)?;
58+
let addition = format!("\n{}\n", shell_export_string()?);
59+
60+
let file_bytes = file.into_bytes();
61+
let addition_bytes = addition.into_bytes();
62+
63+
let idx = file_bytes
64+
.windows(addition_bytes.len())
65+
.position(|w| w == &*addition_bytes);
66+
if let Some(i) = idx {
67+
let mut new_file_bytes = file_bytes[..i].to_vec();
68+
new_file_bytes.extend(&file_bytes[i + addition_bytes.len()..]);
69+
let new_file = String::from_utf8(new_file_bytes).unwrap();
70+
utils::write_file("rcfile", rcpath, &new_file)?;
71+
} else {
72+
// Weird case. rcfile no longer needs to be modified?
73+
}
74+
} else {
75+
unreachable!()
76+
}
77+
}
78+
79+
Ok(())
80+
}
81+
82+
pub fn shell_export_string() -> Result<String> {
83+
let path = format!("{}/bin", canonical_cargo_home()?);
84+
// The path is *prepended* in case there are system-installed
85+
// rustc's that need to be overridden.
86+
Ok(format!(r#"export PATH="{}:$PATH""#, path))
87+
}
88+
89+
pub fn do_add_to_path(methods: &[PathUpdateMethod]) -> Result<()> {
90+
for method in methods {
91+
if let PathUpdateMethod::RcFile(ref rcpath) = *method {
92+
let file = if rcpath.exists() {
93+
utils::read_file("rcfile", rcpath)?
94+
} else {
95+
String::new()
96+
};
97+
let addition = format!("\n{}", shell_export_string()?);
98+
if !file.contains(&addition) {
99+
utils::append_file("rcfile", rcpath, &addition).chain_err(|| {
100+
ErrorKind::WritingShellProfile {
101+
path: rcpath.to_path_buf(),
102+
}
103+
})?;
104+
}
105+
} else {
106+
unreachable!()
107+
}
108+
}
109+
110+
Ok(())
111+
}
112+
113+
/// Tell the upgrader to replace the rustup bins, then delete
114+
/// itself. Like with uninstallation, on Windows we're going to
115+
/// have to jump through hoops to make everything work right.
116+
///
117+
/// On windows we're not going to wait for it to finish before exiting
118+
/// successfully, so it should not do much, and it should try
119+
/// really hard to succeed, because at this point the upgrade is
120+
/// considered successful.
121+
pub fn run_update(setup_path: &Path) -> Result<()> {
122+
let status = Command::new(setup_path)
123+
.arg("--self-replace")
124+
.status()
125+
.chain_err(|| "unable to run updater")?;
126+
127+
if !status.success() {
128+
return Err("self-updated failed to replace rustup executable".into());
129+
}
130+
131+
process::exit(0);
132+
}
133+
134+
/// This function is as the final step of a self-upgrade. It replaces
135+
/// `CARGO_HOME`/bin/rustup with the running exe, and updates the the
136+
/// links to it. On windows this will run *after* the original
137+
/// rustup process exits.
138+
pub fn self_replace() -> Result<()> {
139+
install_bins()?;
140+
141+
Ok(())
142+
}

0 commit comments

Comments
 (0)