From 9160c4facffafd26bee4e94fe726316d07c1e4e5 Mon Sep 17 00:00:00 2001 From: jdx <216188+jdx@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:45:53 -0600 Subject: [PATCH] hook-env: keep prepended PATH entries in front (#1150) With this change, if you manually run PATH="/foo:$PATH" in your shell after activating rtx, rtx will keep "/foo" in front of its own PATH entries. Fixes #863 --- e2e/cd/test_bash | 7 ++++++- src/cli/hook_env.rs | 16 +++++++++++++--- src/env.rs | 1 + src/shell/bash.rs | 1 + src/shell/fish.rs | 1 + .../rtx__shell__bash__tests__hook_init.snap | 1 + .../rtx__shell__bash__tests__hook_init_nix.snap | 1 + .../rtx__shell__fish__tests__hook_init.snap | 1 + .../rtx__shell__fish__tests__hook_init_nix.snap | 1 + .../rtx__shell__zsh__tests__hook_init.snap | 1 + .../rtx__shell__zsh__tests__hook_init_nix.snap | 1 + src/shell/zsh.rs | 1 + 12 files changed, 29 insertions(+), 4 deletions(-) diff --git a/e2e/cd/test_bash b/e2e/cd/test_bash index afc70ca4d..60b827f76 100755 --- a/e2e/cd/test_bash +++ b/e2e/cd/test_bash @@ -43,8 +43,13 @@ cd .. && _rtx_hook test "$(node -v)" = "v20.0.0" assert_path "/root:ROOT/e2e/cwd:INSTALLS/node/20.0.0/bin:INSTALLS/python/3.12.0/bin:INSTALLS/tiny/3.1.0/bin:INSTALLS/poetry/1.7.1/bin:INSTALLS/shellcheck/0.9.0/bin:INSTALLS/shfmt/3.6.0/bin" +export PATH="PRE:$PATH" +cd 18 && _rtx_hook +test "$(node -v)" = "v18.0.0" +assert_path "PRE:/root:ROOT/e2e/cwd:INSTALLS/node/18.0.0/bin:INSTALLS/python/3.12.0/bin:INSTALLS/tiny/3.1.0/bin:INSTALLS/poetry/1.7.1/bin:INSTALLS/shellcheck/0.9.0/bin:INSTALLS/shfmt/3.6.0/bin" + rtx shell node@18.0.0 && _rtx_hook test "$(node -v)" = "v18.0.0" rtx deactivate -assert_path "" +assert_path "PRE" diff --git a/src/cli/hook_env.rs b/src/cli/hook_env.rs index 817c8689e..defd7bc36 100644 --- a/src/cli/hook_env.rs +++ b/src/cli/hook_env.rs @@ -90,9 +90,19 @@ impl HookEnv { installs: &Vec, to_remove: &Vec, ) -> Result> { - let new_path = join_paths([installs.clone(), env::PATH.clone()].concat())? - .to_string_lossy() - .to_string(); + let full = join_paths(&*env::PATH)?.to_string_lossy().to_string(); + let (pre, post) = match &*env::__RTX_ORIG_PATH { + Some(orig_path) => match full.split_once(&format!(":{orig_path}")) { + Some((pre, post)) => (pre.to_string(), (orig_path.to_string() + post)), + None => (String::new(), full), + }, + None => (String::new(), full), + }; + let install_path = join_paths(installs)?.to_string_lossy().to_string(); + let new_path = vec![pre, install_path, post] + .into_iter() + .filter(|p| !p.is_empty()) + .join(":"); let mut ops = vec![EnvDiffOperation::Add("PATH".into(), new_path)]; if let Some(input) = env::DIRENV_DIFF.deref() { diff --git a/src/env.rs b/src/env.rs index da2eb2c3e..fa8e3c8f1 100644 --- a/src/env.rs +++ b/src/env.rs @@ -67,6 +67,7 @@ pub static RTX_FETCH_REMOTE_VERSIONS_CACHE: Lazy> = Lazy::new(| /// used to prevent infinite loops pub static __RTX_SCRIPT: Lazy = Lazy::new(|| var_is_true("__RTX_SCRIPT")); pub static __RTX_DIFF: Lazy = Lazy::new(get_env_diff); +pub static __RTX_ORIG_PATH: Lazy> = Lazy::new(|| var("__RTX_ORIG_PATH").ok()); pub static CI: Lazy = Lazy::new(|| var_is_true("CI")); pub static PREFER_STALE: Lazy = Lazy::new(|| prefer_stale(&ARGS)); /// essentially, this is whether we show spinners or build output on runtime install diff --git a/src/shell/bash.rs b/src/shell/bash.rs index 674ea8385..6b116be8d 100644 --- a/src/shell/bash.rs +++ b/src/shell/bash.rs @@ -15,6 +15,7 @@ impl Shell for Bash { } out.push_str(&formatdoc! {r#" export RTX_SHELL=bash + export __RTX_ORIG_PATH="$PATH" rtx() {{ local command diff --git a/src/shell/fish.rs b/src/shell/fish.rs index 9c69acbd0..a1e616acc 100644 --- a/src/shell/fish.rs +++ b/src/shell/fish.rs @@ -20,6 +20,7 @@ impl Shell for Fish { // https://github.com/direnv/direnv/blob/cb5222442cb9804b1574954999f6073cc636eff0/internal/cmd/shell_fish.go#L14-L36 out.push_str(&formatdoc! {r#" set -gx RTX_SHELL fish + set -gx __RTX_ORIG_PATH $PATH function rtx if test (count $argv) -eq 0 diff --git a/src/shell/snapshots/rtx__shell__bash__tests__hook_init.snap b/src/shell/snapshots/rtx__shell__bash__tests__hook_init.snap index cdd27d924..fab0399f5 100644 --- a/src/shell/snapshots/rtx__shell__bash__tests__hook_init.snap +++ b/src/shell/snapshots/rtx__shell__bash__tests__hook_init.snap @@ -4,6 +4,7 @@ expression: "bash.activate(exe, true)" --- export PATH="/some/dir:$PATH" export RTX_SHELL=bash +export __RTX_ORIG_PATH="$PATH" rtx() { local command diff --git a/src/shell/snapshots/rtx__shell__bash__tests__hook_init_nix.snap b/src/shell/snapshots/rtx__shell__bash__tests__hook_init_nix.snap index 9e555f3cd..81c47d461 100644 --- a/src/shell/snapshots/rtx__shell__bash__tests__hook_init_nix.snap +++ b/src/shell/snapshots/rtx__shell__bash__tests__hook_init_nix.snap @@ -3,6 +3,7 @@ source: src/shell/bash.rs expression: "bash.activate(exe, true)" --- export RTX_SHELL=bash +export __RTX_ORIG_PATH="$PATH" rtx() { local command diff --git a/src/shell/snapshots/rtx__shell__fish__tests__hook_init.snap b/src/shell/snapshots/rtx__shell__fish__tests__hook_init.snap index a9dfcd5be..85c54a5a9 100644 --- a/src/shell/snapshots/rtx__shell__fish__tests__hook_init.snap +++ b/src/shell/snapshots/rtx__shell__fish__tests__hook_init.snap @@ -4,6 +4,7 @@ expression: "fish.activate(exe, true)" --- fish_add_path -g /some/dir set -gx RTX_SHELL fish +set -gx __RTX_ORIG_PATH $PATH function rtx if test (count $argv) -eq 0 diff --git a/src/shell/snapshots/rtx__shell__fish__tests__hook_init_nix.snap b/src/shell/snapshots/rtx__shell__fish__tests__hook_init_nix.snap index 4a02b4967..662c282c3 100644 --- a/src/shell/snapshots/rtx__shell__fish__tests__hook_init_nix.snap +++ b/src/shell/snapshots/rtx__shell__fish__tests__hook_init_nix.snap @@ -3,6 +3,7 @@ source: src/shell/fish.rs expression: "fish.activate(exe, true)" --- set -gx RTX_SHELL fish +set -gx __RTX_ORIG_PATH $PATH function rtx if test (count $argv) -eq 0 diff --git a/src/shell/snapshots/rtx__shell__zsh__tests__hook_init.snap b/src/shell/snapshots/rtx__shell__zsh__tests__hook_init.snap index c6ebdde60..b01fd8338 100644 --- a/src/shell/snapshots/rtx__shell__zsh__tests__hook_init.snap +++ b/src/shell/snapshots/rtx__shell__zsh__tests__hook_init.snap @@ -4,6 +4,7 @@ expression: "zsh.activate(exe, true)" --- export PATH="/some/dir:$PATH" export RTX_SHELL=zsh +export __RTX_ORIG_PATH="$PATH" rtx() { local command diff --git a/src/shell/snapshots/rtx__shell__zsh__tests__hook_init_nix.snap b/src/shell/snapshots/rtx__shell__zsh__tests__hook_init_nix.snap index f1218f4b4..21055d9dc 100644 --- a/src/shell/snapshots/rtx__shell__zsh__tests__hook_init_nix.snap +++ b/src/shell/snapshots/rtx__shell__zsh__tests__hook_init_nix.snap @@ -3,6 +3,7 @@ source: src/shell/zsh.rs expression: "zsh.activate(exe, true)" --- export RTX_SHELL=zsh +export __RTX_ORIG_PATH="$PATH" rtx() { local command diff --git a/src/shell/zsh.rs b/src/shell/zsh.rs index cd0b50ed2..4dbff4ff4 100644 --- a/src/shell/zsh.rs +++ b/src/shell/zsh.rs @@ -19,6 +19,7 @@ impl Shell for Zsh { } out.push_str(&formatdoc! {r#" export RTX_SHELL=zsh + export __RTX_ORIG_PATH="$PATH" rtx() {{ local command