Fix Windows Command::env("PATH")

This commit is contained in:
Chris Denton 2021-08-08 14:23:08 +01:00
parent e8c25f2663
commit 419902e413
No known key found for this signature in database
GPG Key ID: 713472F2F45627DE
2 changed files with 30 additions and 9 deletions

View File

@ -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<u16>,
}
impl EnvKey {
fn new<T: Into<OsString>>(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 @@ impl PartialEq for EnvKey {
}
}
}
impl PartialOrd<str> for EnvKey {
fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
Some(self.cmp(&EnvKey::new(other)))
}
}
impl PartialEq<str> 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 @@ impl From<EnvKey> for OsString {
}
}
impl Borrow<OsStr> 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 @@ impl Command {
// 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) {

View File

@ -65,16 +65,18 @@ impl CommandEnv {
// 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 @@ impl CommandEnv {
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;
}