Allow for passing stdin to child (#106)

This commit is contained in:
Erica Marigold 2023-10-06 07:00:27 +05:30 committed by GitHub
parent c43648faec
commit 8865692f1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 3 deletions

View file

@ -7,6 +7,7 @@ use std::{
use dunce::canonicalize;
use mlua::prelude::*;
use os_str_bytes::RawOsString;
use tokio::io::AsyncWriteExt;
use crate::lune::{scheduler::Scheduler, util::TableBuilder};
@ -199,17 +200,27 @@ async fn process_spawn(
async fn spawn_command(
program: String,
args: Option<Vec<String>>,
options: ProcessSpawnOptions,
mut options: ProcessSpawnOptions,
) -> LuaResult<(ExitStatus, Vec<u8>, Vec<u8>)> {
let inherit_stdio = options.inherit_stdio;
let stdin = options.stdin.take();
let child = options
let mut child = options
.into_command(program, args)
.stdin(Stdio::null())
.stdin(match stdin.is_some() {
true => Stdio::piped(),
false => Stdio::null(),
})
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()?;
// If the stdin option was provided, we write that to the child
if let Some(stdin) = stdin {
let mut child_stdin = child.stdin.take().unwrap();
child_stdin.write_all(&stdin).await.into_lua_err()?;
}
if inherit_stdio {
pipe_and_inherit_child_process_stdio(child).await
} else {

View file

@ -14,6 +14,7 @@ pub struct ProcessSpawnOptions {
pub(crate) envs: HashMap<String, String>,
pub(crate) shell: Option<String>,
pub(crate) inherit_stdio: bool,
pub(crate) stdin: Option<Vec<u8>>,
}
impl<'lua> FromLua<'lua> for ProcessSpawnOptions {
@ -133,6 +134,20 @@ impl<'lua> FromLua<'lua> for ProcessSpawnOptions {
}
}
/*
If we have stdin contents, we need to pass those to the child process
*/
match value.get("stdin")? {
LuaValue::Nil => {}
LuaValue::String(s) => this.stdin = Some(s.as_bytes().to_vec()),
value => {
return Err(LuaError::RuntimeError(format!(
"Invalid type for option 'stdin' - expected 'string', got '{}'",
value.type_name()
)))
}
}
Ok(this)
}
}

View file

@ -160,3 +160,20 @@ assert(
echoResult.stdout == (echoMessage .. trailingAddition),
"Inheriting stdio did not return proper output"
)
-- Passing stdin strings should work
local stdinChild = process.spawn(not IS_WINDOWS and "xargs" or "powershell", {
"echo",
}, {
stdin = echoMessage .. (IS_WINDOWS and "\n\n" or ""),
})
local stdinChildOut = stdinChild.stdout
if IS_WINDOWS then
stdinChildOut = stdinChildOut:sub(#stdinChildOut - #echoMessage - 1, #stdinChildOut)
end
assert(
stdinChildOut == echoMessage .. trailingAddition,
"Stdin passing did not return proper output"
)

View file

@ -13,12 +13,14 @@ export type SpawnOptionsStdio = "inherit" | "default"
* `env` - Extra environment variables to give to the process
* `shell` - Whether to run in a shell or not - set to `true` to run using the default shell, or a string to run using a specific shell
* `stdio` - How to treat output and error streams from the child process - set to "inherit" to pass output and error streams to the current process
* `stdin` - Optional standard input to pass to spawned child process
]=]
export type SpawnOptions = {
cwd: string?,
env: { [string]: string }?,
shell: (boolean | string)?,
stdio: SpawnOptionsStdio?,
stdin: string?,
}
--[=[