From f2b139f23d574ca1d2c764b581a3b993e9af1570 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 2 Aug 2023 21:20:51 +0200 Subject: [PATCH 1/6] Command: also print removed env vars --- library/std/src/process/tests.rs | 23 ++++++++++++++++++- .../src/sys/unix/process/process_common.rs | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 366b591466c07..2c331eb0104e4 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -452,7 +452,7 @@ fn env_empty() { #[test] #[cfg(not(windows))] #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] -fn main() { +fn debug_print() { const PIDFD: &'static str = if cfg!(target_os = "linux") { " create_pidfd: false,\n" } else { "" }; @@ -538,6 +538,27 @@ fn main() { cwd: Some( "/some/path", ), +{PIDFD}}}"# + ) + ); + + let mut command_with_removed_env = Command::new("boring-name"); + command_with_removed_env.env_remove("BAR"); + assert_eq!(format!("{command_with_removed_env:?}"), r#"unset(BAR) "boring-name""#); + assert_eq!( + format!("{command_with_removed_env:#?}"), + format!( + r#"Command {{ + program: "boring-name", + args: [ + "boring-name", + ], + env: CommandEnv {{ + clear: false, + vars: {{ + "BAR": None, + }}, + }}, {PIDFD}}}"# ) ); diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 640648e870748..9362fc7f2058d 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -561,6 +561,8 @@ impl fmt::Debug for Command { for (key, value_opt) in self.get_envs() { if let Some(value) = value_opt { write!(f, "{}={value:?} ", key.to_string_lossy())?; + } else { + write!(f, "unset({}) ", key.to_string_lossy())?; } } if self.program != self.args[0] { From 396cbe66397ba77184e4ed896f4ba17f623c00f7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Aug 2023 09:22:54 +0200 Subject: [PATCH 2/6] make unsetting env vars print as executable command --- library/std/src/process/tests.rs | 5 +++-- .../std/src/sys/unix/process/process_common.rs | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 2c331eb0104e4..0d5321c2eead8 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -543,8 +543,8 @@ fn debug_print() { ); let mut command_with_removed_env = Command::new("boring-name"); - command_with_removed_env.env_remove("BAR"); - assert_eq!(format!("{command_with_removed_env:?}"), r#"unset(BAR) "boring-name""#); + command_with_removed_env.env_remove("FOO").env_remove("BAR"); + assert_eq!(format!("{command_with_removed_env:?}"), r#"unset BAR FOO && "boring-name""#); assert_eq!( format!("{command_with_removed_env:#?}"), format!( @@ -557,6 +557,7 @@ fn debug_print() { clear: false, vars: {{ "BAR": None, + "FOO": None, }}, }}, {PIDFD}}}"# diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 9362fc7f2058d..3a02a6c20d9cb 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -558,11 +558,25 @@ impl fmt::Debug for Command { if let Some(ref cwd) = self.cwd { write!(f, "cd {cwd:?} && ")?; } + // Removed env vars need a separate command. + // We use a single `unset` command for all of them. + let mut any_removed = false; + for (key, value_opt) in self.get_envs() { + if value_opt.is_none() { + if !any_removed { + write!(f, "unset ")?; + any_removed = true; + } + write!(f, "{} ", key.to_string_lossy())?; + } + } + if any_removed { + write!(f, "&& ")?; + } + // Altered env vars can just be added in front of the program. for (key, value_opt) in self.get_envs() { if let Some(value) = value_opt { write!(f, "{}={value:?} ", key.to_string_lossy())?; - } else { - write!(f, "unset({}) ", key.to_string_lossy())?; } } if self.program != self.args[0] { From 3a28887623fe7c61f7f84759f5d53fbf11f6a55e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Aug 2023 12:00:09 +0200 Subject: [PATCH 3/6] fix a typo in env_clear docs --- library/std/src/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index f54d593417502..eb88dfae93ced 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -789,7 +789,7 @@ impl Command { /// or [`Command::envs`]. In addition, it will prevent the spawned child process from inheriting /// any environment variable from its parent process. /// - /// After calling [`Command::env_remove`], the iterator from [`Command::get_envs`] will be + /// After calling [`Command::env_clear`], the iterator from [`Command::get_envs`] will be /// empty. /// /// You can use [`Command::env_remove`] to clear a single mapping. From 53a29e0e60b14486fbe06d0d68f311989d693816 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Aug 2023 12:07:42 +0200 Subject: [PATCH 4/6] also print clearing the environment entirely --- library/std/src/process/tests.rs | 23 +++++++++++++++ .../src/sys/unix/process/process_common.rs | 29 +++++++++++-------- library/std/src/sys_common/process.rs | 4 +++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 0d5321c2eead8..b50dea2e737ba 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -560,6 +560,29 @@ fn debug_print() { "FOO": None, }}, }}, +{PIDFD}}}"# + ) + ); + + let mut command_with_cleared_env = Command::new("boring-name"); + command_with_cleared_env.env_clear().env("BAR", "val").env_remove("FOO"); + assert_eq!(format!("{command_with_cleared_env:?}"), r#"env -i BAR="val" "boring-name""#); + assert_eq!( + format!("{command_with_cleared_env:#?}"), + format!( + r#"Command {{ + program: "boring-name", + args: [ + "boring-name", + ], + env: CommandEnv {{ + clear: true, + vars: {{ + "BAR": Some( + "val", + ), + }}, + }}, {PIDFD}}}"# ) ); diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 3a02a6c20d9cb..23d9f3b78ee5e 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -558,20 +558,25 @@ impl fmt::Debug for Command { if let Some(ref cwd) = self.cwd { write!(f, "cd {cwd:?} && ")?; } - // Removed env vars need a separate command. - // We use a single `unset` command for all of them. - let mut any_removed = false; - for (key, value_opt) in self.get_envs() { - if value_opt.is_none() { - if !any_removed { - write!(f, "unset ")?; - any_removed = true; + if self.env.does_clear() { + write!(f, "env -i ")?; + // Altered env vars will be printed next, that should exactly work as expected. + } else { + // Removed env vars need a separate command. + // We use a single `unset` command for all of them. + let mut any_removed = false; + for (key, value_opt) in self.get_envs() { + if value_opt.is_none() { + if !any_removed { + write!(f, "unset ")?; + any_removed = true; + } + write!(f, "{} ", key.to_string_lossy())?; } - write!(f, "{} ", key.to_string_lossy())?; } - } - if any_removed { - write!(f, "&& ")?; + if any_removed { + write!(f, "&& ")?; + } } // Altered env vars can just be added in front of the program. for (key, value_opt) in self.get_envs() { diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 18883048daef1..4d295cf0f09d5 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -80,6 +80,10 @@ impl CommandEnv { self.vars.clear(); } + pub fn does_clear(&self) -> bool { + self.clear + } + pub fn have_changed_path(&self) -> bool { self.saw_path || self.clear } From fc75f723f681dc2cb1b0be7395c936adfb2f6f63 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 3 Aug 2023 12:14:58 +0200 Subject: [PATCH 5/6] also use 'env' for printing unsetting --- library/std/src/process/tests.rs | 2 +- library/std/src/sys/unix/process/process_common.rs | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index b50dea2e737ba..72894142d175e 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -544,7 +544,7 @@ fn debug_print() { let mut command_with_removed_env = Command::new("boring-name"); command_with_removed_env.env_remove("FOO").env_remove("BAR"); - assert_eq!(format!("{command_with_removed_env:?}"), r#"unset BAR FOO && "boring-name""#); + assert_eq!(format!("{command_with_removed_env:?}"), r#"env -u BAR -u FOO "boring-name""#); assert_eq!( format!("{command_with_removed_env:#?}"), format!( diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 23d9f3b78ee5e..957947a674aff 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -562,21 +562,17 @@ impl fmt::Debug for Command { write!(f, "env -i ")?; // Altered env vars will be printed next, that should exactly work as expected. } else { - // Removed env vars need a separate command. - // We use a single `unset` command for all of them. + // Removed env vars need the command to be wrappen in `env`. let mut any_removed = false; for (key, value_opt) in self.get_envs() { if value_opt.is_none() { if !any_removed { - write!(f, "unset ")?; + write!(f, "env ")?; any_removed = true; } - write!(f, "{} ", key.to_string_lossy())?; + write!(f, "-u {} ", key.to_string_lossy())?; } } - if any_removed { - write!(f, "&& ")?; - } } // Altered env vars can just be added in front of the program. for (key, value_opt) in self.get_envs() { From 98c94ec72f5c9319b9192d688c5abd851dcd2d15 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Sep 2023 17:58:21 +0200 Subject: [PATCH 6/6] fix typo Co-authored-by: Marcin S. --- library/std/src/sys/unix/process/process_common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 957947a674aff..644d32b6459a0 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -562,7 +562,7 @@ impl fmt::Debug for Command { write!(f, "env -i ")?; // Altered env vars will be printed next, that should exactly work as expected. } else { - // Removed env vars need the command to be wrappen in `env`. + // Removed env vars need the command to be wrapped in `env`. let mut any_removed = false; for (key, value_opt) in self.get_envs() { if value_opt.is_none() {