Move the running build into its own struct.
This commit is contained in:
@@ -3,17 +3,13 @@ use std::ffi::OsString;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
|
|
||||||
use tokio::io::AsyncBufReadExt;
|
|
||||||
use tokio::io::BufReader;
|
|
||||||
use tokio::io::Lines;
|
|
||||||
use tokio::process::Child;
|
|
||||||
use tokio::process::ChildStderr;
|
|
||||||
use tokio::process::ChildStdout;
|
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::database::db_handle::DbHandle;
|
use crate::database::db_handle::DbHandle;
|
||||||
|
|
||||||
|
use super::running_build::RunningBuild;
|
||||||
|
|
||||||
pub(crate) async fn nixos_build_target<B, F, A>(
|
pub(crate) async fn nixos_build_target<B, F, A>(
|
||||||
db_handle: &DbHandle,
|
db_handle: &DbHandle,
|
||||||
build_path: B,
|
build_path: B,
|
||||||
@@ -56,110 +52,10 @@ where
|
|||||||
command.arg(reference);
|
command.arg(reference);
|
||||||
command.kill_on_drop(true);
|
command.kill_on_drop(true);
|
||||||
|
|
||||||
let mut child = command.spawn()?;
|
let child = command.spawn()?;
|
||||||
|
|
||||||
let mut output_stream = OutputSream::from_child(&mut child)?;
|
let mut running_build = RunningBuild::new(db_handle)?;
|
||||||
|
running_build.run_to_completion(child).await?;
|
||||||
let exit_status_handle = tokio::spawn(async move {
|
|
||||||
let status = child
|
|
||||||
.wait()
|
|
||||||
.await
|
|
||||||
.expect("nixos-rebuild encountered an error");
|
|
||||||
status
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let next_line = output_stream.next_line().await?;
|
|
||||||
match next_line {
|
|
||||||
OutputLine::Stdout(line) => {
|
|
||||||
println!("STDOUT: {line}");
|
|
||||||
}
|
|
||||||
OutputLine::Stderr(line) => {
|
|
||||||
println!("STDERR: {line}");
|
|
||||||
}
|
|
||||||
OutputLine::Done => break,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let exit_status = exit_status_handle.await?;
|
|
||||||
println!("nixos-rebuild status was: {}", exit_status);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OutputSream {
|
|
||||||
stdout: Option<Lines<BufReader<ChildStdout>>>,
|
|
||||||
stderr: Option<Lines<BufReader<ChildStderr>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl OutputSream {
|
|
||||||
pub(crate) fn from_child(child: &mut Child) -> Result<Self> {
|
|
||||||
let stdout = child
|
|
||||||
.stdout
|
|
||||||
.take()
|
|
||||||
.expect("child did not have a handle to stdout");
|
|
||||||
let stderr = child
|
|
||||||
.stderr
|
|
||||||
.take()
|
|
||||||
.expect("child did not have a handle to stderr");
|
|
||||||
let stdout = BufReader::new(stdout).lines();
|
|
||||||
let stderr = BufReader::new(stderr).lines();
|
|
||||||
Ok(OutputSream {
|
|
||||||
stdout: Some(stdout),
|
|
||||||
stderr: Some(stderr),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn next_line(&mut self) -> Result<OutputLine> {
|
|
||||||
loop {
|
|
||||||
match (&mut self.stdout, &mut self.stderr) {
|
|
||||||
(None, None) => {
|
|
||||||
return Ok(OutputLine::Done);
|
|
||||||
}
|
|
||||||
(None, Some(err)) => {
|
|
||||||
if let Some(line) = err.next_line().await? {
|
|
||||||
return Ok(OutputLine::Stderr(line));
|
|
||||||
} else {
|
|
||||||
return Ok(OutputLine::Done);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Some(out), None) => {
|
|
||||||
if let Some(line) = out.next_line().await? {
|
|
||||||
return Ok(OutputLine::Stdout(line));
|
|
||||||
} else {
|
|
||||||
return Ok(OutputLine::Done);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Some(out), Some(err)) => {
|
|
||||||
tokio::select! {
|
|
||||||
Ok(line) = out.next_line() => match line {
|
|
||||||
Some(line) => {
|
|
||||||
return Ok(OutputLine::Stdout(line));
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
self.stdout.take();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Ok(line) = err.next_line() => match line {
|
|
||||||
Some(line) => {
|
|
||||||
return Ok(OutputLine::Stderr(line));
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
self.stderr.take();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
else => {
|
|
||||||
return Ok(OutputLine::Done);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum OutputLine {
|
|
||||||
Stdout(String),
|
|
||||||
Stderr(String),
|
|
||||||
Done,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
mod high_level;
|
mod high_level;
|
||||||
|
mod running_build;
|
||||||
pub(crate) use high_level::*;
|
pub(crate) use high_level::*;
|
||||||
|
|||||||
127
src/nix_util/running_build.rs
Normal file
127
src/nix_util/running_build.rs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
use tokio::io::AsyncBufReadExt;
|
||||||
|
use tokio::io::BufReader;
|
||||||
|
use tokio::io::Lines;
|
||||||
|
use tokio::process::Child;
|
||||||
|
use tokio::process::ChildStderr;
|
||||||
|
use tokio::process::ChildStdout;
|
||||||
|
|
||||||
|
use crate::Result;
|
||||||
|
use crate::database::db_handle::DbHandle;
|
||||||
|
|
||||||
|
pub(crate) struct RunningBuild<'db> {
|
||||||
|
db_handle: &'db DbHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'db> RunningBuild<'db> {
|
||||||
|
pub(crate) fn new(db_handle: &'db DbHandle) -> Result<Self> {
|
||||||
|
Ok(RunningBuild { db_handle })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn run_to_completion(&mut self, mut child: Child) -> Result<()> {
|
||||||
|
let mut output_stream = OutputStream::from_child(&mut child)?;
|
||||||
|
|
||||||
|
let exit_status_handle = tokio::spawn(async move {
|
||||||
|
let status = child
|
||||||
|
.wait()
|
||||||
|
.await
|
||||||
|
.expect("nixos-rebuild encountered an error");
|
||||||
|
status
|
||||||
|
});
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let next_line = output_stream.next_line().await?;
|
||||||
|
match next_line {
|
||||||
|
OutputLine::Stdout(line) | OutputLine::Stderr(line) => {
|
||||||
|
self.handle_line(line)?;
|
||||||
|
}
|
||||||
|
OutputLine::Done => break,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let exit_status = exit_status_handle.await?;
|
||||||
|
println!("nixos-rebuild status was: {}", exit_status);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_line(&mut self, line: String) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OutputStream {
|
||||||
|
stdout: Option<Lines<BufReader<ChildStdout>>>,
|
||||||
|
stderr: Option<Lines<BufReader<ChildStderr>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutputStream {
|
||||||
|
pub(crate) fn from_child(child: &mut Child) -> Result<Self> {
|
||||||
|
let stdout = child
|
||||||
|
.stdout
|
||||||
|
.take()
|
||||||
|
.expect("child did not have a handle to stdout");
|
||||||
|
let stderr = child
|
||||||
|
.stderr
|
||||||
|
.take()
|
||||||
|
.expect("child did not have a handle to stderr");
|
||||||
|
let stdout = BufReader::new(stdout).lines();
|
||||||
|
let stderr = BufReader::new(stderr).lines();
|
||||||
|
Ok(OutputStream {
|
||||||
|
stdout: Some(stdout),
|
||||||
|
stderr: Some(stderr),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn next_line(&mut self) -> Result<OutputLine> {
|
||||||
|
loop {
|
||||||
|
match (&mut self.stdout, &mut self.stderr) {
|
||||||
|
(None, None) => {
|
||||||
|
return Ok(OutputLine::Done);
|
||||||
|
}
|
||||||
|
(None, Some(err)) => {
|
||||||
|
if let Some(line) = err.next_line().await? {
|
||||||
|
return Ok(OutputLine::Stderr(line));
|
||||||
|
} else {
|
||||||
|
return Ok(OutputLine::Done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(out), None) => {
|
||||||
|
if let Some(line) = out.next_line().await? {
|
||||||
|
return Ok(OutputLine::Stdout(line));
|
||||||
|
} else {
|
||||||
|
return Ok(OutputLine::Done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(out), Some(err)) => {
|
||||||
|
tokio::select! {
|
||||||
|
Ok(line) = out.next_line() => match line {
|
||||||
|
Some(line) => {
|
||||||
|
return Ok(OutputLine::Stdout(line));
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.stdout.take();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Ok(line) = err.next_line() => match line {
|
||||||
|
Some(line) => {
|
||||||
|
return Ok(OutputLine::Stderr(line));
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
self.stderr.take();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
else => {
|
||||||
|
return Ok(OutputLine::Done);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OutputLine {
|
||||||
|
Stdout(String),
|
||||||
|
Stderr(String),
|
||||||
|
Done,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user