mod atomic;
mod cli;
mod config;
mod files;
mod git;
mod interactive;
mod lsp;
mod output;
mod plugin;
mod values;
use std::{
io::{self, Write},
process::ExitCode,
};
fn output_pipe_closed(error: &anyhow::Error) -> bool {
error
.chain()
.any(|cause| cause.downcast_ref::<output::OutputPipeClosed>().is_some())
}
fn main() -> ExitCode {
match cli::run() {
Ok(code) => ExitCode::from(code),
Err(error) if output_pipe_closed(&error) => ExitCode::SUCCESS,
Err(error) => {
let message = output::sanitize_message(&format!("{error:#}"));
let _ = writeln!(io::stderr(), "ocomment: {message}");
ExitCode::from(2)
}
}
}
#[cfg(test)]
mod tests {
use super::{output::OutputPipeClosed, output_pipe_closed};
use anyhow::{Context, Result};
use std::io::{Error, ErrorKind};
#[test]
fn a_tagged_output_pipe_is_recognized_through_its_context() {
let error = Result::<()>::Err(anyhow::Error::new(OutputPipeClosed))
.context("cannot write standard output")
.context("check failed")
.unwrap_err();
assert!(output_pipe_closed(&error));
}
#[test]
fn an_untagged_broken_pipe_is_not_an_output_pipe_closure() {
let error = Result::<()>::Err(Error::from(ErrorKind::BrokenPipe).into())
.context("cannot write the rewritten blob to git hash-object")
.context("fix failed")
.unwrap_err();
assert!(!output_pipe_closed(&error));
}
#[test]
fn another_io_failure_is_not_an_output_pipe_closure() {
let error = Result::<()>::Err(Error::from(ErrorKind::StorageFull).into())
.context("cannot write standard output")
.unwrap_err();
assert!(!output_pipe_closed(&error));
}
#[test]
fn an_error_carrying_no_io_failure_is_not_an_output_pipe_closure() {
assert!(!output_pipe_closed(&anyhow::anyhow!(
"plugin `x` is not locked"
)));
}
}