Skip to content

Commit a768196

Browse files
authored
Merge pull request sourcegraph#60 from craigfurman/trailing-content
MultiFileDiffReader returns trailing content
2 parents 82e3467 + b8a97d3 commit a768196

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)