|
|
|
@ -44,7 +44,7 @@ async fn run_async(cmd: SendSubcommand, _opt: CommonOpt) -> Result<(), Error> {
|
|
|
|
|
_ => 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
print_response(cmd.format, res)?;
|
|
|
|
|
format_response(cmd.format, res)?.print();
|
|
|
|
|
|
|
|
|
|
// If we are executing a process and not detaching, we want to continue receiving
|
|
|
|
|
// responses sent to us
|
|
|
|
@ -79,7 +79,8 @@ async fn run_async(cmd: SendSubcommand, _opt: CommonOpt) -> Result<(), Error> {
|
|
|
|
|
)
|
|
|
|
|
})?;
|
|
|
|
|
let done = res.payload.is_proc_done();
|
|
|
|
|
print_response(cmd.format, res)?;
|
|
|
|
|
|
|
|
|
|
format_response(cmd.format, res)?.print();
|
|
|
|
|
|
|
|
|
|
if done {
|
|
|
|
|
break;
|
|
|
|
@ -90,35 +91,6 @@ async fn run_async(cmd: SendSubcommand, _opt: CommonOpt) -> Result<(), Error> {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn print_response(fmt: ResponseFormat, res: Response) -> io::Result<()> {
|
|
|
|
|
// If we are not shell format or we are shell format and got stdout/stderr, we want
|
|
|
|
|
// to print out the results
|
|
|
|
|
let is_fmt_shell = fmt.is_shell();
|
|
|
|
|
let is_type_stderr = res.payload.is_proc_stderr();
|
|
|
|
|
let is_type_stdout = res.payload.is_proc_stdout();
|
|
|
|
|
let do_print = !is_fmt_shell || is_type_stderr || is_type_stdout;
|
|
|
|
|
|
|
|
|
|
let out = format_response(fmt, res)?;
|
|
|
|
|
|
|
|
|
|
// Print out our response if flagged to do so
|
|
|
|
|
if do_print {
|
|
|
|
|
// If we are shell format and got stderr, write it to stderr without altering content
|
|
|
|
|
if is_fmt_shell && is_type_stderr {
|
|
|
|
|
eprint!("{}", out);
|
|
|
|
|
|
|
|
|
|
// Else, if we are shell format and got stdout, write it to stdout without altering content
|
|
|
|
|
} else if is_fmt_shell && is_type_stdout {
|
|
|
|
|
print!("{}", out);
|
|
|
|
|
|
|
|
|
|
// Otherwise, always go to stdout with traditional println
|
|
|
|
|
} else {
|
|
|
|
|
println!("{}", out);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn spawn_stdin_reader() -> mpsc::Receiver<String> {
|
|
|
|
|
let (tx, rx) = mpsc::channel(1);
|
|
|
|
|
|
|
|
|
@ -145,63 +117,81 @@ fn spawn_stdin_reader() -> mpsc::Receiver<String> {
|
|
|
|
|
rx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn format_response(fmt: ResponseFormat, res: Response) -> io::Result<String> {
|
|
|
|
|
Ok(match fmt {
|
|
|
|
|
ResponseFormat::Human => format_human(res),
|
|
|
|
|
ResponseFormat::Json => serde_json::to_string(&res)
|
|
|
|
|
.map_err(|x| io::Error::new(io::ErrorKind::InvalidData, x))?,
|
|
|
|
|
ResponseFormat::Shell => format_shell(res),
|
|
|
|
|
})
|
|
|
|
|
/// Represents the output content and destination
|
|
|
|
|
enum ResponseOut {
|
|
|
|
|
Stdout(String),
|
|
|
|
|
Stderr(String),
|
|
|
|
|
None,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn format_shell(res: Response) -> String {
|
|
|
|
|
match res.payload {
|
|
|
|
|
ResponsePayload::ProcStdout { data, .. } => String::from_utf8_lossy(&data).to_string(),
|
|
|
|
|
ResponsePayload::ProcStderr { data, .. } => String::from_utf8_lossy(&data).to_string(),
|
|
|
|
|
_ => String::new(),
|
|
|
|
|
impl ResponseOut {
|
|
|
|
|
pub fn print(self) {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Stdout(x) => print!("{}", x),
|
|
|
|
|
Self::Stderr(x) => eprint!("{}", x),
|
|
|
|
|
Self::None => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn format_human(res: Response) -> String {
|
|
|
|
|
fn format_response(fmt: ResponseFormat, res: Response) -> io::Result<ResponseOut> {
|
|
|
|
|
Ok(match fmt {
|
|
|
|
|
ResponseFormat::Json => ResponseOut::Stdout(
|
|
|
|
|
serde_json::to_string(&res)
|
|
|
|
|
.map_err(|x| io::Error::new(io::ErrorKind::InvalidData, x))?,
|
|
|
|
|
),
|
|
|
|
|
ResponseFormat::Shell => format_shell(res),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn format_shell(res: Response) -> ResponseOut {
|
|
|
|
|
match res.payload {
|
|
|
|
|
ResponsePayload::Ok => "Done.".to_string(),
|
|
|
|
|
ResponsePayload::Error { description } => format!("Failed: '{}'.", description),
|
|
|
|
|
ResponsePayload::Blob { data } => String::from_utf8_lossy(&data).to_string(),
|
|
|
|
|
ResponsePayload::Text { data } => data,
|
|
|
|
|
ResponsePayload::DirEntries { entries } => entries
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|entry| {
|
|
|
|
|
format!(
|
|
|
|
|
"{}{}",
|
|
|
|
|
entry.path.as_os_str().to_string_lossy(),
|
|
|
|
|
if entry.file_type.is_dir() {
|
|
|
|
|
std::path::MAIN_SEPARATOR.to_string()
|
|
|
|
|
} else {
|
|
|
|
|
String::new()
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
.join("\n"),
|
|
|
|
|
ResponsePayload::ProcEntries { entries } => entries
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|entry| format!("{}: {} {}", entry.id, entry.cmd, entry.args.join(" ")))
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
.join("\n"),
|
|
|
|
|
ResponsePayload::ProcStart { id } => format!("Proc({}): Started.", id),
|
|
|
|
|
ResponsePayload::ProcStdout { id, data } => {
|
|
|
|
|
format!("Stdout({}): '{}'.", id, String::from_utf8_lossy(&data))
|
|
|
|
|
ResponsePayload::Ok => ResponseOut::None,
|
|
|
|
|
ResponsePayload::Error { description } => {
|
|
|
|
|
ResponseOut::Stderr(format!("Failed: '{}'.", description))
|
|
|
|
|
}
|
|
|
|
|
ResponsePayload::Blob { data } => {
|
|
|
|
|
ResponseOut::Stdout(String::from_utf8_lossy(&data).to_string())
|
|
|
|
|
}
|
|
|
|
|
ResponsePayload::Text { data } => ResponseOut::Stdout(data),
|
|
|
|
|
ResponsePayload::DirEntries { entries } => ResponseOut::Stdout(
|
|
|
|
|
entries
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|entry| {
|
|
|
|
|
format!(
|
|
|
|
|
"{}{}",
|
|
|
|
|
entry.path.as_os_str().to_string_lossy(),
|
|
|
|
|
if entry.file_type.is_dir() {
|
|
|
|
|
std::path::MAIN_SEPARATOR.to_string()
|
|
|
|
|
} else {
|
|
|
|
|
String::new()
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
.join("\n"),
|
|
|
|
|
),
|
|
|
|
|
ResponsePayload::ProcEntries { entries } => ResponseOut::Stdout(
|
|
|
|
|
entries
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|entry| format!("{}: {} {}", entry.id, entry.cmd, entry.args.join(" ")))
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
.join("\n"),
|
|
|
|
|
),
|
|
|
|
|
ResponsePayload::ProcStart { .. } => ResponseOut::None,
|
|
|
|
|
ResponsePayload::ProcStdout { data, .. } => {
|
|
|
|
|
ResponseOut::Stdout(String::from_utf8_lossy(&data).to_string())
|
|
|
|
|
}
|
|
|
|
|
ResponsePayload::ProcStderr { id, data } => {
|
|
|
|
|
format!("Stderr({}): '{}'.", id, String::from_utf8_lossy(&data))
|
|
|
|
|
ResponsePayload::ProcStderr { data, .. } => {
|
|
|
|
|
ResponseOut::Stderr(String::from_utf8_lossy(&data).to_string())
|
|
|
|
|
}
|
|
|
|
|
ResponsePayload::ProcDone { id, success, code } => {
|
|
|
|
|
if success {
|
|
|
|
|
format!("Proc({}): Done.", id)
|
|
|
|
|
ResponseOut::None
|
|
|
|
|
} else if let Some(code) = code {
|
|
|
|
|
format!("Proc({}): Failed with code {}.", id, code)
|
|
|
|
|
ResponseOut::Stderr(format!("Proc {} failed with code {}", id, code))
|
|
|
|
|
} else {
|
|
|
|
|
format!("Proc({}): Failed.", id)
|
|
|
|
|
ResponseOut::Stderr(format!("Proc {} failed", id))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|