Replace exact content in a file without using line numbers. This method is safer for parallel operations as it doesn't rely on line numbers that might change when multiple agents modify the same file concurrently. Args: path(str): The relative file path to modif
(self,
path: str,
source: str = None,
target: str = None,
occurrence: int = 1)
| 477 | return f'Write file <{path}> failed, error: ' + str(e) |
| 478 | |
| 479 | async def replace_file_contents(self, |
| 480 | path: str, |
| 481 | source: str = None, |
| 482 | target: str = None, |
| 483 | occurrence: int = 1): |
| 484 | """Replace exact content in a file without using line numbers. |
| 485 | |
| 486 | This method is safer for parallel operations as it doesn't rely on line numbers |
| 487 | that might change when multiple agents modify the same file concurrently. |
| 488 | |
| 489 | Args: |
| 490 | path(str): The relative file path to modify |
| 491 | source(str): The exact content to find and replace (must match exactly including whitespace) |
| 492 | target(str): The new content to replace with |
| 493 | occurrence(int): Which occurrence to replace (1-based). Use -1 to replace all occurrences. |
| 494 | Default is 1 (first occurrence). |
| 495 | |
| 496 | Returns: |
| 497 | Success or error message. |
| 498 | """ |
| 499 | try: |
| 500 | if not source: |
| 501 | return f'Error: You MUST provide the `source` parameter to be replaced with the `target`, but got {source}.' |
| 502 | if target is None: |
| 503 | return f'Error: You MUST provide the `target` parameter to replace the `source`, but got {target}.' |
| 504 | target_path_real = self.get_real_path(path) |
| 505 | if target_path_real is None: |
| 506 | return f'<{path}> is out of the valid project path: {self.output_dir}' |
| 507 | |
| 508 | # Read file content |
| 509 | if not os.path.exists(target_path_real): |
| 510 | return f'Error: File <{path}> does not exist' |
| 511 | |
| 512 | with open(target_path_real, 'r', encoding='utf-8') as f: |
| 513 | file_content = f.read() |
| 514 | |
| 515 | # Check if source exists |
| 516 | if source not in file_content: |
| 517 | return ( |
| 518 | f'Error: Could not find the exact content to replace in <{path}>. ' |
| 519 | f'Make sure the content matches exactly including all whitespace.' |
| 520 | ) |
| 521 | |
| 522 | # Count occurrences |
| 523 | count = file_content.count(source) |
| 524 | |
| 525 | # Replace based on occurrence parameter |
| 526 | if occurrence == -1: |
| 527 | # Replace all occurrences |
| 528 | updated_content = file_content.replace(source, target) |
| 529 | operation_msg = f'Replaced all {count} occurrence(s)' |
| 530 | elif occurrence < 1: |
| 531 | return f'Error: occurrence must be >= 1 or -1 (for all), got {occurrence}' |
| 532 | elif occurrence > count: |
| 533 | return f'Error: occurrence {occurrence} exceeds total occurrences ({count}) of the content' |
| 534 | else: |
| 535 | # Replace specific occurrence |
| 536 | parts = file_content.split(source, occurrence) |
nothing calls this directly
no test coverage detected