Skip to main content

aether_evals/evals/
diff.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub struct GitDiff {
5    pub diff: String,
6    pub stats: DiffStats,
7}
8
9impl GitDiff {
10    pub(crate) fn new(diff: String) -> Self {
11        Self { stats: DiffStats::from_diff(&diff), diff }
12    }
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct DiffStats {
17    pub files_changed: usize,
18    pub lines_added: usize,
19    pub lines_removed: usize,
20}
21
22impl DiffStats {
23    pub fn from_diff(diff: &str) -> Self {
24        let mut lines_added = 0;
25        let mut lines_removed = 0;
26        let mut files_changed = 0;
27
28        for line in diff.lines() {
29            if line.starts_with("diff --git") {
30                files_changed += 1;
31            } else if line.starts_with('+') && !line.starts_with("+++") {
32                lines_added += 1;
33            } else if line.starts_with('-') && !line.starts_with("---") {
34                lines_removed += 1;
35            }
36        }
37
38        Self { files_changed, lines_added, lines_removed }
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn diff_stats_from_diff_counts_files_and_changed_lines() {
48        let diff = "diff --git a/a.txt b/a.txt\n--- a/a.txt\n+++ b/a.txt\n@@\n-old\n+new\ndiff --git a/b.txt b/b.txt\n+++ b/b.txt\n+added\n";
49
50        let stats = DiffStats::from_diff(diff);
51
52        assert_eq!(stats.files_changed, 2);
53        assert_eq!(stats.lines_added, 2);
54        assert_eq!(stats.lines_removed, 1);
55    }
56}