sync_readme_test_runner/
main.rs1use std::fmt;
5
6use anyhow::Context;
7use camino::Utf8PathBuf;
8use clap::Parser;
9use console::{Style, style};
10use similar::{ChangeTag, TextDiff};
11
12#[derive(Parser, Debug)]
14#[command(version, about, long_about = None)]
15struct Args {
16 #[arg(long, env = "RENDER_OUTPUT_PATH")]
17 render_output: Utf8PathBuf,
18}
19
20struct Line(Option<usize>);
21
22impl fmt::Display for Line {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 match self.0 {
25 None => write!(f, " "),
26 Some(idx) => write!(f, "{:<4}", idx + 1),
27 }
28 }
29}
30
31fn main() -> anyhow::Result<()> {
32 let args = Args::parse();
33
34 let render_output = std::fs::read_to_string(&args.render_output).context("read results")?;
35 let render_output: sync_readme_common::SyncReadmeRenderOutput =
36 serde_json::from_str(&render_output).context("parse results")?;
37 if render_output.rendered == render_output.source {
38 println!("readme matches render");
39 return Ok(());
40 }
41
42 println!("Difference found in {}", render_output.path);
43
44 println!("{}", diff(&render_output.source, &render_output.rendered));
45
46 std::process::exit(1)
47}
48
49pub(crate) fn diff(old: &str, new: &str) -> String {
50 use std::fmt::Write;
51
52 let diff = TextDiff::from_lines(old, new);
53 let mut output = String::new();
54
55 for (idx, group) in diff.grouped_ops(3).iter().enumerate() {
56 if idx > 0 {
57 writeln!(&mut output, "{0:─^1$}┼{0:─^2$}", "─", 9, 120).unwrap();
58 }
59 for op in group {
60 for change in diff.iter_inline_changes(op) {
61 let (sign, s) = match change.tag() {
62 ChangeTag::Delete => ("-", Style::new().red()),
63 ChangeTag::Insert => ("+", Style::new().green()),
64 ChangeTag::Equal => (" ", Style::new().dim()),
65 };
66 write!(
67 &mut output,
68 "{}{} │{}",
69 style(Line(change.old_index())).dim(),
70 style(Line(change.new_index())).dim(),
71 s.apply_to(sign).bold(),
72 )
73 .unwrap();
74 for (_, value) in change.iter_strings_lossy() {
75 write!(&mut output, "{}", s.apply_to(value)).unwrap();
76 }
77 if change.missing_newline() {
78 writeln!(&mut output).unwrap();
79 }
80 }
81 }
82 }
83
84 output
85}