project: Normalize `Path` env var to `PATH` in shell env on windows (#40720)

Lukas Wirth created

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/languages/src/python.rs    | 10 +++++++---
crates/project/src/environment.rs |  7 ++++++-
crates/project/src/lsp_store.rs   |  7 +------
3 files changed, 14 insertions(+), 10 deletions(-)

Detailed changes

crates/languages/src/python.rs 🔗

@@ -1344,9 +1344,13 @@ impl pet_core::os_environment::Environment for EnvironmentApi<'_> {
 
     fn get_know_global_search_locations(&self) -> Vec<PathBuf> {
         if self.global_search_locations.lock().is_empty() {
-            let mut paths =
-                std::env::split_paths(&self.get_env_var("PATH".to_string()).unwrap_or_default())
-                    .collect::<Vec<PathBuf>>();
+            let mut paths = std::env::split_paths(
+                &self
+                    .get_env_var("PATH".to_string())
+                    .or_else(|| self.get_env_var("Path".to_string()))
+                    .unwrap_or_default(),
+            )
+            .collect::<Vec<PathBuf>>();
 
             log::trace!("Env PATH: {:?}", paths);
             for p in self.pet_env.get_know_global_search_locations() {

crates/project/src/environment.rs 🔗

@@ -265,7 +265,7 @@ async fn load_shell_environment(
         (Some(fake_env), None)
     } else if cfg!(target_os = "windows") {
         let (shell, args) = shell.program_and_args();
-        let envs = match shell_env::capture(shell, args, dir).await {
+        let mut envs = match shell_env::capture(shell, args, dir).await {
             Ok(envs) => envs,
             Err(err) => {
                 util::log_err(&err);
@@ -278,6 +278,11 @@ async fn load_shell_environment(
                 );
             }
         };
+        if let Some(path) = envs.remove("Path") {
+            // windows env vars are case-insensitive, so normalize the path var
+            // so we can just assume `PATH` in other places
+            envs.insert("PATH".into(), path);
+        }
 
         // Note: direnv is not available on Windows, so we skip direnv processing
         // and just return the shell environment

crates/project/src/lsp_store.rs 🔗

@@ -13271,12 +13271,7 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
 
         let env = self.shell_env().await;
 
-        // On Windows, PATH might be "Path" instead of "PATH"
-        let shell_path = env
-            .get("PATH")
-            .or_else(|| env.get("Path"))
-            .or_else(|| env.get("path"))
-            .cloned();
+        let shell_path = env.get("PATH").cloned();
 
         which::which_in(command, shell_path.as_ref(), worktree_abs_path).ok()
     }