From ea34aaf6e5fa56114d47ce08d5eb31ba3fb68d6f Mon Sep 17 00:00:00 2001 From: Chris Drew Date: Sun, 10 Feb 2019 14:55:59 +0000 Subject: [PATCH] Handle diffs on windows Running the standard diff tool on windows produces output with CRLF line endings. Stripping trailing CR in the line reader utility prevents errors in diff parsing. --- diff/diff_test.go | 38 +++++++++++ diff/reader_util.go | 13 +++- diff/reader_util_test.go | 68 ++++++++++++++++++++ diff/testdata/sample_multi_file_new_win.diff | 27 ++++++++ 4 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 diff/reader_util_test.go create mode 100644 diff/testdata/sample_multi_file_new_win.diff diff --git a/diff/diff_test.go b/diff/diff_test.go index 6982239..7883180 100644 --- a/diff/diff_test.go +++ b/diff/diff_test.go @@ -375,6 +375,44 @@ func TestParseMultiFileDiffHeaders(t *testing.T) { }, }, }, + { + filename: "sample_multi_file_new_win.diff", + wantDiffs: []*FileDiff{ + { + OrigName: "/dev/null", + OrigTime: nil, + NewName: "b/_vendor/go/build/syslist_test.go", + NewTime: nil, + Extended: []string{ + "diff --git a/_vendor/go/build/syslist_test.go b/_vendor/go/build/syslist_test.go", + "new file mode 100644", + "index 0000000..3be2928", + }, + }, + { + OrigName: "/dev/null", + OrigTime: nil, + NewName: "b/_vendor/go/build/testdata/empty/dummy", + NewTime: nil, + Extended: []string{ + "diff --git a/_vendor/go/build/testdata/empty/dummy b/_vendor/go/build/testdata/empty/dummy", + "new file mode 100644", + "index 0000000..e69de29", + }, + }, + { + OrigName: "/dev/null", + OrigTime: nil, + NewName: "b/_vendor/go/build/testdata/multi/file.go", + NewTime: nil, + Extended: []string{ + "diff --git a/_vendor/go/build/testdata/multi/file.go b/_vendor/go/build/testdata/multi/file.go", + "new file mode 100644", + "index 0000000..ee946eb", + }, + }, + }, + }, } for _, test := range tests { diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename)) diff --git a/diff/reader_util.go b/diff/reader_util.go index 7674424..395fb7b 100644 --- a/diff/reader_util.go +++ b/diff/reader_util.go @@ -2,7 +2,6 @@ package diff import ( "bufio" - "bytes" "io" ) @@ -25,6 +24,14 @@ func readLine(r *bufio.Reader) ([]byte, error) { } else if err != nil { return nil, err } - line := bytes.TrimSuffix(line_, []byte{'\n'}) - return line, nil + line := line_[0 : len(line_)-1] + return dropCR(line), nil +} + +// dropCR drops a terminal \r from the data. +func dropCR(data []byte) []byte { + if len(data) > 0 && data[len(data)-1] == '\r' { + return data[0 : len(data)-1] + } + return data } diff --git a/diff/reader_util_test.go b/diff/reader_util_test.go new file mode 100644 index 0000000..8d5b2b7 --- /dev/null +++ b/diff/reader_util_test.go @@ -0,0 +1,68 @@ +package diff + +import ( + "bufio" + "io" + "reflect" + "strings" + "testing" +) + +func TestReadLine(t *testing.T) { + tests := []struct { + name string + input string + want []string + }{ + { + name: "empty", + input: "", + want: []string{}, + }, + { + name: "single_line", + input: "@@ -0,0 +1,62 @@", + want: []string{"@@ -0,0 +1,62 @@"}, + }, + { + name: "single_lf_terminated_line", + input: "@@ -0,0 +1,62 @@\n", + want: []string{"@@ -0,0 +1,62 @@"}, + }, + { + name: "single_crlf_terminated_line", + input: "@@ -0,0 +1,62 @@\r\n", + want: []string{"@@ -0,0 +1,62 @@"}, + }, + { + name: "multi_line", + input: `diff --git a/test.go b/test.go +new file mode 100644 +index 0000000..3be2928`, + want: []string{ + "diff --git a/test.go b/test.go", + "new file mode 100644", + "index 0000000..3be2928", + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + in := bufio.NewReader(strings.NewReader(test.input)) + out := []string{} + for { + l, err := readLine(in) + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } + out = append(out, string(l)) + } + if !reflect.DeepEqual(test.want, out) { + t.Errorf("read lines not equal: want %v, got %v", test.want, out) + } + }) + } +} diff --git a/diff/testdata/sample_multi_file_new_win.diff b/diff/testdata/sample_multi_file_new_win.diff new file mode 100644 index 0000000..b5e1788 --- /dev/null +++ b/diff/testdata/sample_multi_file_new_win.diff @@ -0,0 +1,27 @@ +diff --git a/_vendor/go/build/syslist_test.go b/_vendor/go/build/syslist_test.go +new file mode 100644 +index 0000000..3be2928 +--- /dev/null ++++ b/_vendor/go/build/syslist_test.go +@@ -0,0 +1,62 @@ ++func TestGoodOSArch(t *testing.T) { ++ for _, test := range tests { ++ if Default.goodOSArchFile(test.name, make(map[string]bool)) != test.result { ++ t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result) ++ } ++ } ++} +diff --git a/_vendor/go/build/testdata/empty/dummy b/_vendor/go/build/testdata/empty/dummy +new file mode 100644 +index 0000000..e69de29 +diff --git a/_vendor/go/build/testdata/multi/file.go b/_vendor/go/build/testdata/multi/file.go +new file mode 100644 +index 0000000..ee946eb +--- /dev/null ++++ b/_vendor/go/build/testdata/multi/file.go +@@ -0,0 +1,5 @@ ++// Test data - not compiled. ++ ++package main ++ ++func main() {}