Phase 2: Write changes sequentially with hash chaining.
(
&self,
repo: &mut Repository,
commits: &[ParsedCommit],
line_index: &mut ImportLineIndex,
)
| 2495 | |
| 2496 | /// Phase 2: Write changes sequentially with hash chaining. |
| 2497 | fn phase2_write( |
| 2498 | &self, |
| 2499 | repo: &mut Repository, |
| 2500 | commits: &[ParsedCommit], |
| 2501 | line_index: &mut ImportLineIndex, |
| 2502 | ) -> CliResult<(WriteStats, Vec<ImportedCommitInfo>)> { |
| 2503 | let mut stats = WriteStats::default(); |
| 2504 | let mut imported_commits = Vec::new(); |
| 2505 | let total = commits.len(); |
| 2506 | let phase2_start = Instant::now(); |
| 2507 | let mut batch_start = Instant::now(); |
| 2508 | |
| 2509 | for (idx, parsed) in commits.iter().enumerate() { |
| 2510 | // Progress reporting with per-batch timing |
| 2511 | if total > 100 && idx % 100 == 0 { |
| 2512 | if idx == 0 { |
| 2513 | print_info(&format!(" Writing {}/{}...", idx, total)); |
| 2514 | } else { |
| 2515 | let batch_elapsed = batch_start.elapsed(); |
| 2516 | let total_elapsed = phase2_start.elapsed(); |
| 2517 | let avg_per_commit = total_elapsed.as_secs_f64() / idx as f64; |
| 2518 | print_info(&format!( |
| 2519 | " Writing {}/{}... (last 100: {:.2}s, avg: {:.1}ms/commit)", |
| 2520 | idx, |
| 2521 | total, |
| 2522 | batch_elapsed.as_secs_f64(), |
| 2523 | avg_per_commit * 1000.0, |
| 2524 | )); |
| 2525 | } |
| 2526 | batch_start = Instant::now(); |
| 2527 | } |
| 2528 | |
| 2529 | // Write the change |
| 2530 | match self.write_commit(repo, parsed, line_index) { |
| 2531 | Ok(info) => { |
| 2532 | if parsed.is_empty { |
| 2533 | stats.empty_commits += 1; |
| 2534 | } else if parsed.is_merge { |
| 2535 | stats.merge_commits += 1; |
| 2536 | } else { |
| 2537 | stats.changes_written += 1; |
| 2538 | } |
| 2539 | stats.files_processed += parsed.files.len(); |
| 2540 | imported_commits.push(info); |
| 2541 | } |
| 2542 | Err(e) => { |
| 2543 | print_warning(&format!("Failed to write {}: {}", parsed.short_sha, e)); |
| 2544 | } |
| 2545 | } |
| 2546 | } |
| 2547 | |
| 2548 | // Populate the file index for all files written during this batch. |
| 2549 | // This lets `atomic status` compare file metadata (stat + content hash) |
| 2550 | // instead of reconstructing graph content for every file — reducing |
| 2551 | // post-import status from O(files × graph_traversal) to O(files × stat). |
| 2552 | use atomic_core::types::Hash; |
| 2553 | let repo_root = repo.root().to_path_buf(); |
| 2554 | let mut index_entries: Vec<(String, i64, u32, u64, Hash)> = Vec::new(); |
no test coverage detected