save: print to stderr for bytestream (#13422)

# Description
Fixes: #13260 

When user run a command like this:
```nushell
$env.FOO = " New";
$env.BAZ = " New Err";
do -i {nu -n -c 'nu --testbin echo_env FOO; nu --testbin echo_env_stderr BAZ'} | save -a -r save_test_22/log.txt
```

`save` command sinks the output of previous commands' stderr output. I
think it should be `stderr`.

# User-Facing Changes
```nushell
$env.FOO = " New";
$env.BAZ = " New Err";
do -i {nu -n -c 'nu --testbin echo_env FOO; nu --testbin echo_env_stderr BAZ'} | save -a -r save_test_22/log.txt
```
The command will output ` New Err` to stderr.

# Tests + Formatting
Added 2 cases.
This commit is contained in:
Wind 2024-08-01 00:19:35 +08:00 committed by GitHub
parent d880241102
commit 928c57db41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 2 deletions

View file

@ -121,9 +121,11 @@ impl Command for Save {
} else {
match stderr {
ChildPipe::Pipe(mut pipe) => {
io::copy(&mut pipe, &mut io::sink())
io::copy(&mut pipe, &mut io::stderr())
}
ChildPipe::Tee(mut tee) => {
io::copy(&mut tee, &mut io::stderr())
}
ChildPipe::Tee(mut tee) => io::copy(&mut tee, &mut io::sink()),
}
.err_span(span)?;
}

View file

@ -463,3 +463,65 @@ fn save_same_file_with_collect_and_filter() {
assert_eq!("helloworld", actual.out);
})
}
#[test]
fn save_from_child_process_dont_sink_stderr() {
Playground::setup("save_test_22", |dirs, sandbox| {
sandbox.with_files(&[
Stub::FileWithContent("log.txt", "Old"),
Stub::FileWithContent("err.txt", "Old Err"),
]);
let expected_file = dirs.test().join("log.txt");
let expected_stderr_file = dirs.test().join("err.txt");
let actual = nu!(
cwd: dirs.root(),
r#"
$env.FOO = " New";
$env.BAZ = " New Err";
do -i {nu -n -c 'nu --testbin echo_env FOO; nu --testbin echo_env_stderr BAZ'} | save -a -r save_test_22/log.txt"#,
);
assert_eq!(actual.err.trim_end(), " New Err");
let actual = file_contents(expected_file);
assert_eq!(actual.trim_end(), "Old New");
let actual = file_contents(expected_stderr_file);
assert_eq!(actual.trim_end(), "Old Err");
})
}
#[test]
fn parent_redirection_doesnt_affect_save() {
Playground::setup("save_test_23", |dirs, sandbox| {
sandbox.with_files(&[
Stub::FileWithContent("log.txt", "Old"),
Stub::FileWithContent("err.txt", "Old Err"),
]);
let expected_file = dirs.test().join("log.txt");
let expected_stderr_file = dirs.test().join("err.txt");
let actual = nu!(
cwd: dirs.root(),
r#"
$env.FOO = " New";
$env.BAZ = " New Err";
def tttt [] {
do -i {nu -n -c 'nu --testbin echo_env FOO; nu --testbin echo_env_stderr BAZ'} | save -a -r save_test_23/log.txt
};
tttt e> ("save_test_23" | path join empty_file)"#
);
assert_eq!(actual.err.trim_end(), " New Err");
let actual = file_contents(expected_file);
assert_eq!(actual.trim_end(), "Old New");
let actual = file_contents(expected_stderr_file);
assert_eq!(actual.trim_end(), "Old Err");
let actual = file_contents(dirs.test().join("empty_file"));
assert_eq!(actual.trim_end(), "");
})
}