diesel_migration_test/
main.rs1use std::collections::BTreeMap;
5use std::fmt;
6
7use anyhow::Context;
8use camino::Utf8PathBuf;
9use clap::Parser;
10use console::{Style, style};
11use similar::{ChangeTag, TextDiff};
12
13#[derive(Parser, Debug)]
15#[command(version, about, long_about = None)]
16struct Args {
17 #[arg(long, env = "RESULT_PATH")]
18 result_path: Utf8PathBuf,
19
20 #[arg(long, env = "SCHEMAS_PATHS", value_delimiter = ';')]
21 schemas_paths: Vec<Utf8PathBuf>,
22
23 #[arg(long, env = "SCHEMAS_SHORT_PATHS", value_delimiter = ';')]
24 schemas_short_paths: Vec<Utf8PathBuf>,
25}
26
27struct Line(Option<usize>);
28
29impl fmt::Display for Line {
30 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31 match self.0 {
32 None => write!(f, " "),
33 Some(idx) => write!(f, "{:<4}", idx + 1),
34 }
35 }
36}
37
38fn main() -> anyhow::Result<()> {
39 let args = Args::parse();
40
41 let runfiles = runfiles::Runfiles::create().expect("failed to create runfiles");
42 let path_map = args
43 .schemas_paths
44 .iter()
45 .zip(args.schemas_short_paths.iter())
46 .collect::<BTreeMap<_, _>>();
47 let result_path = runfiles::rlocation!(&runfiles, args.result_path).expect("failed to get result path");
48
49 let results = std::fs::read_to_string(&result_path).context("read results")?;
50 let results: BTreeMap<Utf8PathBuf, String> = serde_json::from_str(&results).context("parse results")?;
51
52 let mut diff_found = false;
53 for (path, content) in results {
54 let actual_path = runfiles::rlocation!(&runfiles, path_map[&path]).expect("failed to get actual path");
55 let expected = std::fs::read_to_string(&actual_path).context("read expected")?;
56
57 if content != expected {
58 diff_found = true;
59 println!("Difference found in {}", path);
60 println!("{}", diff(&expected, &content));
61 }
62 }
63
64 if diff_found {
65 std::process::exit(1)
66 }
67
68 Ok(())
69}
70
71pub(crate) fn diff(old: &str, new: &str) -> String {
72 use std::fmt::Write;
73
74 let diff = TextDiff::from_lines(old, new);
75 let mut output = String::new();
76
77 for (idx, group) in diff.grouped_ops(3).iter().enumerate() {
78 if idx > 0 {
79 writeln!(&mut output, "{0:─^1$}┼{0:─^2$}", "─", 9, 120).unwrap();
80 }
81 for op in group {
82 for change in diff.iter_inline_changes(op) {
83 let (sign, s) = match change.tag() {
84 ChangeTag::Delete => ("-", Style::new().red()),
85 ChangeTag::Insert => ("+", Style::new().green()),
86 ChangeTag::Equal => (" ", Style::new().dim()),
87 };
88 write!(
89 &mut output,
90 "{}{} │{}",
91 style(Line(change.old_index())).dim(),
92 style(Line(change.new_index())).dim(),
93 s.apply_to(sign).bold(),
94 )
95 .unwrap();
96 for (_, value) in change.iter_strings_lossy() {
97 write!(&mut output, "{}", s.apply_to(value)).unwrap();
98 }
99 if change.missing_newline() {
100 writeln!(&mut output).unwrap();
101 }
102 }
103 }
104 }
105
106 output
107}