#[cfg(feature = "cli")]
use clap::Parser;
#[cfg(feature = "cli")]
use anyhow::{anyhow, Result};
#[cfg(feature = "cli")]
use colored::Colorize;
#[cfg(feature = "cli")]
use difference::{Changeset, Difference};
use corg::{Corg, CorgError, CorgRunner};
use std::io::Write;
use std::path::PathBuf;
#[derive(Debug)]
#[cfg_attr(feature = "cli", derive(Parser))]
#[cfg_attr(feature = "cli", clap(author, version, about))]
pub struct Cli {
pub input: PathBuf,
#[cfg_attr(feature = "cli", clap(short, long))]
pub output: Option<PathBuf>,
#[cfg_attr(feature = "cli", clap(short, long))]
pub replace: bool,
#[cfg_attr(feature = "cli", clap(short, long))]
pub delete_blocks: bool,
#[cfg_attr(feature = "cli", clap(short = 'e'))]
pub warn_if_no_blocks: bool,
#[cfg_attr(feature = "cli", clap(short = 'x', long))]
pub omit_output: bool,
#[cfg_attr(feature = "cli", clap(long))]
pub check: bool,
#[cfg_attr(feature = "cli", clap(long, short))]
pub checksum: bool,
#[cfg_attr(feature = "cli", clap(long, parse(try_from_str = parse_markers)))]
pub markers: Option<(String, String, String)>,
}
pub fn parse_markers(s: &str) -> Result<(String, String, String)> {
let mut iter = s.splitn(3, ' ');
let start_block = iter.next();
let end_block = iter.next();
let end_output = iter.next();
match (start_block, end_block, end_output) {
(Some(start_block), Some(end_block), Some(end_output)) => Ok((
start_block.to_string(),
end_block.to_string(),
end_output.to_string(),
)),
_ => Err(anyhow!("Invalid marker: {}", s)),
}
}
fn main() -> Result<(), CorgError> {
let cli = Cli::parse();
let mut options = Corg::default()
.delete_blocks(cli.delete_blocks)
.warn_if_no_blocks(cli.warn_if_no_blocks)
.omit_output(cli.omit_output)
.check_only(cli.check);
if cfg!(feature = "cli") {
options = options.checksum(cli.checksum);
}
if let Some(markers) = cli.markers {
options = options.override_markers(markers.0, markers.1, markers.2)
}
let corg_runner = CorgRunner::default()
.input(cli.input)
.replace_input(cli.replace)
.output(cli.output);
let exit_code = match corg_runner.execute(&options) {
Ok(_) => 0,
Err(e) => {
eprintln!("{}", e.to_string().red());
match e {
CorgError::NoBlocksDetected => 0,
CorgError::IOError(_) => 1,
CorgError::BlockExecutionError(_) => 3,
CorgError::CheckFailed((content, output)) => {
let Changeset { diffs, .. } = Changeset::new(&content, &output, "");
let mut out = std::io::stderr();
for c in &diffs {
let colored = match *c {
Difference::Same(ref z) => z.white(),
Difference::Rem(ref z) => z.on_red(),
Difference::Add(ref z) => z.on_green(),
};
write!(out, "{}", colored)?;
}
5
}
CorgError::ChecksumMismatch(_) => 7,
}
}
};
std::process::exit(exit_code);
}