(
base_path: &Path,
file_patch: &FilePatch,
)
| 551 | } |
| 552 | |
| 553 | async fn process_file_patch( |
| 554 | base_path: &Path, |
| 555 | file_patch: &FilePatch, |
| 556 | ) -> Result<FileChange, ToolError> { |
| 557 | let file_path = base_path.join(&file_patch.path); |
| 558 | let relative_path = file_patch.path.clone(); |
| 559 | |
| 560 | match file_patch.operation { |
| 561 | PatchOperation::Add => { |
| 562 | let new_content = file_patch |
| 563 | .hunks |
| 564 | .iter() |
| 565 | .flat_map(|h| h.lines.iter()) |
| 566 | .filter_map(|l| match l { |
| 567 | PatchLine::Add(s) => Some(s.clone()), |
| 568 | _ => None, |
| 569 | }) |
| 570 | .collect::<Vec<_>>() |
| 571 | .join("\n"); |
| 572 | |
| 573 | let diff = format!( |
| 574 | "--- /dev/null\n+++ b/{}\n{}", |
| 575 | relative_path, |
| 576 | file_patch |
| 577 | .hunks |
| 578 | .iter() |
| 579 | .flat_map(|h| h.lines.iter()) |
| 580 | .map(|l| match l { |
| 581 | PatchLine::Add(s) => format!("+{}", s), |
| 582 | _ => String::new(), |
| 583 | }) |
| 584 | .collect::<Vec<_>>() |
| 585 | .join("\n") |
| 586 | ); |
| 587 | |
| 588 | Ok(FileChange { |
| 589 | relative_path, |
| 590 | operation: PatchOperation::Add, |
| 591 | old_content: String::new(), |
| 592 | new_content: new_content + "\n", |
| 593 | diff, |
| 594 | }) |
| 595 | } |
| 596 | PatchOperation::Update | PatchOperation::Move { .. } => { |
| 597 | let old_content = tokio::fs::read_to_string(&file_path) |
| 598 | .await |
| 599 | .map_err(|e| ToolError::ExecutionError(format!("Failed to read file: {}", e)))?; |
| 600 | |
| 601 | let new_content = apply_hunks(&old_content, &file_patch.hunks)?; |
| 602 | |
| 603 | let diff = generate_diff(&relative_path, &old_content, &new_content); |
| 604 | |
| 605 | Ok(FileChange { |
| 606 | relative_path, |
| 607 | operation: file_patch.operation.clone(), |
| 608 | old_content, |
| 609 | new_content, |
| 610 | diff, |
no test coverage detected