1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
use core::fmt;
use std::{path::PathBuf, process::Command};
use anyhow::{Context, Result};
use clap::Parser;
#[derive(Parser)]
struct Cli {
/// The file to pull the patch to rollup from.
patch_file: PathBuf,
}
struct Diff {
files: Vec<FileDiff>,
}
struct FileDiff {
from: PathBuf,
to: PathBuf,
diff: String,
index: String,
}
impl fmt::Display for FileDiff {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(
f,
"diff --git a/{} b/{}",
self.from.display(),
self.to.display()
)?;
writeln!(f, "--- a/{}", self.from.display())?;
writeln!(f, "+++ b/{}", self.to.display())?;
writeln!(f, "index {}", self.index)?;
writeln!(f, "{}", self.diff)?;
Ok(())
}
}
macro_rules! take {
($line:expr, $prefix:literal) => {
$line.strip_prefix($prefix).unwrap().trim()
};
}
fn main() -> Result<()> {
let args = Cli::parse();
let data = Command::new("filterdiff")
.arg(&args.patch_file)
.output()
.context("Failed to run `filterdiff` for patch analysis")?;
let stdout = String::from_utf8(data.stdout).unwrap();
let mut diff = Diff { files: vec![] };
let mut file_diff_from = None;
let mut file_diff_to = None;
let mut file_diff_diff: Option<String> = None;
let mut file_diff_index: Option<String> = None;
for (idx, line) in stdout.lines().enumerate() {
eprintln!("{}", line);
if line.starts_with("---") {
file_diff_from = Some(PathBuf::from(take!(line, "--- a/")));
} else if line.starts_with("+++") {
file_diff_to = Some(PathBuf::from(take!(line, "+++ b/")));
} else if line.starts_with("index") {
file_diff_index = Some(take!(line, "index").to_owned());
} else if line.starts_with("diff --git") {
if idx != 0 {
diff.files.push(FileDiff {
from: file_diff_from.take().unwrap(),
to: file_diff_to.take().unwrap(),
diff: file_diff_diff.take().unwrap(),
index: file_diff_index.take().unwrap(),
});
}
} else {
match file_diff_diff.as_mut() {
Some(str) => {
str.push_str(line);
str.push('\n');
}
None => {
let mut base = line.to_owned();
base.push('\n');
file_diff_diff = Some(base);
}
}
}
}
diff.files.push(FileDiff {
from: file_diff_from.unwrap(),
to: file_diff_to.unwrap(),
diff: file_diff_diff.unwrap(),
index: file_diff_index.unwrap(),
});
for file in diff.files {
eprintln!("{}", file)
}
Ok(())
}
|