Open rudolphfroger opened 1 year ago
I've written a snippet to demonstrate the problem:
fn main() {
let sh = xshell::Shell::new().unwrap();
let cmd = xshell::cmd!(sh, "test -t 0");
let result = cmd.run();
println!("test if stdin is open and associated with a terminal: {result:?}");
let cmd = xshell::cmd!(sh, "cat");
let result = cmd.run();
println!("{result:?}");
}
xshell 0.2.3, doesn't wait for input and gives:
$ test -t 0
test if stdin is open and associated with a terminal: Err(command exited with non-zero code `test -t 0`: 1)
$ cat
Ok(())
xshell 0.2.2, does wait for input and outputs:
$ test -t 0
test if stdin is open and associated with a terminal: Ok(())
$ cat
^C
As expected I had to C-c
to stop cat from reading from stdin.
All functions using output_impl()
have this problem (also in 0.2.2) it's just that in 0.2.3 run()
also started to use output_impl()
.
Stdin is intentionally not inherited by default. xshell is primarily oriented towards non-interactive usage in scripts or larger programs, and there accidentally inheriting stdin might cause a latent bug.
But adding a method to control this behavior, to enable inheriting of stdin, would be useful!
There's also a bigger issue that our overall semantics with inheriting/dev/nulling standard streams seems alll over the place. Eg, the read
would inherit stderr, which also feels error prone....
So, it seems like it might make sense to overhaul the overall streams behavior here, to make it more predicatble and robust. The following would make sense to me:
The run
is thus split into two methids with TBD names:
We might actually extend this split to non-run commands like read
? If I do
let pkgid = cmd!(sh, "cargo pkgid").read()?;
In my CI, I'd probably would love to both:
See
$ cargo pkgid
file:///home/matklad/p/xshell#0.2.5
printout
This requires some fancy tee-ing of the stdout.
This large overhaul would require 0.3 of course. Toggling just stding inheritance would be a minor patch though!
Some programs use whether the stdin is a tty to decide whether to turn on color output. I had to stay on 0.2.2 for this.
This large overhaul would require 0.3 of course. Toggling just stding inheritance would be a minor patch though!
It would be great if this could be added with a simple method.
Chiming in to mention this is important for e.g. CLIs like tailwindcss
: without TTY, the --watch flag doesn't work at all.
pipe stdout/stderr, but return an error if those are non-empty.
I've since learned that checking for empty stderr
is a wrong thing to do.
While you do generally expect my-command do-thing
to return with zero and have empty stderr, there are annoying edge-cases.
For example, it might turn out that my-command
is a tool managed by some version manager, like rustup
, and, when you run my-command do-thing
, the command itself has empty stderr, but you still get
my-command v6.6.6 not found locally
downloading my-command v6.6.6
stderr printouts from that version manager.
Just hit this as well.
Updated xshell, and now our project-local xtask
that invokes apt install
to install dependencies no longer works 😅
In the interim, I've pinned our project to xshell 0.2.2.
+1 that there should be a way to opt-in to stdin inheritance
Since
0.2.3
therun
function now usesoutput_impl
andoutput_impl
is missing the option to allowstdin
to beStdio::inherit()
, which I guess should have been the default behaviour. In practice this breaks interaction with commands being executed byrun
.I think https://github.com/matklad/xshell/blob/master/src/lib.rs#L1011-L1014 should account for the case where one wants
stdin
to be inherited. So possiblyoutput_impl
also needs aignore_stdin
argument to switchstdin
toStdio::none()
. ~If you want I can write a piece of code to demonstrate the bug.~