summaryrefslogtreecommitdiffstats
path: root/pkgs/by-name/ro/rollup/src/main.rs
blob: 8285e7025c6bdc2c3372e362d2eb52ebab03fda1 (plain) (blame)
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(())
}