parseUnifiedDiff walks `git diff --unified=0` output and emits per-file FileDiff structures with 1-indexed line numbers.
(diff string)
| 123 | // parseUnifiedDiff walks `git diff --unified=0` output and emits per-file |
| 124 | // FileDiff structures with 1-indexed line numbers. |
| 125 | func parseUnifiedDiff(diff string) map[string]vcs.FileDiff { |
| 126 | out := make(map[string]vcs.FileDiff) |
| 127 | var currentPath string |
| 128 | var current vcs.FileDiff |
| 129 | var oldLine, newLine int |
| 130 | |
| 131 | flush := func() { |
| 132 | if currentPath == "" { |
| 133 | return |
| 134 | } |
| 135 | out[currentPath] = current |
| 136 | } |
| 137 | |
| 138 | lines := strings.Split(diff, "\n") |
| 139 | for _, line := range lines { |
| 140 | switch { |
| 141 | case strings.HasPrefix(line, "diff --git "): |
| 142 | flush() |
| 143 | currentPath = "" |
| 144 | current = vcs.FileDiff{} |
| 145 | // Path is the `b/...` side; pick it from the trailing token. |
| 146 | fields := strings.Fields(line) |
| 147 | if len(fields) >= 4 { |
| 148 | currentPath = strings.TrimPrefix(fields[3], "b/") |
| 149 | } |
| 150 | case strings.HasPrefix(line, "new file mode"): |
| 151 | current.IsNew = true |
| 152 | case strings.HasPrefix(line, "deleted file mode"): |
| 153 | current.IsDeleted = true |
| 154 | case strings.HasPrefix(line, "rename from"), strings.HasPrefix(line, "rename to"): |
| 155 | current.IsRenamed = true |
| 156 | case strings.HasPrefix(line, "@@"): |
| 157 | oldStart, _, newStart, _, ok := parseHunkHeader(line) |
| 158 | if !ok { |
| 159 | continue |
| 160 | } |
| 161 | oldLine = oldStart |
| 162 | newLine = newStart |
| 163 | case strings.HasPrefix(line, "+++"), strings.HasPrefix(line, "---"): |
| 164 | // File headers; ignore. |
| 165 | case strings.HasPrefix(line, "+"): |
| 166 | current.Additions = append(current.Additions, newLine) |
| 167 | newLine++ |
| 168 | case strings.HasPrefix(line, "-"): |
| 169 | current.Deletions = append(current.Deletions, oldLine) |
| 170 | oldLine++ |
| 171 | } |
| 172 | } |
| 173 | flush() |
| 174 | return out |
| 175 | } |
| 176 | |
| 177 | // parseHunkHeader parses a unified-diff hunk header of the form |
| 178 | // |