Compute (start, old_count, new_lines) replacement tuples.
(
original_lines: List[str],
file_path: str,
chunks: List[UpdateChunk],
)
| 680 | return PatchResult(hunks=hunks) |
| 681 | |
| 682 | def _compute_replacements( |
| 683 | original_lines: List[str], |
| 684 | file_path: str, |
| 685 | chunks: List[UpdateChunk], |
| 686 | ) -> List[Tuple[int, int, List[str]]]: |
| 687 | """Compute (start, old_count, new_lines) replacement tuples.""" |
| 688 | replacements: List[Tuple[int, int, List[str]]] = [] |
| 689 | line_index = 0 |
| 690 | |
| 691 | for chunk in chunks: |
| 692 | # Context-based seeking |
| 693 | if chunk.change_context: |
| 694 | ctx_idx = seek_sequence( |
| 695 | original_lines, [chunk.change_context], line_index, |
| 696 | ) |
| 697 | if ctx_idx == -1: |
| 698 | raise PatchError( |
| 699 | f"Cannot locate context anchor " |
| 700 | f"'{chunk.change_context}' in {file_path}" |
| 701 | ) |
| 702 | line_index = ctx_idx |
| 703 | |
| 704 | # Pure addition (no old lines to match) |
| 705 | if not chunk.old_lines: |
| 706 | if original_lines and original_lines[-1] == "": |
| 707 | insert_idx = len(original_lines) - 1 |
| 708 | else: |
| 709 | insert_idx = len(original_lines) |
| 710 | replacements.append((insert_idx, 0, chunk.new_lines)) |
| 711 | continue |
| 712 | |
| 713 | pattern = list(chunk.old_lines) |
| 714 | new_slice = list(chunk.new_lines) |
| 715 | found = seek_sequence( |
| 716 | original_lines, pattern, line_index, chunk.is_end_of_file, |
| 717 | ) |
| 718 | |
| 719 | # Retry without trailing empty line |
| 720 | if found == -1 and pattern and pattern[-1] == "": |
| 721 | pattern = pattern[:-1] |
| 722 | if new_slice and new_slice[-1] == "": |
| 723 | new_slice = new_slice[:-1] |
| 724 | found = seek_sequence( |
| 725 | original_lines, pattern, line_index, chunk.is_end_of_file, |
| 726 | ) |
| 727 | |
| 728 | if found != -1: |
| 729 | replacements.append((found, len(pattern), new_slice)) |
| 730 | line_index = found + len(pattern) |
| 731 | else: |
| 732 | raise PatchError( |
| 733 | f"Cannot find expected lines in {file_path}:\n" |
| 734 | + "\n".join(chunk.old_lines) |
| 735 | ) |
| 736 | |
| 737 | replacements.sort(key=lambda x: x[0]) |
| 738 | return replacements |
| 739 |
no test coverage detected