use std::{
fmt::Write,
fs::File,
io::{stdout, BufRead, Write as _},
path::PathBuf,
process::{Command, Stdio},
};
use clap::Parser;
#[derive(Parser, Debug)]
struct Args {
file: PathBuf,
#[clap(long)]
open: bool,
}
fn main() {
let args = Args::parse();
let file = std::fs::canonicalize(args.file).expect("Could not canonicalize file path.");
let log = Command::new("pijul")
.arg("log")
.arg("--hash-only")
.current_dir(&file)
.output()
.expect("`pijul log` failed");
let mut dot = String::new();
writeln!(dot, "strict digraph {{").unwrap();
for line in log.stdout.lines() {
let change = line.unwrap();
let info = Command::new("pijul")
.arg("change")
.arg(&change)
.current_dir(&file)
.output()
.expect("`pijul log` failed");
writeln!(dot, r#" "{}" [label="{}"]"#, change, &change[0..4]).unwrap();
for dep in info
.stdout
.lines()
.skip_while(|line| !line.as_ref().unwrap().starts_with("# Dependencies"))
.skip(1)
{
if let Some(dep) = &dep.unwrap().get(4..) {
writeln!(dot, r#" "{}" -> "{}";"#, dep, change).unwrap();
} else {
break;
}
}
}
writeln!(dot, "}}").unwrap();
let mut graphviz = Command::new("dot")
.arg("-Tsvg")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("`dot` failed.");
graphviz
.stdin
.take()
.unwrap()
.write_all(dot.as_bytes())
.unwrap();
let out = graphviz.wait_with_output().unwrap().stdout;
if args.open {
File::create("/tmp/picture.svg")
.unwrap()
.write_all(&out)
.unwrap();
Command::new("firefox")
.arg("/tmp/picture.svg")
.spawn()
.unwrap()
.wait()
.unwrap();
} else {
stdout().lock().write_all(&out).unwrap();
}
}