From 419902e413ddd62673f8e54c71e5164d862aee08 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 8 Aug 2021 14:23:08 +0100 Subject: [PATCH] Fix Windows Command::env("PATH") --- library/std/src/sys/windows/process.rs | 29 +++++++++++++++++++++----- library/std/src/sys_common/process.rs | 10 +++++---- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 0fdf72c8067..ae193b82e91 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -3,7 +3,6 @@ #[cfg(test)] mod tests; -use crate::borrow::Borrow; use crate::cmp; use crate::collections::BTreeMap; use crate::convert::{TryFrom, TryInto}; @@ -46,6 +45,12 @@ pub struct EnvKey { utf16: Vec, } +impl EnvKey { + fn new>(key: T) -> Self { + EnvKey::from(key.into()) + } +} + // Comparing Windows environment variable keys[1] are behaviourally the // composition of two operations[2]: // @@ -100,6 +105,20 @@ fn eq(&self, other: &Self) -> bool { } } } +impl PartialOrd for EnvKey { + fn partial_cmp(&self, other: &str) -> Option { + Some(self.cmp(&EnvKey::new(other))) + } +} +impl PartialEq for EnvKey { + fn eq(&self, other: &str) -> bool { + if self.os_string.len() != other.len() { + false + } else { + self.cmp(&EnvKey::new(other)) == cmp::Ordering::Equal + } + } +} // Environment variable keys should preserve their original case even though // they are compared using a caseless string mapping. @@ -115,9 +134,9 @@ fn from(k: EnvKey) -> Self { } } -impl Borrow for EnvKey { - fn borrow(&self) -> &OsStr { - &self.os_string +impl From<&OsStr> for EnvKey { + fn from(k: &OsStr) -> Self { + Self::from(k.to_os_string()) } } @@ -242,7 +261,7 @@ pub fn spawn( // to read the *child's* PATH if one is provided. See #15149 for more // details. let program = maybe_env.as_ref().and_then(|env| { - if let Some(v) = env.get(OsStr::new("PATH")) { + if let Some(v) = env.get(&EnvKey::new("PATH")) { // Split the value and test each path to see if the // program exists. for path in split_paths(&v) { diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index fe89b11043c..38007d5c414 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -65,16 +65,18 @@ pub fn capture_if_changed(&self) -> Option> { // The following functions build up changes pub fn set(&mut self, key: &OsStr, value: &OsStr) { + let key = EnvKey::from(key); self.maybe_saw_path(&key); - self.vars.insert(key.to_owned().into(), Some(value.to_owned())); + self.vars.insert(key, Some(value.to_owned())); } pub fn remove(&mut self, key: &OsStr) { + let key = EnvKey::from(key); self.maybe_saw_path(&key); if self.clear { - self.vars.remove(key); + self.vars.remove(&key); } else { - self.vars.insert(key.to_owned().into(), None); + self.vars.insert(key, None); } } @@ -87,7 +89,7 @@ pub fn have_changed_path(&self) -> bool { self.saw_path || self.clear } - fn maybe_saw_path(&mut self, key: &OsStr) { + fn maybe_saw_path(&mut self, key: &EnvKey) { if !self.saw_path && key == "PATH" { self.saw_path = true; }