Skip to content

Commit ba2c541

Browse files
committed
fix no-newline edge case
1 parent 11d71e2 commit ba2c541

File tree

5 files changed

+41
-50
lines changed

5 files changed

+41
-50
lines changed

diff/diff_test.go

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"io/ioutil"
66
"path/filepath"
77
"reflect"
8-
"strings"
98
"testing"
109
)
1110

@@ -54,7 +53,11 @@ func TestParseHunksAndPrintHunks(t *testing.T) {
5453
{
5554
filename: "sample_hunks_no_newline.diff",
5655
},
56+
{
57+
filename: "sample_hunks_no_newline2.diff",
58+
},
5759
{filename: "empty.diff"},
60+
{filename: "oneline_hunk.diff"},
5861
}
5962
for _, test := range tests {
6063
diffData, err := ioutil.ReadFile(filepath.Join("testdata", test.filename))
@@ -80,6 +83,25 @@ func TestParseHunksAndPrintHunks(t *testing.T) {
8083
}
8184
}
8285

86+
func TestStripModifierLines(t *testing.T) {
87+
orig := `- a
88+
\ No newline at end of file
89+
+ b
90+
\ No newline at end of file
91+
`
92+
want := `- a
93+
+ b
94+
`
95+
96+
hunks := []*Hunk{{Body: []byte(orig)}}
97+
StripModifierLines(hunks)
98+
stripped := string(hunks[0].Body)
99+
100+
if stripped != want {
101+
t.Errorf("Want:\n%s\nbut got:\n%s", want, stripped)
102+
}
103+
}
104+
83105
func TestParseFileDiffAndPrintFileDiff(t *testing.T) {
84106
tests := []struct {
85107
filename string
@@ -160,36 +182,6 @@ func TestParseMultiFileDiffAndPrintMultiFileDiff(t *testing.T) {
160182
}
161183
}
162184

163-
func TestNoNewlineAtEnd(t *testing.T) {
164-
orig := `@@ -1,1 +1,1 @@
165-
-b
166-
+b
167-
\ No newline at end of file
168-
`
169-
170-
hunks, err := ParseHunks([]byte(orig))
171-
if err != nil {
172-
t.Fatal("ParseHunks: %s", err)
173-
}
174-
175-
for _, hunk := range hunks {
176-
if body := string(hunk.Body); strings.Contains(body, "No newline") {
177-
t.Errorf("after parse, hunk body contains 'No newline...' string\n\nbody is:\n%q", body)
178-
}
179-
if bytes.HasSuffix(hunk.Body, []byte{'\n'}) {
180-
t.Errorf("after parse, hunk body ends with newline\n\nbody is:\n%q", hunk.Body)
181-
}
182-
183-
printed, err := PrintHunks(hunks)
184-
if err != nil {
185-
t.Fatal("PrintHunks: %s", err)
186-
}
187-
if printed := string(printed); printed != orig {
188-
t.Errorf("printed diff hunks != original diff hunks\n\n# PrintHunks output:\n%q\n\n# Original:\n%q", printed, orig)
189-
}
190-
}
191-
}
192-
193185
func TestFileDiff_Stat(t *testing.T) {
194186
tests := map[string]struct {
195187
hunks []*Hunk

diff/parse.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,15 @@ func ParseHunks(diff []byte) ([]*Hunk, error) {
304304
return hunks, nil
305305
}
306306

307+
// StripModifierLines strips the modifier line "\ No newline at end of file", which
308+
// indicates that the preceding line has no terminating newline character. This makes it
309+
// so that all lines in the hunk corresponds to actual lines in the file.
310+
func StripModifierLines(hunks []*Hunk) {
311+
for _, hunk := range hunks {
312+
hunk.Body = bytes.Replace(hunk.Body, []byte(NoNewlineMessage+"\n"), []byte{}, -1)
313+
}
314+
}
315+
307316
// NewHunksReader returns a new HunksReader that reads unified diff hunks
308317
// from r.
309318
func NewHunksReader(r io.Reader) *HunksReader {
@@ -391,13 +400,6 @@ func (r *HunksReader) ReadHunk() (*Hunk, error) {
391400
// handle that case.
392401
return r.hunk, &ParseError{r.line, r.offset, &ErrBadHunkLine{Line: line}}
393402
}
394-
if bytes.Equal(line, []byte(noNewlineMessage)) {
395-
// Remove previous line's newline.
396-
if len(r.hunk.Body) != 0 {
397-
r.hunk.Body = r.hunk.Body[:len(r.hunk.Body)-1]
398-
}
399-
continue
400-
}
401403

402404
r.hunk.Body = append(r.hunk.Body, line...)
403405
r.hunk.Body = append(r.hunk.Body, '\n')
@@ -414,7 +416,7 @@ func (r *HunksReader) ReadHunk() (*Hunk, error) {
414416
return nil, io.EOF
415417
}
416418

417-
const noNewlineMessage = `\ No newline at end of file`
419+
const NoNewlineMessage = `\ No newline at end of file`
418420

419421
// linePrefixes is the set of all characters a valid line in a diff
420422
// hunk can start with. '\' can appear in diffs when no newline is

diff/print.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,6 @@ func PrintHunks(hunks []*Hunk) ([]byte, error) {
8989
if _, err := buf.Write(hunk.Body); err != nil {
9090
return nil, err
9191
}
92-
if !bytes.HasSuffix(hunk.Body, []byte{'\n'}) {
93-
if _, err := fmt.Fprintln(&buf); err != nil {
94-
return nil, err
95-
}
96-
if _, err := buf.Write([]byte(noNewlineMessage)); err != nil {
97-
return nil, err
98-
}
99-
if _, err := fmt.Fprintln(&buf); err != nil {
100-
return nil, err
101-
}
102-
}
10392
}
10493
return buf.Bytes(), nil
10594
}

diff/testdata/oneline_hunk.diff

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@@ -1,1 +1,1 @@
2+
-there is an {{ identifier }} in this file
3+
+this is a file
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@@ -1,1 +1,1 @@
2+
-b
3+
\ No newline at end of file
4+
+b
5+
\ No newline at end of file

0 commit comments

Comments
 (0)