mirror of
https://github.com/nushell/nushell
synced 2024-11-10 15:14:14 +00:00
Switch from subprocess crate to the builtin std::process (#1284)
* Switch from subprocess crate to the builtin std::process * Update external.rs * Update external.rs * Update external.rs Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
parent
d48f99cb0e
commit
32dfb32741
8 changed files with 32 additions and 67 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -2282,7 +2282,6 @@ dependencies = [
|
||||||
"shellexpand",
|
"shellexpand",
|
||||||
"starship",
|
"starship",
|
||||||
"strip-ansi-escapes",
|
"strip-ansi-escapes",
|
||||||
"subprocess",
|
|
||||||
"syntect",
|
"syntect",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"term",
|
"term",
|
||||||
|
@ -2326,7 +2325,6 @@ dependencies = [
|
||||||
"serde 1.0.104",
|
"serde 1.0.104",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"subprocess",
|
|
||||||
"toml 0.5.6",
|
"toml 0.5.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2411,7 +2409,6 @@ dependencies = [
|
||||||
"serde_bytes",
|
"serde_bytes",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"subprocess",
|
|
||||||
"toml 0.5.6",
|
"toml 0.5.6",
|
||||||
"typetag",
|
"typetag",
|
||||||
]
|
]
|
||||||
|
@ -3795,17 +3792,6 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "subprocess"
|
|
||||||
version = "0.1.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68713fc0f9d941642c1e020d622e6421dfe09e8891ddd4bfa2109fda9a40431d"
|
|
||||||
dependencies = [
|
|
||||||
"crossbeam-utils 0.7.0",
|
|
||||||
"libc",
|
|
||||||
"winapi 0.3.8",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "surf"
|
name = "surf"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
|
|
@ -101,7 +101,6 @@ nom_locate = "1.0.0"
|
||||||
nom-tracable = "0.4.1"
|
nom-tracable = "0.4.1"
|
||||||
unicode-xid = "0.2.0"
|
unicode-xid = "0.2.0"
|
||||||
serde_ini = "0.2.0"
|
serde_ini = "0.2.0"
|
||||||
subprocess = "0.1.20"
|
|
||||||
pretty-hex = "0.1.1"
|
pretty-hex = "0.1.1"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
|
@ -24,7 +24,6 @@ nom_locate = "1.0.0"
|
||||||
getset = "0.0.9"
|
getset = "0.0.9"
|
||||||
|
|
||||||
# implement conversions
|
# implement conversions
|
||||||
subprocess = "0.1.18"
|
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
toml = "0.5.5"
|
toml = "0.5.5"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
|
|
|
@ -821,12 +821,6 @@ impl std::convert::From<std::io::Error> for ShellError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<subprocess::PopenError> for ShellError {
|
|
||||||
fn from(input: subprocess::PopenError) -> ShellError {
|
|
||||||
ShellError::untagged_runtime_error(format!("{}", input))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::convert::From<serde_yaml::Error> for ShellError {
|
impl std::convert::From<serde_yaml::Error> for ShellError {
|
||||||
fn from(input: serde_yaml::Error) -> ShellError {
|
fn from(input: serde_yaml::Error) -> ShellError {
|
||||||
ShellError::untagged_runtime_error(format!("{:?}", input))
|
ShellError::untagged_runtime_error(format!("{:?}", input))
|
||||||
|
|
|
@ -33,7 +33,6 @@ byte-unit = "3.0.3"
|
||||||
natural = "0.3.0"
|
natural = "0.3.0"
|
||||||
|
|
||||||
# implement conversions
|
# implement conversions
|
||||||
subprocess = "0.1.18"
|
|
||||||
serde_yaml = "0.8"
|
serde_yaml = "0.8"
|
||||||
toml = "0.5.5"
|
toml = "0.5.5"
|
||||||
serde_json = "1.0.44"
|
serde_json = "1.0.44"
|
||||||
|
|
|
@ -70,7 +70,6 @@ rustyline = "4.1.0"
|
||||||
serde = "1.0.91"
|
serde = "1.0.91"
|
||||||
serde_derive = "1.0.91"
|
serde_derive = "1.0.91"
|
||||||
serde_json = "1.0.39"
|
serde_json = "1.0.39"
|
||||||
subprocess = "0.1.18"
|
|
||||||
sysinfo = "0.8.4"
|
sysinfo = "0.8.4"
|
||||||
term = "0.5.2"
|
term = "0.5.2"
|
||||||
tokio-fs = "0.1.6"
|
tokio-fs = "0.1.6"
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use futures_codec::{Decoder, Encoder, Framed};
|
use futures_codec::{Decoder, Encoder, FramedRead};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_parser::ExternalCommand;
|
use nu_parser::ExternalCommand;
|
||||||
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
|
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
|
||||||
use std::io::{Error, ErrorKind, Write};
|
use std::io::{Error, ErrorKind, Write};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use subprocess::Exec;
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
/// A simple `Codec` implementation that splits up data into lines.
|
/// A simple `Codec` implementation that splits up data into lines.
|
||||||
pub struct LinesCodec {}
|
pub struct LinesCodec {}
|
||||||
|
@ -275,11 +275,11 @@ async fn spawn(
|
||||||
let mut process = {
|
let mut process = {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
let mut process = Exec::cmd("cmd");
|
let mut process = Command::new("cmd");
|
||||||
process = process.arg("/c");
|
process.arg("/c");
|
||||||
process = process.arg(&command.name);
|
process.arg(&command.name);
|
||||||
for arg in args {
|
for arg in args {
|
||||||
process = process.arg(&arg);
|
process.arg(&arg);
|
||||||
}
|
}
|
||||||
process
|
process
|
||||||
}
|
}
|
||||||
|
@ -287,34 +287,34 @@ async fn spawn(
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
let cmd_with_args = vec![command.name.clone(), args.join(" ")].join(" ");
|
let cmd_with_args = vec![command.name.clone(), args.join(" ")].join(" ");
|
||||||
Exec::shell(&cmd_with_args)
|
let mut process = Command::new("sh");
|
||||||
|
process.arg("-c").arg(cmd_with_args);
|
||||||
|
process
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
process = process.cwd(path);
|
process.current_dir(path);
|
||||||
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
trace!(target: "nu::run::external", "cwd = {:?}", &path);
|
||||||
|
|
||||||
// We want stdout regardless of what
|
// We want stdout regardless of what
|
||||||
// we are doing ($it case or pipe stdin)
|
// we are doing ($it case or pipe stdin)
|
||||||
if !is_last {
|
if !is_last {
|
||||||
process = process.stdout(subprocess::Redirection::Pipe);
|
process.stdout(Stdio::piped());
|
||||||
trace!(target: "nu::run::external", "set up stdout pipe");
|
trace!(target: "nu::run::external", "set up stdout pipe");
|
||||||
}
|
}
|
||||||
|
|
||||||
// open since we have some contents for stdin
|
// open since we have some contents for stdin
|
||||||
if stdin_contents.is_some() {
|
if stdin_contents.is_some() {
|
||||||
process = process.stdin(subprocess::Redirection::Pipe);
|
process.stdin(Stdio::piped());
|
||||||
trace!(target: "nu::run::external", "set up stdin pipe");
|
trace!(target: "nu::run::external", "set up stdin pipe");
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!(target: "nu::run::external", "built process {:?}", process);
|
trace!(target: "nu::run::external", "built command {:?}", process);
|
||||||
|
|
||||||
let popen = process.detached().popen();
|
if let Ok(mut child) = process.spawn() {
|
||||||
|
|
||||||
if let Ok(mut popen) = popen {
|
|
||||||
let stream = async_stream! {
|
let stream = async_stream! {
|
||||||
if let Some(mut input) = stdin_contents.as_ref() {
|
if let Some(mut input) = stdin_contents.as_ref() {
|
||||||
let mut stdin_write = popen.stdin
|
let mut stdin_write = child.stdin
|
||||||
.take()
|
.take()
|
||||||
.expect("Internal error: could not get stdin pipe for external command");
|
.expect("Internal error: could not get stdin pipe for external command");
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ async fn spawn(
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_last && command.has_it_argument() {
|
if is_last && command.has_it_argument() {
|
||||||
if let Ok(status) = popen.wait() {
|
if let Ok(status) = child.wait() {
|
||||||
if status.success() {
|
if status.success() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ async fn spawn(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_last {
|
if !is_last {
|
||||||
let stdout = if let Some(stdout) = popen.stdout.take() {
|
let stdout = if let Some(stdout) = child.stdout.take() {
|
||||||
stdout
|
stdout
|
||||||
} else {
|
} else {
|
||||||
yield Ok(Value {
|
yield Ok(Value {
|
||||||
|
@ -376,7 +376,7 @@ async fn spawn(
|
||||||
};
|
};
|
||||||
|
|
||||||
let file = futures::io::AllowStdIo::new(stdout);
|
let file = futures::io::AllowStdIo::new(stdout);
|
||||||
let stream = Framed::new(file, LinesCodec {});
|
let stream = FramedRead::new(file, LinesCodec {});
|
||||||
|
|
||||||
let mut stream = stream.map(|line| {
|
let mut stream = stream.map(|line| {
|
||||||
if let Ok(line) = line {
|
if let Ok(line) = line {
|
||||||
|
@ -394,30 +394,20 @@ async fn spawn(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
if child.wait().is_err() {
|
||||||
match popen.poll() {
|
let cfg = crate::data::config::config(Tag::unknown());
|
||||||
None => futures_timer::Delay::new(std::time::Duration::from_millis(10)).await,
|
if let Ok(cfg) = cfg {
|
||||||
Some(status) => {
|
if cfg.contains_key("nonzero_exit_errors") {
|
||||||
if !status.success() {
|
yield Ok(Value {
|
||||||
// We can give an error when we see a non-zero exit code, but this is different
|
value: UntaggedValue::Error(
|
||||||
// than what other shells will do.
|
ShellError::labeled_error(
|
||||||
let cfg = crate::data::config::config(Tag::unknown());
|
"External command failed",
|
||||||
if let Ok(cfg) = cfg {
|
"command failed",
|
||||||
if cfg.contains_key("nonzero_exit_errors") {
|
&name_tag,
|
||||||
yield Ok(Value {
|
)
|
||||||
value: UntaggedValue::Error(
|
),
|
||||||
ShellError::labeled_error(
|
tag: name_tag,
|
||||||
"External command failed",
|
});
|
||||||
"command failed",
|
|
||||||
&name_tag,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
tag: name_tag,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
tests/fixtures/formats/cargo_sample.toml
vendored
1
tests/fixtures/formats/cargo_sample.toml
vendored
|
@ -19,7 +19,6 @@ itertools = "0.8.0"
|
||||||
ansi_term = "0.11.0"
|
ansi_term = "0.11.0"
|
||||||
conch-parser = "0.1.1"
|
conch-parser = "0.1.1"
|
||||||
nom = "5.0.0-beta1"
|
nom = "5.0.0-beta1"
|
||||||
subprocess = "0.1.18"
|
|
||||||
dunce = "1.0.0"
|
dunce = "1.0.0"
|
||||||
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
indexmap = { version = "1.0.2", features = ["serde-1"] }
|
||||||
chrono-humanize = "0.0.11"
|
chrono-humanize = "0.0.11"
|
||||||
|
|
Loading…
Reference in a new issue