| 614 | } |
| 615 | |
| 616 | pub(super) fn build_git_import_file_diffs( |
| 617 | change: &Change, |
| 618 | ) -> Option<(Vec<FileDiff>, DiffStats)> { |
| 619 | let diff_files_value = change |
| 620 | .unhashed |
| 621 | .as_ref()? |
| 622 | .get("git")? |
| 623 | .get("diff_lines")? |
| 624 | .clone(); |
| 625 | |
| 626 | let diff_files: Vec<GitMetadataDiffFile> = serde_json::from_value(diff_files_value).ok()?; |
| 627 | let mut file_diffs = Vec::new(); |
| 628 | let mut stats = DiffStats::new(); |
| 629 | |
| 630 | for entry in diff_files { |
| 631 | let mut insertions = 0usize; |
| 632 | let mut deletions = 0usize; |
| 633 | let mut hunk_lines = Vec::new(); |
| 634 | let mut old_start = None; |
| 635 | let mut new_start = None; |
| 636 | |
| 637 | for line in entry.lines { |
| 638 | let content = String::from_utf8_lossy(&line.content) |
| 639 | .trim_end_matches('\n') |
| 640 | .to_string(); |
| 641 | match line.origin { |
| 642 | '+' => { |
| 643 | let new_num = line.new_lineno.unwrap_or((insertions + 1) as u32) as usize; |
| 644 | if new_start.is_none() { |
| 645 | new_start = Some(new_num); |
| 646 | } |
| 647 | hunk_lines.push(HunkLine::added(content, new_num)); |
| 648 | insertions += 1; |
| 649 | } |
| 650 | '-' => { |
| 651 | let old_num = line.old_lineno.unwrap_or((deletions + 1) as u32) as usize; |
| 652 | if old_start.is_none() { |
| 653 | old_start = Some(old_num); |
| 654 | } |
| 655 | hunk_lines.push(HunkLine::removed(content, old_num)); |
| 656 | deletions += 1; |
| 657 | } |
| 658 | _ => {} |
| 659 | } |
| 660 | } |
| 661 | |
| 662 | if hunk_lines.is_empty() { |
| 663 | continue; |
| 664 | } |
| 665 | |
| 666 | let status = match (insertions > 0, deletions > 0) { |
| 667 | (true, false) => FileChangeStatus::Added, |
| 668 | (false, true) => FileChangeStatus::Deleted, |
| 669 | _ => FileChangeStatus::Modified, |
| 670 | }; |
| 671 | |
| 672 | let mut file_diff = match status { |
| 673 | FileChangeStatus::Added => FileDiff::added(&entry.path), |