| 314 | } |
| 315 | |
| 316 | pub(super) fn build_git_import_file_diffs( |
| 317 | change: &Change, |
| 318 | ) -> Option<(Vec<FileDiff>, DiffStats)> { |
| 319 | let diff_files_value = change |
| 320 | .unhashed |
| 321 | .as_ref()? |
| 322 | .get("git")? |
| 323 | .get("diff_lines")? |
| 324 | .clone(); |
| 325 | |
| 326 | let diff_files: Vec<GitMetadataDiffFile> = serde_json::from_value(diff_files_value).ok()?; |
| 327 | let mut file_diffs = Vec::new(); |
| 328 | let mut stats = DiffStats::new(); |
| 329 | |
| 330 | for entry in diff_files { |
| 331 | let mut insertions = 0usize; |
| 332 | let mut deletions = 0usize; |
| 333 | let mut hunk_lines = Vec::new(); |
| 334 | let mut old_start = None; |
| 335 | let mut new_start = None; |
| 336 | |
| 337 | for line in entry.lines { |
| 338 | let content = String::from_utf8_lossy(&line.content) |
| 339 | .trim_end_matches('\n') |
| 340 | .to_string(); |
| 341 | match line.origin { |
| 342 | '+' => { |
| 343 | let new_num = line.new_lineno.unwrap_or((insertions + 1) as u32) as usize; |
| 344 | if new_start.is_none() { |
| 345 | new_start = Some(new_num); |
| 346 | } |
| 347 | hunk_lines.push(HunkLine::added(content, new_num)); |
| 348 | insertions += 1; |
| 349 | } |
| 350 | '-' => { |
| 351 | let old_num = line.old_lineno.unwrap_or((deletions + 1) as u32) as usize; |
| 352 | if old_start.is_none() { |
| 353 | old_start = Some(old_num); |
| 354 | } |
| 355 | hunk_lines.push(HunkLine::removed(content, old_num)); |
| 356 | deletions += 1; |
| 357 | } |
| 358 | _ => {} |
| 359 | } |
| 360 | } |
| 361 | |
| 362 | if hunk_lines.is_empty() { |
| 363 | continue; |
| 364 | } |
| 365 | |
| 366 | let status = match (insertions > 0, deletions > 0) { |
| 367 | (true, false) => FileChangeStatus::Added, |
| 368 | (false, true) => FileChangeStatus::Deleted, |
| 369 | _ => FileChangeStatus::Modified, |
| 370 | }; |
| 371 | |
| 372 | let mut file_diff = match status { |
| 373 | FileChangeStatus::Added => FileDiff::added(&entry.path), |