summaryrefslogtreecommitdiffstats
path: root/src/runner/builtins/command.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/runner/builtins/command.rs')
-rw-r--r--src/runner/builtins/command.rs123
1 files changed, 49 insertions, 74 deletions
diff --git a/src/runner/builtins/command.rs b/src/runner/builtins/command.rs
index e3a3fce..16d8b40 100644
--- a/src/runner/builtins/command.rs
+++ b/src/runner/builtins/command.rs
@@ -38,8 +38,8 @@ impl Command {
self.cfg.io.set_stderr(fh);
}
- // Safety: see pre_exec in async_std::os::unix::process::CommandExt (this
- // is just a wrapper)
+ // Safety: see pre_exec in tokio::process::Command (this is just a
+ // wrapper)
pub unsafe fn pre_exec<F>(&mut self, f: F)
where
F: 'static + FnMut() -> std::io::Result<()> + Send + Sync,
@@ -51,7 +51,7 @@ impl Command {
self.cfg.io.apply_redirects(redirects);
}
- pub fn spawn(self, env: &Env) -> anyhow::Result<Child> {
+ pub fn spawn(self, env: &Env) -> Result<Child> {
let Self { f, exe, cfg } = self;
(f)(exe, env, cfg)
}
@@ -73,8 +73,8 @@ impl Cfg {
&self.io
}
- // Safety: see pre_exec in async_std::os::unix::process::CommandExt (this
- // is just a wrapper)
+ // Safety: see pre_exec in tokio::process::Command (this is just a
+ // wrapper)
pub unsafe fn pre_exec<F>(&mut self, f: F)
where
F: 'static + FnMut() -> std::io::Result<()> + Send + Sync,
@@ -187,10 +187,10 @@ impl Io {
}
}
- pub async fn read_line_stdin(&self) -> anyhow::Result<(String, bool)> {
- let mut buf = vec![];
- if let Some(fh) = self.stdin() {
- if let File::In(fh) = &*fh {
+ pub fn read_line_stdin(&self) -> Result<(String, bool)> {
+ let mut line = vec![];
+ if let Some(file) = self.stdin() {
+ if let File::In(fh) = &*file {
// we have to read only a single character at a time here
// because stdin needs to be shared across all commands in the
// command list, some of which may be builtins and others of
@@ -199,36 +199,27 @@ impl Io {
// no longer be available to the next command, since we have
// them buffered in memory rather than them being on the stdin
// pipe.
- let mut c = [0_u8];
- loop {
- match (&*fh).read_exact(&mut c[..]).await {
- Ok(()) => {}
- Err(e) => {
- if e.kind() == std::io::ErrorKind::UnexpectedEof {
- break;
- }
- return Err(e.into());
- }
- }
- if c[0] == b'\n' {
+ for byte in fh.bytes() {
+ let byte = byte?;
+ line.push(byte);
+ if byte == b'\n' {
break;
}
- buf.push(c[0]);
}
}
}
- let done = buf.is_empty();
- let mut buf = String::from_utf8(buf).unwrap();
- if buf.ends_with('\n') {
- buf.truncate(buf.len() - 1);
+ let done = line.is_empty();
+ let mut line = String::from_utf8(line).unwrap();
+ if line.ends_with('\n') {
+ line.truncate(line.len() - 1);
}
- Ok((buf, done))
+ Ok((line, done))
}
- pub async fn write_stdout(&self, buf: &[u8]) -> anyhow::Result<()> {
- if let Some(fh) = self.stdout() {
- if let File::Out(fh) = &*fh {
- Ok((&*fh).write_all(buf).await.map(|_| ())?)
+ pub fn write_stdout(&self, buf: &[u8]) -> Result<()> {
+ if let Some(file) = self.stdout() {
+ if let File::Out(fh) = &*file {
+ Ok((&*fh).write_all(buf)?)
} else {
Ok(())
}
@@ -237,10 +228,10 @@ impl Io {
}
}
- pub async fn write_stderr(&self, buf: &[u8]) -> anyhow::Result<()> {
- if let Some(fh) = self.stderr() {
- if let File::Out(fh) = &*fh {
- Ok((&*fh).write_all(buf).await.map(|_| ())?)
+ pub fn write_stderr(&self, buf: &[u8]) -> Result<()> {
+ if let Some(file) = self.stderr() {
+ if let File::Out(fh) = &*file {
+ Ok((&*fh).write_all(buf)?)
} else {
Ok(())
}
@@ -299,19 +290,19 @@ impl Drop for Io {
#[derive(Debug)]
pub enum File {
- In(async_std::fs::File),
- Out(async_std::fs::File),
+ In(std::fs::File),
+ Out(std::fs::File),
}
impl File {
// Safety: fd must not be owned by any other File object
pub unsafe fn input(fd: std::os::unix::io::RawFd) -> Self {
- Self::In(async_std::fs::File::from_raw_fd(fd))
+ Self::In(std::fs::File::from_raw_fd(fd))
}
// Safety: fd must not be owned by any other File object
pub unsafe fn output(fd: std::os::unix::io::RawFd) -> Self {
- Self::Out(async_std::fs::File::from_raw_fd(fd))
+ Self::Out(std::fs::File::from_raw_fd(fd))
}
fn maybe_drop(file: std::sync::Arc<Self>) {
@@ -339,59 +330,43 @@ impl std::os::unix::io::IntoRawFd for File {
}
}
-pub struct Child<'a> {
- fut: std::pin::Pin<
- Box<
- dyn std::future::Future<Output = std::process::ExitStatus>
- + Sync
- + Send
- + 'a,
- >,
- >,
- wrapped_child: Option<Box<crate::runner::Child<'a>>>,
+pub enum Child {
+ Task(tokio::task::JoinHandle<std::process::ExitStatus>),
+ Wrapped(Box<crate::runner::Child>),
}
-impl<'a> Child<'a> {
- pub fn new_fut<F>(fut: F) -> Self
+impl Child {
+ pub fn new_task<F>(f: F) -> Self
where
- F: std::future::Future<Output = std::process::ExitStatus>
- + Sync
- + Send
- + 'a,
+ F: FnOnce() -> std::process::ExitStatus + Send + 'static,
{
- Self {
- fut: Box::pin(fut),
- wrapped_child: None,
- }
+ Self::Task(tokio::task::spawn_blocking(f))
}
- pub fn new_wrapped(child: crate::runner::Child<'a>) -> Self {
- Self {
- fut: Box::pin(async move { unreachable!() }),
- wrapped_child: Some(Box::new(child)),
- }
+ pub fn new_wrapped(child: crate::runner::Child) -> Self {
+ Self::Wrapped(Box::new(child))
}
pub fn id(&self) -> Option<u32> {
- self.wrapped_child.as_ref().and_then(|cmd| cmd.id())
+ match self {
+ Self::Task(_) => None,
+ Self::Wrapped(child) => child.id(),
+ }
}
pub fn status(
self,
) -> std::pin::Pin<
Box<
- dyn std::future::Future<
- Output = anyhow::Result<async_std::process::ExitStatus>,
- > + Send
- + Sync
- + 'a,
+ dyn std::future::Future<Output = Result<std::process::ExitStatus>>
+ + Send
+ + Sync,
>,
> {
Box::pin(async move {
- if let Some(child) = self.wrapped_child {
- child.status().await
- } else {
- Ok(self.fut.await)
+ match self {
+ Self::Task(task) => task.await.map_err(|e| anyhow!(e)),
+ Self::Wrapped(child) => child.status().await,
}
})
}