diff --git a/pkg/git/diff.go b/pkg/git/diff.go index 3fa0f5262..42e683b01 100644 --- a/pkg/git/diff.go +++ b/pkg/git/diff.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "regexp" "strconv" "strings" @@ -28,6 +29,8 @@ type FilePatch struct { Chunks Chunks } +var pathSplitterRegexp = regexp.MustCompile(`^(([^\.]+)\.([^\s]+))\s(.+)$`) + func Diff(rootDir, baseRef string) ([]FilePatch, error) { var result []FilePatch @@ -113,13 +116,13 @@ func parseDiff(scanner *linescanner.Scanner) ([]FilePatch, error) { } func parseDiffHeader(value string) (string, string, error) { - parts := strings.Split(value, " ") - fromPath, err := unquoteFilename(parts[2]) + parts := splitPath(value, 2, 4) + fromPath, err := unquoteFilename(parts[0]) if err != nil { return "", "", fmt.Errorf("error parsing header 'from' path: %w", err) } - toPath, err := unquoteFilename(parts[3]) + toPath, err := unquoteFilename(parts[1]) if err != nil { return "", "", fmt.Errorf("error parsing header 'to' path: %w", err) } @@ -127,6 +130,19 @@ func parseDiffHeader(value string) (string, string, error) { return fromPath, toPath, nil } +func splitPath(value string, offset int, expectedLen int) []string { + parts := strings.Split(value, " ") + if len(parts) == expectedLen { + return []string{parts[2], parts[3]} + } + + // parts may contain spaces + // TODO: how to handle spaces plus multi-fullstop filenames e.g "who would.do.this"? + valueWithoutOffset := strings.Join(parts[offset:], " ") + matches := pathSplitterRegexp.FindStringSubmatch(valueWithoutOffset) + return []string{matches[1], matches[4]} +} + func parseChunkHeader(value string) (Chunk, error) { parts := strings.Split(value, " ")