Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 15 additions & 30 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,36 +445,20 @@ but will not be added automatically."
};
}

#[cfg(not(windows))]
macro_rules! post_install_msg_unix_source_env {
() => {
r#"To configure your current shell, you need to source
the corresponding `env` file under {cargo_home}.

This is usually done by running one of the following (note the leading DOT):
. "{cargo_home}/env" # For sh/bash/zsh/ash/dash/pdksh
source "{cargo_home}/env.fish" # For fish
source "{cargo_home_nushell}/env.nu" # For nushell
source "{cargo_home}/env.tcsh" # For tcsh
. "{cargo_home}/env.ps1" # For pwsh
source "{cargo_home}/env.xsh" # For xonsh
"#
};
}

#[cfg(not(windows))]
macro_rules! post_install_msg_unix {
() => {
concat!(
r"# Rust is installed now. Great!
r"# Rust is installed now. Great!

To get started you may need to restart your current shell.
This would reload your `PATH` environment variable to include
Cargo's bin directory ({cargo_home}/bin).

",
post_install_msg_unix_source_env!(),
)
To configure your current shell, you need to source
the corresponding `env` file under {cargo_home}.

This is usually done by running one of the following (note the leading DOT):
{source_env_lines}"
};
}

Expand All @@ -494,15 +478,16 @@ Cargo's bin directory ({cargo_home}\\bin).
#[cfg(not(windows))]
macro_rules! post_install_msg_unix_no_modify_path {
() => {
concat!(
r"# Rust is installed now. Great!
r"# Rust is installed now. Great!

To get started you need Cargo's bin directory ({cargo_home}/bin) in your `PATH`
environment variable. This has not been done automatically.

",
post_install_msg_unix_source_env!(),
)
To configure your current shell, you need to source
the corresponding `env` file under {cargo_home}.

This is usually done by running one of the following (note the leading DOT):
{source_env_lines}"
};
}

Expand Down Expand Up @@ -661,19 +646,19 @@ pub(crate) async fn install(
format!(post_install_msg_win!(), cargo_home = cargo_home)
};
#[cfg(not(windows))]
let cargo_home_nushell = Nu.cargo_home_str(cfg.process)?;
let source_env_lines = shell::build_source_env_lines(cfg.process);
#[cfg(not(windows))]
let msg = if no_modify_path {
format!(
post_install_msg_unix_no_modify_path!(),
cargo_home = cargo_home,
cargo_home_nushell = cargo_home_nushell,
source_env_lines = source_env_lines,
)
} else {
format!(
post_install_msg_unix!(),
cargo_home = cargo_home,
cargo_home_nushell = cargo_home_nushell,
source_env_lines = source_env_lines,
)
};
md(&mut term, msg);
Expand Down
56 changes: 56 additions & 0 deletions src/cli/self_update/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ pub(crate) trait UnixShell {
// heuristic should be used, assuming shells exist if any traces do.
fn does_exist(&self, process: &Process) -> bool;

// Returns the display name of the shell, used in post-install messages.
fn name(&self) -> &'static str;

// Gives all rcfiles of a given shell that Rustup is concerned with.
// Used primarily in checking rcfiles for cleanup.
fn rcfiles(&self, process: &Process) -> Vec<PathBuf>;
Expand Down Expand Up @@ -128,6 +131,10 @@ impl UnixShell for Posix {
true
}

fn name(&self) -> &'static str {
"sh/ash/dash/pdksh"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
match process.home_dir() {
Some(dir) => vec![dir.join(".profile")],
Expand All @@ -149,6 +156,10 @@ impl UnixShell for Bash {
!self.update_rcs(process).is_empty()
}

fn name(&self) -> &'static str {
"bash"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
// Bash also may read .profile, however Rustup already includes handling
// .profile as part of POSIX and always does setup for POSIX shells.
Expand Down Expand Up @@ -197,6 +208,10 @@ impl UnixShell for Zsh {
|| utils::find_cmd(&["zsh"], process).is_some()
}

fn name(&self) -> &'static str {
"zsh"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
[Zsh::zdotdir(process).ok(), process.home_dir()]
.iter()
Expand Down Expand Up @@ -229,6 +244,10 @@ impl UnixShell for Fish {
|| utils::find_cmd(&["fish"], process).is_some()
}

fn name(&self) -> &'static str {
"fish"
}

// > "$XDG_CONFIG_HOME/fish/conf.d" (or "~/.config/fish/conf.d" if that variable is unset) for the user
// from <https://github.com/fish-shell/fish-shell/issues/3170#issuecomment-228311857>
fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
Expand Down Expand Up @@ -278,6 +297,10 @@ impl UnixShell for Nu {
|| utils::find_cmd(&["nu"], process).is_some()
}

fn name(&self) -> &'static str {
"nushell"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
let mut paths = vec![];

Expand Down Expand Up @@ -329,6 +352,10 @@ impl UnixShell for Tcsh {
|| utils::find_cmd(&["tcsh"], process).is_some()
}

fn name(&self) -> &'static str {
"tcsh"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
let mut paths = vec![];

Expand Down Expand Up @@ -378,6 +405,10 @@ impl UnixShell for Pwsh {
|| utils::find_cmd(&["pwsh"], process).is_some()
}

fn name(&self) -> &'static str {
"pwsh"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
let mut paths = vec![];

Expand Down Expand Up @@ -453,6 +484,10 @@ impl UnixShell for Xonsh {
process.var("XONSHRC").is_ok() || utils::find_cmd(&["xonsh"], process).is_some()
}

fn name(&self) -> &'static str {
"xonsh"
}

fn rcfiles(&self, process: &Process) -> Vec<PathBuf> {
let mut paths = vec![];

Expand Down Expand Up @@ -501,6 +536,27 @@ impl UnixShell for Xonsh {
}
}

/// Builds the shell source lines for the post-install message, showing only
/// shells that are available on the current system. Shells sharing the same
/// env file are grouped onto one line (e.g. sh/bash/zsh all use `env`).
pub(crate) fn build_source_env_lines(process: &Process) -> String {
let mut groups: Vec<(String, Vec<&'static str>)> = Vec::new();
for shell in get_available_shells(process) {
let Ok(src) = shell.source_string(process) else {
continue;
};
if let Some(group) = groups.iter_mut().find(|(s, _)| *s == src) {
group.1.push(shell.name());
} else {
groups.push((src, vec![shell.name()]));
}
}
groups
.into_iter()
.map(|(src, names)| format!(" {} # For {}\n", src, names.join("/")))
.collect()
}

pub(crate) fn legacy_paths(process: &Process) -> impl Iterator<Item = PathBuf> + '_ {
let zprofiles = Zsh::zdotdir(process)
.into_iter()
Expand Down
Loading