Skip to content

Commit 9887dfa

Browse files
authored
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.
2 parents 8759de0 + 98c94ec commit 9887dfa

File tree

4 files changed

+68
-2
lines changed

4 files changed

+68
-2
lines changed

library/std/src/process.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ impl Command {
789789
/// or [`Command::envs`]. In addition, it will prevent the spawned child process from inheriting
790790
/// any environment variable from its parent process.
791791
///
792-
/// After calling [`Command::env_remove`], the iterator from [`Command::get_envs`] will be
792+
/// After calling [`Command::env_clear`], the iterator from [`Command::get_envs`] will be
793793
/// empty.
794794
///
795795
/// You can use [`Command::env_remove`] to clear a single mapping.

library/std/src/process/tests.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ fn env_empty() {
537537
#[test]
538538
#[cfg(not(windows))]
539539
#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
540-
fn main() {
540+
fn debug_print() {
541541
const PIDFD: &'static str =
542542
if cfg!(target_os = "linux") { " create_pidfd: false,\n" } else { "" };
543543

@@ -623,6 +623,51 @@ fn main() {
623623
cwd: Some(
624624
"/some/path",
625625
),
626+
{PIDFD}}}"#
627+
)
628+
);
629+
630+
let mut command_with_removed_env = Command::new("boring-name");
631+
command_with_removed_env.env_remove("FOO").env_remove("BAR");
632+
assert_eq!(format!("{command_with_removed_env:?}"), r#"env -u BAR -u FOO "boring-name""#);
633+
assert_eq!(
634+
format!("{command_with_removed_env:#?}"),
635+
format!(
636+
r#"Command {{
637+
program: "boring-name",
638+
args: [
639+
"boring-name",
640+
],
641+
env: CommandEnv {{
642+
clear: false,
643+
vars: {{
644+
"BAR": None,
645+
"FOO": None,
646+
}},
647+
}},
648+
{PIDFD}}}"#
649+
)
650+
);
651+
652+
let mut command_with_cleared_env = Command::new("boring-name");
653+
command_with_cleared_env.env_clear().env("BAR", "val").env_remove("FOO");
654+
assert_eq!(format!("{command_with_cleared_env:?}"), r#"env -i BAR="val" "boring-name""#);
655+
assert_eq!(
656+
format!("{command_with_cleared_env:#?}"),
657+
format!(
658+
r#"Command {{
659+
program: "boring-name",
660+
args: [
661+
"boring-name",
662+
],
663+
env: CommandEnv {{
664+
clear: true,
665+
vars: {{
666+
"BAR": Some(
667+
"val",
668+
),
669+
}},
670+
}},
626671
{PIDFD}}}"#
627672
)
628673
);

library/std/src/sys/unix/process/process_common.rs

+17
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,23 @@ impl fmt::Debug for Command {
586586
if let Some(ref cwd) = self.cwd {
587587
write!(f, "cd {cwd:?} && ")?;
588588
}
589+
if self.env.does_clear() {
590+
write!(f, "env -i ")?;
591+
// Altered env vars will be printed next, that should exactly work as expected.
592+
} else {
593+
// Removed env vars need the command to be wrapped in `env`.
594+
let mut any_removed = false;
595+
for (key, value_opt) in self.get_envs() {
596+
if value_opt.is_none() {
597+
if !any_removed {
598+
write!(f, "env ")?;
599+
any_removed = true;
600+
}
601+
write!(f, "-u {} ", key.to_string_lossy())?;
602+
}
603+
}
604+
}
605+
// Altered env vars can just be added in front of the program.
589606
for (key, value_opt) in self.get_envs() {
590607
if let Some(value) = value_opt {
591608
write!(f, "{}={value:?} ", key.to_string_lossy())?;

library/std/src/sys_common/process.rs

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ impl CommandEnv {
8080
self.vars.clear();
8181
}
8282

83+
pub fn does_clear(&self) -> bool {
84+
self.clear
85+
}
86+
8387
pub fn have_changed_path(&self) -> bool {
8488
self.saw_path || self.clear
8589
}

0 commit comments

Comments
 (0)