diff --git a/Cargo.lock b/Cargo.lock index 31278083b..eb153446b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -92,7 +92,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -110,7 +110,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -376,7 +376,7 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -418,7 +418,7 @@ dependencies = [ "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -616,7 +616,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -767,7 +767,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1250,7 +1250,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1310,7 +1310,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1319,7 +1319,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1447,7 +1447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1587,7 +1587,7 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1739,7 +1739,7 @@ dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1757,7 +1757,7 @@ dependencies = [ "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1805,7 +1805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1818,7 +1818,7 @@ dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1927,7 +1927,7 @@ name = "remove_dir_all" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2019,7 +2019,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2172,7 +2172,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2521,6 +2521,8 @@ dependencies = [ "tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2950,7 +2952,7 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3002,7 +3004,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3330,7 +3332,7 @@ version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3360,7 +3362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3382,7 +3384,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3395,10 +3397,18 @@ name = "wincolor" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winreg" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws" version = "0.8.1" @@ -3746,12 +3756,13 @@ dependencies = [ "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum winreg 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "daf67b95d0b1bf421c4f11048d63110ca3719977169eec86396b614c8942b6e0" "checksum ws 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec91ea61b83ce033c43c06c52ddc7532f465c0153281610d44c58b74083aee1a" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" diff --git a/install/Cargo.toml b/install/Cargo.toml index 899aa896a..500cf3bea 100644 --- a/install/Cargo.toml +++ b/install/Cargo.toml @@ -36,6 +36,10 @@ tar = "0.4.26" tempdir = "0.3.7" url = "1.7.2" +[target."cfg(windows)".dependencies] +winapi = "0.3.7" +winreg = "0.6" + [[bin]] name = "solana-install" path = "src/main-install.rs" diff --git a/install/src/command.rs b/install/src/command.rs index 2a4bc31bf..0babe37d8 100644 --- a/install/src/command.rs +++ b/install/src/command.rs @@ -276,6 +276,217 @@ fn check_env_path_for_bin_dir(config: &Config) { } } +/// Encodes a UTF-8 string as a null-terminated UCS-2 string in bytes +#[cfg(windows)] +pub fn string_to_winreg_bytes(s: &str) -> Vec { + use std::ffi::OsString; + use std::os::windows::ffi::OsStrExt; + let v: Vec<_> = OsString::from(format!("{}\x00", s)).encode_wide().collect(); + unsafe { std::slice::from_raw_parts(v.as_ptr() as *const u8, v.len() * 2).to_vec() } +} + +// This is used to decode the value of HKCU\Environment\PATH. If that +// key is not Unicode (or not REG_SZ | REG_EXPAND_SZ) then this +// returns null. The winreg library itself does a lossy unicode +// conversion. +#[cfg(windows)] +pub fn string_from_winreg_value(val: &winreg::RegValue) -> Option { + use std::slice; + use winreg::enums::RegType; + + match val.vtype { + RegType::REG_SZ | RegType::REG_EXPAND_SZ => { + // Copied from winreg + let words = unsafe { + slice::from_raw_parts(val.bytes.as_ptr() as *const u16, val.bytes.len() / 2) + }; + let mut s = if let Ok(s) = String::from_utf16(words) { + s + } else { + return None; + }; + while s.ends_with('\u{0}') { + s.pop(); + } + Some(s) + } + _ => None, + } +} +// Get the windows PATH variable out of the registry as a String. If +// this returns None then the PATH variable is not Unicode and we +// should not mess with it. +#[cfg(windows)] +fn get_windows_path_var() -> Result, String> { + use winreg::enums::{HKEY_CURRENT_USER, KEY_READ, KEY_WRITE}; + use winreg::RegKey; + + let root = RegKey::predef(HKEY_CURRENT_USER); + let environment = root + .open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE) + .map_err(|err| format!("Unable to open HKEY_CURRENT_USER\\Environment: {}", err))?; + + let reg_value = environment.get_raw_value("PATH"); + match reg_value { + Ok(val) => { + if let Some(s) = string_from_winreg_value(&val) { + Ok(Some(s)) + } else { + println!("the registry key HKEY_CURRENT_USER\\Environment\\PATH does not contain valid Unicode. Not modifying the PATH variable"); + return Ok(None); + } + } + Err(ref e) if e.kind() == io::ErrorKind::NotFound => Ok(Some(String::new())), + Err(e) => Err(e.to_string()), + } +} + +#[cfg(windows)] +fn add_to_path(new_path: &str) -> Result { + use std::ptr; + use winapi::shared::minwindef::*; + use winapi::um::winuser::{ + SendMessageTimeoutA, HWND_BROADCAST, SMTO_ABORTIFHUNG, WM_SETTINGCHANGE, + }; + use winreg::enums::{RegType, HKEY_CURRENT_USER, KEY_READ, KEY_WRITE}; + use winreg::{RegKey, RegValue}; + + let old_path = if let Some(s) = get_windows_path_var()? { + s + } else { + return Ok(false); + }; + + if !old_path.contains(&new_path) { + let mut new_path = new_path.to_string(); + if !old_path.is_empty() { + new_path.push_str(";"); + new_path.push_str(&old_path); + } + + let root = RegKey::predef(HKEY_CURRENT_USER); + let environment = root + .open_subkey_with_flags("Environment", KEY_READ | KEY_WRITE) + .map_err(|err| format!("Unable to open HKEY_CURRENT_USER\\Environment: {}", err))?; + + let reg_value = RegValue { + bytes: string_to_winreg_bytes(&new_path), + vtype: RegType::REG_EXPAND_SZ, + }; + + environment + .set_raw_value("PATH", ®_value) + .map_err(|err| format!("Unable set HKEY_CURRENT_USER\\Environment\\PATH: {}", err))?; + + // Tell other processes to update their environment + unsafe { + SendMessageTimeoutA( + HWND_BROADCAST, + WM_SETTINGCHANGE, + 0 as WPARAM, + "Environment\0".as_ptr() as LPARAM, + SMTO_ABORTIFHUNG, + 5000, + ptr::null_mut(), + ); + } + } + + println!( + "\n{}\n {}\n\n{}", + style("The HKEY_CURRENT_USER/Environment/PATH registry key has been modified to include:").bold(), + new_path, + style("Future applications will automatically have the correct environment, but you may need to restart your current shell.").bold() + ); + Ok(true) +} + +#[cfg(unix)] +fn add_to_path(new_path: &str) -> Result { + let shell_export_string = format!(r#"export PATH="{}:$PATH""#, new_path); + let mut modified_rcfiles = false; + + // Look for sh, bash, and zsh rc files + let mut rcfiles = vec![dirs::home_dir().map(|p| p.join(".profile"))]; + if let Ok(shell) = std::env::var("SHELL") { + if shell.contains("zsh") { + let zdotdir = std::env::var("ZDOTDIR") + .ok() + .map(PathBuf::from) + .or_else(dirs::home_dir); + let zprofile = zdotdir.map(|p| p.join(".zprofile")); + rcfiles.push(zprofile); + } + } + + if let Some(bash_profile) = dirs::home_dir().map(|p| p.join(".bash_profile")) { + // Only update .bash_profile if it exists because creating .bash_profile + // will cause .profile to not be read + if bash_profile.exists() { + rcfiles.push(Some(bash_profile)); + } + } + let rcfiles = rcfiles.into_iter().filter_map(|f| f.filter(|f| f.exists())); + + // For each rc file, append a PATH entry if not already present + for rcfile in rcfiles { + if !rcfile.exists() { + continue; + } + + fn read_file(path: &Path) -> io::Result { + let mut file = fs::OpenOptions::new().read(true).open(path)?; + let mut contents = String::new(); + io::Read::read_to_string(&mut file, &mut contents)?; + Ok(contents) + } + + match read_file(&rcfile) { + Err(err) => { + println!("Unable to read {:?}: {}", rcfile, err); + } + Ok(contents) => { + if !contents.contains(&shell_export_string) { + println!( + "Adding {} to {}", + style(&shell_export_string).italic(), + style(rcfile.to_str().unwrap()).bold() + ); + + fn append_file(dest: &Path, line: &str) -> io::Result<()> { + use std::io::Write; + let mut dest_file = fs::OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open(dest)?; + + writeln!(&mut dest_file, "{}", line)?; + + dest_file.sync_data()?; + + Ok(()) + } + append_file(&rcfile, &shell_export_string).unwrap_or_else(|err| { + format!("Unable to append to {:?}: {}", rcfile, err); + }); + modified_rcfiles = true; + } + } + } + } + + if modified_rcfiles { + println!( + "\n{}\n {}\n", + style("Close and reopen your terminal to apply the PATH changes or run the following in your existing shell:").bold().blue(), + shell_export_string + ); + } + + Ok(modified_rcfiles) +} + pub fn init( config_file: &str, data_dir: &str, @@ -294,96 +505,18 @@ pub fn init( } config }; + update(config_file)?; - let mut modified_rcfiles = false; - let shell_export_string = format!( - r#"export PATH="{}:$PATH""#, - config.active_release_bin_dir().to_str().unwrap() - ); - - if !no_modify_path { - // Look for sh, bash, and zsh rc files - let mut rcfiles = vec![dirs::home_dir().map(|p| p.join(".profile"))]; - if let Ok(shell) = std::env::var("SHELL") { - if shell.contains("zsh") { - let zdotdir = std::env::var("ZDOTDIR") - .ok() - .map(PathBuf::from) - .or_else(dirs::home_dir); - let zprofile = zdotdir.map(|p| p.join(".zprofile")); - rcfiles.push(zprofile); - } - } - - if let Some(bash_profile) = dirs::home_dir().map(|p| p.join(".bash_profile")) { - // Only update .bash_profile if it exists because creating .bash_profile - // will cause .profile to not be read - if bash_profile.exists() { - rcfiles.push(Some(bash_profile)); - } - } - let rcfiles = rcfiles.into_iter().filter_map(|f| f.filter(|f| f.exists())); - - // For each rc file, append a PATH entry if not already present - for rcfile in rcfiles { - if !rcfile.exists() { - continue; - } - - fn read_file(path: &Path) -> io::Result { - let mut file = fs::OpenOptions::new().read(true).open(path)?; - let mut contents = String::new(); - io::Read::read_to_string(&mut file, &mut contents)?; - Ok(contents) - } - - match read_file(&rcfile) { - Err(err) => { - println!("Unable to read {:?}: {}", rcfile, err); - } - Ok(contents) => { - if !contents.contains(&shell_export_string) { - println!( - "Adding {} to {}", - style(&shell_export_string).italic(), - style(rcfile.to_str().unwrap()).bold() - ); - - fn append_file(dest: &Path, line: &str) -> io::Result<()> { - use std::io::Write; - let mut dest_file = fs::OpenOptions::new() - .write(true) - .append(true) - .create(true) - .open(dest)?; - - writeln!(&mut dest_file, "{}", line)?; - - dest_file.sync_data()?; - - Ok(()) - } - append_file(&rcfile, &shell_export_string).unwrap_or_else(|err| { - format!("Unable to append to {:?}: {}", rcfile, err); - }); - modified_rcfiles = true; - } - } - } - } - } - - if modified_rcfiles { - println!( - "\n{}\n {}\n", - style("Close and reopen your terminal to apply the PATH changes or run the following in your existing shell:").bold().blue(), - shell_export_string - ); + let path_modified = if !no_modify_path { + add_to_path(&config.active_release_bin_dir().to_str().unwrap())? } else { + false + }; + + if !path_modified { check_env_path_for_bin_dir(&config); } - Ok(()) } @@ -394,6 +527,11 @@ pub fn info(config_file: &str, local_info_only: bool) -> Result