mod parser;
pub mod untracked;
pub use parser::parse;
pub fn parse_with_untracked(raw_diff: &str) -> (DiffData, String) {
let untracked_paths = untracked::discover_untracked_files();
parse_with_untracked_paths(raw_diff, &untracked_paths)
}
pub fn parse_with_untracked_paths(raw_diff: &str, untracked_paths: &[String]) -> (DiffData, String) {
if untracked_paths.is_empty() {
let data = parse(raw_diff);
return (data, raw_diff.to_string());
}
let (untracked_diff, binary_untracked) =
untracked::generate_untracked_diff(untracked_paths);
let combined = if untracked_diff.is_empty() {
raw_diff.to_string()
} else {
format!("{raw_diff}{untracked_diff}")
};
let mut data = parse(&combined);
let untracked_set: std::collections::HashSet<&str> =
untracked_paths.iter().map(|s| s.as_str()).collect();
for file in &mut data.files {
let path = file.target_file.trim_start_matches("b/");
if untracked_set.contains(path) {
file.is_untracked = true;
}
}
data.binary_files.extend(binary_untracked);
(data, combined)
}
#[derive(Debug, Clone)]
pub struct DiffData {
pub files: Vec<DiffFile>,
pub binary_files: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct DiffFile {
pub source_file: String,
pub target_file: String,
pub is_rename: bool,
pub is_untracked: bool,
pub hunks: Vec<Hunk>,
pub added_count: usize,
pub removed_count: usize,
}
#[derive(Debug, Clone)]
pub struct Hunk {
pub header: String,
pub source_start: usize,
pub target_start: usize,
pub lines: Vec<DiffLine>,
}
#[derive(Debug, Clone)]
pub struct DiffLine {
pub line_type: LineType,
pub content: String,
pub inline_segments: Option<Vec<DiffSegment>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum LineType {
Added,
Removed,
Context,
}
#[derive(Debug, Clone)]
pub struct DiffSegment {
pub tag: SegmentTag,
pub text: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SegmentTag {
Equal,
Changed,
}