Split a git diff into separate diffs for each file. Args: diff: Git diff text containing potentially multiple files Returns: Dictionary mapping file paths to their individual diff content
(diff: str)
| 108 | |
| 109 | |
| 110 | def split_git_diff_by_files(diff: str) -> dict[str, str]: |
| 111 | """Split a git diff into separate diffs for each file. |
| 112 | |
| 113 | Args: |
| 114 | diff: Git diff text containing potentially multiple files |
| 115 | |
| 116 | Returns: |
| 117 | Dictionary mapping file paths to their individual diff content |
| 118 | """ |
| 119 | if not diff or not diff.strip(): |
| 120 | return {} |
| 121 | |
| 122 | lines = diff.splitlines(keepends=True) |
| 123 | files_diffs = {} |
| 124 | current_file = None |
| 125 | current_block = [] |
| 126 | |
| 127 | # Store any prelude (content before first diff --git line) |
| 128 | prelude = [] |
| 129 | found_first_diff = False |
| 130 | |
| 131 | for line in lines: |
| 132 | if line.startswith("diff --git "): |
| 133 | # Save previous file's diff if we have one |
| 134 | if current_file and current_block: |
| 135 | files_diffs[current_file] = "".join(prelude + current_block) |
| 136 | current_block = [] |
| 137 | |
| 138 | # Extract file path from the diff line |
| 139 | # Format: "diff --git a/path/to/file b/path/to/file" |
| 140 | match = re.match(r"diff --git a/(.+) b/(.+)", line) |
| 141 | if match: |
| 142 | current_file = match.group(2) # Use the "b/" path (after changes) |
| 143 | else: |
| 144 | # Fallback parsing |
| 145 | parts = line.strip().split() |
| 146 | if len(parts) >= 4: |
| 147 | current_file = parts[3][2:] if parts[3].startswith("b/") else parts[3] |
| 148 | else: |
| 149 | current_file = "unknown_file" |
| 150 | |
| 151 | current_block.append(line) |
| 152 | found_first_diff = True |
| 153 | else: |
| 154 | if found_first_diff and current_file: |
| 155 | current_block.append(line) |
| 156 | else: |
| 157 | # This is prelude content before any diff |
| 158 | prelude.append(line) |
| 159 | |
| 160 | # Handle the last file |
| 161 | if current_file and current_block: |
| 162 | files_diffs[current_file] = "".join(prelude + current_block) |
| 163 | |
| 164 | return files_diffs |