about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-09-22 12:15:25 +0200
committerGitHub <noreply@github.com>2023-09-22 12:15:25 +0200
commit9887dfab2c7a204fafa2c1af6de5fd304f587322 (patch)
tree4a75f0f01fc5392575ceb5a7959de23e7c06fb2f
parent8759de0a4935e677fdce99a849addea2d5318da9 (diff)
parent98c94ec72f5c9319b9192d688c5abd851dcd2d15 (diff)
downloadrust-9887dfab2c7a204fafa2c1af6de5fd304f587322.tar.gz
rust-9887dfab2c7a204fafa2c1af6de5fd304f587322.zip
Rollup merge of #114379 - RalfJung:command-removed-env-vars, r=m-ou-se
Command: also print removed env vars

There is no real shell syntax for unsetting an env var so easily, so we have to make one up. But we already do that for showing the 'program' name so I hope that's okay here, too. No strong opinion on what that should look like, I went with `unset(VAR_NAME)` for now.
-rw-r--r--library/std/src/process.rs2
-rw-r--r--library/std/src/process/tests.rs47
-rw-r--r--library/std/src/sys/unix/process/process_common.rs17
-rw-r--r--library/std/src/sys_common/process.rs4
4 files changed, 68 insertions, 2 deletions
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 5df1105e264..948862c2a7d 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.
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 00636237288..07d4de5c1a2 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -537,7 +537,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 { "" };
 
@@ -626,6 +626,51 @@ fn main() {
 {PIDFD}}}"#
         )
     );
+
+    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#"env -u BAR -u FOO "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,
+            "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}}}"#
+        )
+    );
 }
 
 // See issue #91991
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index f729da44774..1ca11a7f9d7 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -586,6 +586,23 @@ impl fmt::Debug for Command {
             if let Some(ref cwd) = self.cwd {
                 write!(f, "cd {cwd:?} && ")?;
             }
+            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 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() {
+                        if !any_removed {
+                            write!(f, "env ")?;
+                            any_removed = true;
+                        }
+                        write!(f, "-u {} ", key.to_string_lossy())?;
+                    }
+                }
+            }
+            // 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())?;
diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs
index 18883048dae..4d295cf0f09 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
     }