From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- library/std/src/sys_common/process.rs | 119 ++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 library/std/src/sys_common/process.rs (limited to 'library/std/src/sys_common/process.rs') diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs new file mode 100644 index 000000000..9f978789a --- /dev/null +++ b/library/std/src/sys_common/process.rs @@ -0,0 +1,119 @@ +#![allow(dead_code)] +#![unstable(feature = "process_internals", issue = "none")] + +use crate::collections::BTreeMap; +use crate::env; +use crate::ffi::{OsStr, OsString}; +use crate::sys::process::EnvKey; + +// Stores a set of changes to an environment +#[derive(Clone, Debug)] +pub struct CommandEnv { + clear: bool, + saw_path: bool, + vars: BTreeMap>, +} + +impl Default for CommandEnv { + fn default() -> Self { + CommandEnv { clear: false, saw_path: false, vars: Default::default() } + } +} + +impl CommandEnv { + // Capture the current environment with these changes applied + pub fn capture(&self) -> BTreeMap { + let mut result = BTreeMap::::new(); + if !self.clear { + for (k, v) in env::vars_os() { + result.insert(k.into(), v); + } + } + for (k, maybe_v) in &self.vars { + if let &Some(ref v) = maybe_v { + result.insert(k.clone(), v.clone()); + } else { + result.remove(k); + } + } + result + } + + pub fn is_unchanged(&self) -> bool { + !self.clear && self.vars.is_empty() + } + + pub fn capture_if_changed(&self) -> Option> { + if self.is_unchanged() { None } else { Some(self.capture()) } + } + + // 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, 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); + } else { + self.vars.insert(key, None); + } + } + + pub fn clear(&mut self) { + self.clear = true; + self.vars.clear(); + } + + pub fn have_changed_path(&self) -> bool { + self.saw_path || self.clear + } + + fn maybe_saw_path(&mut self, key: &EnvKey) { + if !self.saw_path && key == "PATH" { + self.saw_path = true; + } + } + + pub fn iter(&self) -> CommandEnvs<'_> { + let iter = self.vars.iter(); + CommandEnvs { iter } + } +} + +/// An iterator over the command environment variables. +/// +/// This struct is created by +/// [`Command::get_envs`][crate::process::Command::get_envs]. See its +/// documentation for more. +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[stable(feature = "command_access", since = "1.57.0")] +#[derive(Debug)] +pub struct CommandEnvs<'a> { + iter: crate::collections::btree_map::Iter<'a, EnvKey, Option>, +} + +#[stable(feature = "command_access", since = "1.57.0")] +impl<'a> Iterator for CommandEnvs<'a> { + type Item = (&'a OsStr, Option<&'a OsStr>); + fn next(&mut self) -> Option { + self.iter.next().map(|(key, value)| (key.as_ref(), value.as_deref())) + } + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "command_access", since = "1.57.0")] +impl<'a> ExactSizeIterator for CommandEnvs<'a> { + fn len(&self) -> usize { + self.iter.len() + } + fn is_empty(&self) -> bool { + self.iter.is_empty() + } +} -- cgit v1.2.3