From db4e83f18f032b531b09e59f75d857541cdea919 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Thu, 27 Sep 2018 14:19:55 +0200 Subject: [PATCH] Implement ID reporting This patch adds the id reporting feature to libimagrt::runtime::Runtime, where processed ("touched") ids can be reported to the Runtime and then get printed to stdout if stdout is a pipe. Other output is automatically redirected to stderr if stdout is a pipe now. --- lib/core/libimagrt/src/runtime.rs | 54 +++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/core/libimagrt/src/runtime.rs b/lib/core/libimagrt/src/runtime.rs index 83876ec9..e00a93f6 100644 --- a/lib/core/libimagrt/src/runtime.rs +++ b/lib/core/libimagrt/src/runtime.rs @@ -23,6 +23,8 @@ use std::env; use std::process::exit; use std::io::Stdin; use std::sync::Arc; +use std::io::StdoutLock; +use std::borrow::Borrow; pub use clap::App; use clap::AppSettings; @@ -42,9 +44,11 @@ use io::OutputProxy; use libimagerror::errors::ErrorMsg as EM; use libimagerror::trace::*; use libimagstore::store::Store; +use libimagstore::storeid::StoreId; use libimagstore::file_abstraction::InMemoryFileAbstraction; use libimagutil::debug_result::DebugResult; use spec::CliSpec; +use atty; /// The Runtime object /// @@ -55,6 +59,9 @@ pub struct Runtime<'a> { configuration: Option, cli_matches: ArgMatches<'a>, store: Store, + + has_output_pipe: bool, + has_input_pipe: bool, } impl<'a> Runtime<'a> { @@ -142,6 +149,9 @@ impl<'a> Runtime<'a> { configuration: config, rtp: rtp, store: store, + + has_output_pipe: !atty::is(atty::Stream::Stdout), + has_input_pipe: !atty::is(atty::Stream::Stdin), }) .context(err_msg("Cannot instantiate runtime")) .map_err(Error::from) @@ -415,7 +425,11 @@ impl<'a> Runtime<'a> { } pub fn stdout(&self) -> OutputProxy { - OutputProxy::Out(::std::io::stdout()) + if self.has_output_pipe { + OutputProxy::Err(::std::io::stderr()) + } else { + OutputProxy::Out(::std::io::stdout()) + } } pub fn stderr(&self) -> OutputProxy { @@ -423,7 +437,11 @@ impl<'a> Runtime<'a> { } pub fn stdin(&self) -> Option { - Some(::std::io::stdin()) + if self.has_input_pipe { + None + } else { + Some(::std::io::stdin()) + } } /// Helper for handling subcommands which are not available. @@ -504,6 +522,38 @@ impl<'a> Runtime<'a> { .context(EM::IO) .map_err(Error::from) } + + pub fn report_touched(&self, id: &StoreId) -> Result<()> { + let out = ::std::io::stdout(); + let mut lock = out.lock(); + + self.report_touched_id(id, &mut lock) + } + + pub fn report_all_touched(&self, ids: I) -> Result<()> + where ID: Borrow + Sized, + I: Iterator + { + let out = ::std::io::stdout(); + let mut lock = out.lock(); + + for id in ids { + self.report_touched_id(id.borrow(), &mut lock)?; + } + + Ok(()) + } + + #[inline] + fn report_touched_id(&self, id: &StoreId, output: &mut StdoutLock) -> Result<()> { + use std::io::Write; + + if self.has_output_pipe { + writeln!(output, "{}", id)?; + } + + Ok(()) + } } /// Exported for the `imag` command, you probably do not want to use that.