Skip to content

Commit b8a97d3

Browse files
committed
MultiFileDiffReader returns trailing content
Along with EOF. This is useful for handling mixed diff and non-diff output. Note that "stray" content between diff files was already included in the extended headers for the next diff. To avoid breaking the existing API, this trailing content is only available in a new method.
1 parent 82e3467 commit b8a97d3

4 files changed

+121
-9
lines changed

diff/diff_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package diff
22

33
import (
44
"bytes"
5+
"io"
56
"io/ioutil"
67
"path/filepath"
78
"reflect"
@@ -818,6 +819,52 @@ func TestParseMultiFileDiffAndPrintMultiFileDiff(t *testing.T) {
818819
}
819820
}
820821

822+
func TestParseMultiFileDiffAndPrintMultiFileDiffIncludingTrailingContent(t *testing.T) {
823+
testInput, err := ioutil.ReadFile(filepath.Join("testdata", "sample_multi_file_trailing_content.diff"))
824+
if err != nil {
825+
t.Fatal(err)
826+
}
827+
expectedDiffs, err := ioutil.ReadFile(filepath.Join("testdata", "sample_multi_file_trailing_content_diffsonly.diff"))
828+
if err != nil {
829+
t.Fatal(err)
830+
}
831+
832+
diffReader := NewMultiFileDiffReader(bytes.NewReader(testInput))
833+
var diffs []*FileDiff
834+
trailingContent := ""
835+
for {
836+
var fd *FileDiff
837+
var err error
838+
fd, trailingContent, err = diffReader.ReadFileWithTrailingContent()
839+
if fd != nil {
840+
diffs = append(diffs, fd)
841+
}
842+
if err == io.EOF {
843+
break
844+
}
845+
if err != nil {
846+
t.Error(err)
847+
}
848+
}
849+
850+
if len(diffs) != 2 {
851+
t.Errorf("expected 2 diffs, got %d", len(diffs))
852+
}
853+
854+
printed, err := PrintMultiFileDiff(diffs)
855+
if err != nil {
856+
t.Errorf("PrintMultiFileDiff: %s", err)
857+
}
858+
if !bytes.Equal(printed, expectedDiffs) {
859+
t.Errorf("printed multi-file diff != original multi-file diff\n\n# PrintMultiFileDiff output - Original:\n%s", cmp.Diff(expectedDiffs, printed))
860+
}
861+
862+
expectedTrailingContent := "some trailing content"
863+
if trailingContent != expectedTrailingContent {
864+
t.Errorf("expected trailing content %s, got %s", expectedTrailingContent, trailingContent)
865+
}
866+
}
867+
821868
func TestNoNewlineAtEnd(t *testing.T) {
822869
diffs := map[string]struct {
823870
diff string

diff/parse.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ type MultiFileDiffReader struct {
4646
// all hunks) from r. If there are no more files in the diff, it
4747
// returns error io.EOF.
4848
func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) {
49+
fd, _, err := r.ReadFileWithTrailingContent()
50+
return fd, err
51+
}
52+
53+
// ReadFileWithTrailingContent reads the next file unified diff (including
54+
// headers and all hunks) from r, also returning any trailing content. If there
55+
// are no more files in the diff, it returns error io.EOF.
56+
func (r *MultiFileDiffReader) ReadFileWithTrailingContent() (*FileDiff, string, error) {
4957
fr := &FileDiffReader{
5058
line: r.line,
5159
offset: r.offset,
@@ -59,23 +67,33 @@ func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) {
5967
switch e := err.(type) {
6068
case *ParseError:
6169
if e.Err == ErrNoFileHeader || e.Err == ErrExtendedHeadersEOF {
62-
return nil, io.EOF
70+
// Any non-diff content preceding a valid diff is included in the
71+
// extended headers of the following diff. In this way, mixed diff /
72+
// non-diff content can be parsed. Trailing non-diff content is
73+
// different: it doesn't make sense to return a FileDiff with only
74+
// extended headers populated. Instead, we return any trailing content
75+
// in case the caller needs it.
76+
trailing := ""
77+
if fd != nil {
78+
trailing = strings.Join(fd.Extended, "\n")
79+
}
80+
return nil, trailing, io.EOF
6381
}
64-
return nil, err
82+
return nil, "", err
6583

6684
case OverflowError:
6785
r.nextFileFirstLine = []byte(e)
68-
return fd, nil
86+
return fd, "", nil
6987

7088
default:
71-
return nil, err
89+
return nil, "", err
7290
}
7391
}
7492

7593
// FileDiff is added/deleted file
7694
// No further collection of hunks needed
7795
if fd.NewName == "" {
78-
return fd, nil
96+
return fd, "", nil
7997
}
8098

8199
// Before reading hunks, check to see if there are any. If there
@@ -87,7 +105,7 @@ func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) {
87105
hr := fr.HunksReader()
88106
line, err := r.reader.readLine()
89107
if err != nil && err != io.EOF {
90-
return fd, err
108+
return fd, "", err
91109
}
92110
line = bytes.TrimSuffix(line, []byte{'\n'})
93111
if bytes.HasPrefix(line, hunkPrefix) {
@@ -101,18 +119,18 @@ func (r *MultiFileDiffReader) ReadFile() (*FileDiff, error) {
101119
// This just means we finished reading the hunks for the
102120
// current file. See the ErrBadHunkLine doc for more info.
103121
r.nextFileFirstLine = e.Line
104-
return fd, nil
122+
return fd, "", nil
105123
}
106124
}
107-
return nil, err
125+
return nil, "", err
108126
}
109127
} else {
110128
// There weren't any hunks, so that line we peeked ahead at
111129
// actually belongs to the next file. Put it back.
112130
r.nextFileFirstLine = line
113131
}
114132

115-
return fd, nil
133+
return fd, "", nil
116134
}
117135

118136
// ReadAllFiles reads all file unified diffs (including headers and all
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
some leading content
2+
diff --git a/comment-last-line.sql b/comment-last-line.sql
3+
index 04a1655..97bd115 100644
4+
--- a/comment-last-line.sql
5+
+++ b/comment-last-line.sql
6+
@@ -1,4 +1,4 @@
7+
select 1;
8+
+++ invalid SQL comment
9+
select 2;
10+
select 3;
11+
--- end of three queries
12+
some content between diffs
13+
diff --git a/query.sql b/query.sql
14+
index 9537d7b..234ef35 100644
15+
--- a/query.sql
16+
+++ b/query.sql
17+
@@ -1,5 +1,4 @@
18+
select 1;
19+
--- this is my query
20+
select 2;
21+
select 3;
22+
--- this is the last line
23+
+++ invalid sql comment
24+
some trailing content
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
some leading content
2+
diff --git a/comment-last-line.sql b/comment-last-line.sql
3+
index 04a1655..97bd115 100644
4+
--- a/comment-last-line.sql
5+
+++ b/comment-last-line.sql
6+
@@ -1,4 +1,4 @@
7+
select 1;
8+
+++ invalid SQL comment
9+
select 2;
10+
select 3;
11+
--- end of three queries
12+
some content between diffs
13+
diff --git a/query.sql b/query.sql
14+
index 9537d7b..234ef35 100644
15+
--- a/query.sql
16+
+++ b/query.sql
17+
@@ -1,5 +1,4 @@
18+
select 1;
19+
--- this is my query
20+
select 2;
21+
select 3;
22+
--- this is the last line
23+
+++ invalid sql comment

0 commit comments

Comments
 (0)