~matthiasbeyer/imag

84bb05035b51b05734eef44657cffd1fdb2950db — Matthias Beyer 1 year, 10 months ago 3e016d9
Fix: Ignore broken pipe when reporting ids

This fixes a bug where a broken pipe in Runtime::report_touched()
resulted in an Err(_) raised up to main() which then reported this.

But as report_touched() should ignore a broken pipe (because the program
will exit anyways shortly after the call), we can safely ignore this
error.

This also results in `ExitCode` removed from the function signature,
which pushes us forward to the removal of custom error-handling
implementations!

Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
1 files changed, 16 insertions(+), 11 deletions(-)

M lib/core/libimagrt/src/runtime.rs
M lib/core/libimagrt/src/runtime.rs => lib/core/libimagrt/src/runtime.rs +16 -11
@@ 24,7 24,6 @@ use std::process::exit;
use std::io::Stdin;
use std::io::StdoutLock;
use std::borrow::Borrow;
use std::result::Result as RResult;

pub use clap::App;
use clap::AppSettings;


@@ 41,10 40,8 @@ use crate::configuration::{fetch_config, override_config, InternalConfiguration}
use crate::logger::ImagLogger;
use crate::io::OutputProxy;

use libimagerror::exit::ExitCode;
use libimagerror::errors::ErrorMsg as EM;
use libimagerror::trace::*;
use libimagerror::io::ToExitCode;
use libimagstore::store::Store;
use libimagstore::storeid::StoreId;
use libimagutil::debug_result::DebugResult;


@@ 522,14 519,14 @@ impl<'a> Runtime<'a> {
            .map_err(Error::from)
    }

    pub fn report_touched(&self, id: &StoreId) -> RResult<(), ExitCode> {
    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)
        self.report_touched_id(id, &mut lock).map(|_| ())
    }

    pub fn report_all_touched<ID, I>(&self, ids: I) -> RResult<(), ExitCode>
    pub fn report_all_touched<ID, I>(&self, ids: I) -> Result<()>
        where ID: Borrow<StoreId> + Sized,
              I: Iterator<Item = ID>
    {


@@ 537,22 534,30 @@ impl<'a> Runtime<'a> {
        let mut lock = out.lock();

        for id in ids {
            self.report_touched_id(id.borrow(), &mut lock)?;
            if !self.report_touched_id(id.borrow(), &mut lock)? {
                break
            }
        }

        Ok(())
    }

    #[inline]
    fn report_touched_id(&self, id: &StoreId, output: &mut StdoutLock) -> RResult<(), ExitCode> {
    fn report_touched_id(&self, id: &StoreId, output: &mut StdoutLock) -> Result<bool> {
        use std::io::Write;

        if self.output_is_pipe() && !self.ignore_ids {
            trace!("Reporting: {} to {:?}", id, output);
            writeln!(output, "{}", id).to_exit_code()
        } else {
            Ok(())
            if let Err(e) = writeln!(output, "{}", id) {
                return if e.kind() == std::io::ErrorKind::BrokenPipe {
                    Ok(false)
                } else {
                    Err(failure::Error::from(e))
                }
            }
        }

        Ok(true)
    }
}