diff --git a/diff/parse.go b/diff/parse.go index b73e230..ca947cf 100644 --- a/diff/parse.go +++ b/diff/parse.go @@ -466,7 +466,7 @@ func parseDiffGitArgs(diffArgs string) (string, string, bool) { return first, second, true } // If the names don't have the a/ and b/ prefixes and they're equal, proceed. - if !(first[:2] == "a/" && second[:2] == "b/") && first == second { + if !(strings.HasPrefix(first, "a/") && strings.HasPrefix(second, "b/")) && first == second { return first, second, true } } diff --git a/diff/parse_test.go b/diff/parse_test.go index ad00c2f..4bf302b 100644 --- a/diff/parse_test.go +++ b/diff/parse_test.go @@ -91,3 +91,27 @@ func TestParseDiffGitArgs_Unsuccessful(t *testing.T) { } } } + +// Short, space-heavy args reach the ambiguous unquoted-with-spaces branch with a +// filename shorter than the "a/"/"b/" prefixes it is compared against. The syntax +// is valid but no filename can be extracted, so the function must return +// ("", "", true) rather than panicking on the prefix slice. +func TestParseDiffGitArgs_ShortAmbiguous(t *testing.T) { + for _, input := range []string{`x `, `a `, `ab `} { + first, second, success := parseDiffGitArgs(input) + if !success || first != "" || second != "" { + t.Errorf("`diff --git %s`: expected (\"\", \"\", true), got (%q, %q, %v)", input, first, second, success) + } + } +} + +func TestParseFileDiff_ShortAmbiguousDiffGitArgs(t *testing.T) { + input := []byte("diff --git x \ndeleted file mode 100644\nindex e69de29..0000000\n") + fileDiff, err := ParseFileDiff(input) + if err != nil { + t.Fatalf("ParseFileDiff: expected success, got %s", err) + } + if fileDiff.OrigName != "" || fileDiff.NewName != "/dev/null" { + t.Errorf("ParseFileDiff: expected empty original name and /dev/null new name, got %q and %q", fileDiff.OrigName, fileDiff.NewName) + } +}