chiark / gitweb /
apitest: Capture and return the output from otter(1)
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 3 May 2021 12:38:53 +0000 (13:38 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 3 May 2021 12:38:53 +0000 (13:38 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
apitest/apitest.rs
src/prelude.rs

index 187a87e47911e9ecc72c33ff77213f71fa11a8f5..421ce708d170af19e081fd2346b6acce8f5844b5 100644 (file)
@@ -632,13 +632,42 @@ _ = "error" # rocket
 #[error("wait status: {0}")]
 pub struct ExitStatusError(pub std::process::ExitStatus);
 
+pub struct OtterOutput {
+  output: Option<NamedTempFile>,
+}
+impl Deref for OtterOutput {
+  type Target = fs::File;
+  fn deref(&self) -> &fs::File { self.output.as_ref().unwrap().as_file() }
+}
+impl DerefMut for OtterOutput {
+  fn deref_mut(&mut self) -> &mut fs::File {
+    self.output.as_mut().unwrap().as_file_mut()
+  }
+}
+impl From<OtterOutput> for String {
+  fn from(mut oo: OtterOutput) -> String {
+    let mut s = String::new();
+    let mut o = oo.output.take().unwrap();
+    o.rewind().unwrap();
+    o.read_to_string(&mut s).unwrap();
+    s
+  }
+}
+impl Drop for OtterOutput {
+  fn drop(&mut self) {
+    if let Some(mut o) = self.output.take() {
+      io::copy(&mut o, &mut io::stdout()).expect("copy otter stdout");
+    }
+  }
+}
+
 impl DirSubst {
   pub fn specs_dir(&self) -> String {
     format!("{}/specs" , &self.src)
   }
 
   #[throws(AE)]
-  pub fn otter<'s,S>(&self, xargs: &'s [S])
+  pub fn otter<'s,S>(&self, xargs: &'s [S]) -> OtterOutput
   where &'s S: Into<String>
   {
     self.otter_prctx(&default(), xargs)?
@@ -646,6 +675,7 @@ impl DirSubst {
 
   #[throws(AE)]
   pub fn otter_prctx<'s,S>(&self, prctx: &PathResolveContext, xargs: &'s [S])
+                           -> OtterOutput
   where &'s S: Into<String>
   {
     let ds = self;
@@ -656,10 +686,14 @@ impl DirSubst {
     args.push("--spec-dir".to_owned()); args.push(prctx.resolve(&specs) );
     args.extend(xargs.iter().map(|s| s.into()));
     let dbg = format!("running {} {:?}", &exe, &args);
+    let mut output = NamedTempFile::new_in(
+      ds.subst("@abstmp@").unwrap()
+    ).unwrap();
     debug!("{}", &dbg);
     (||{
       let mut cmd = Command::new(&exe);
       cmd.args(&args);
+      cmd.stdout(output.as_file().try_clone().unwrap());
       let st = cmd
         .spawn().context("spawn")?
         .wait().context("wait")?;
@@ -670,6 +704,9 @@ impl DirSubst {
     })()
       .context(dbg)
       .context("run otter client")?;
+
+    output.rewind().unwrap();
+    OtterOutput { output: Some(output) }
   }
 
   #[throws(AE)]
index 223f6c88e1214c7210ba11ecb14ba6a9a488643c..177220af3c4a0e326389b0d1e36da90577e78f78 100644 (file)
@@ -95,6 +95,7 @@ pub use sha2::{Sha512, Sha512Trunc256};
 pub use slotmap::{dense::DenseSlotMap, SparseSecondaryMap, Key as _};
 pub use strum::{EnumString, EnumIter, EnumProperty};
 pub use strum::{IntoEnumIterator, IntoStaticStr};
+pub use tempfile::NamedTempFile;
 pub use thiserror::Error;
 pub use url::Url;
 pub use vecdeque_stableix::Deque as StableIndexVecDeque;