tog/commands/run/handlers/
output.rs1use crate::profile::Profile;
2use crate::commands::run::handlers::monitor;
3use crate::commands::run::processes::stream_read::{PipeStreamReader, PipedLine};
4use crate::commands::run::processes::Process;
5use crate::util::log;
6use crossbeam_channel::Select;
7use std::collections::HashMap;
8
9pub fn handle_output(profile: &Profile, mut proc: Process) {
10 let mut channels: Vec<PipeStreamReader> = Vec::new();
11 channels.push(PipeStreamReader::new(Box::new(
12 proc.child.stdout.take().expect("!stdout"),
13 )));
14 channels.push(PipeStreamReader::new(Box::new(
15 proc.child.stderr.take().expect("!stderr"),
16 )));
17
18 let mut select = Select::new();
19 for channel in channels.iter() {
20 select.recv(&channel.lines);
21 }
22
23 let mut stream_eof = false;
24
25 while !stream_eof {
26 let operation = select.select();
27 let index = operation.index();
28 let received = operation.recv(&channels.get(index).expect("!channel").lines);
29
30 match received {
31 Ok(remote_result) => match remote_result {
32 Ok(piped_line) => match piped_line {
33 PipedLine::Line(line) => {
34 handle_output_line(&profile, &mut proc, line);
35 }
36 PipedLine::EOF => {
37 stream_eof = true;
38 select.remove(index);
39 }
40 },
41 Err(error) => log::error(&format!("{:?}", error)),
42 },
43 Err(_) => {
44 stream_eof = true;
45 select.remove(index);
46 }
47 }
48 }
49
50 let status = proc.child.wait().expect("!wait");
51 if status.success() {
52 let annotated_message = &format!("[{}] exited with success.", proc.name);
53 log::logger(annotated_message);
54 } else {
55 let annotated_message = &format!("[{}] exited with failure.", proc.name);
56 log::logger(annotated_message);
57 }
58}
59
60pub fn handle_output_line(profile: &Profile, proc: &mut Process, line: String) {
61 let mut log_data = log::LogData {
62 message: &line,
63 snippets: HashMap::new(),
64 };
65
66 monitor::handle_monitor(profile, proc, &mut log_data);
67}