Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

format: diff, Handle no newline at end of file. Fixes #936 #1225

Merged
merged 1 commit into from
Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions plumbing/format/diff/unified_encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"io"
"regexp"
"strings"

"gopkg.in/src-d/go-git.v4/plumbing"
Expand All @@ -25,9 +26,10 @@ const (
tPath = "+++ %s\n"
binary = "Binary files %s and %s differ\n"

addLine = "+%s\n"
deleteLine = "-%s\n"
equalLine = " %s\n"
addLine = "+%s%s"
deleteLine = "-%s%s"
equalLine = " %s%s"
noNewLine = "\n\\ No newline at end of file\n"

oldMode = "old mode %o\n"
newMode = "new mode %o\n"
Expand Down Expand Up @@ -216,7 +218,7 @@ func (c *hunksGenerator) processHunk(i int, op Operation) {
linesBefore = c.ctxLines
}

c.current = &hunk{ctxPrefix: ctxPrefix}
c.current = &hunk{ctxPrefix: strings.TrimSuffix(ctxPrefix, "\n")}
c.current.AddOp(Equal, c.beforeContext...)

switch op {
Expand Down Expand Up @@ -279,12 +281,13 @@ func (c *hunksGenerator) processEqualsLines(ls []string, i int) {
}
}

var splitLinesRE = regexp.MustCompile(`[^\n]*(\n|$)`)

func splitLines(s string) []string {
out := strings.Split(s, "\n")
out := splitLinesRE.FindAllString(s, -1)
if out[len(out)-1] == "" {
out = out[:len(out)-1]
}

return out
}

Expand Down Expand Up @@ -346,7 +349,7 @@ type op struct {
}

func (o *op) String() string {
var prefix string
var prefix, suffix string
switch o.t {
case Add:
prefix = addLine
Expand All @@ -355,6 +358,10 @@ func (o *op) String() string {
case Equal:
prefix = equalLine
}
n := len(o.text)
if n > 0 && o.text[n-1] != '\n' {
suffix = noNewLine
}

return fmt.Sprintf(prefix, o.text)
return fmt.Sprintf(prefix, o.text, suffix)
}
90 changes: 68 additions & 22 deletions plumbing/format/diff/unified_encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ var oneChunkPatch Patch = testPatch{
content: "A\n",
op: Delete,
}, {
content: "B\nC\nD\nE\nF\nG",
content: "B\nC\nD\nE\nF\nG\n",
op: Equal,
}, {
content: "H\n",
Expand Down Expand Up @@ -125,7 +125,7 @@ var oneChunkPatchInverted Patch = testPatch{
content: "A\n",
op: Add,
}, {
content: "B\nC\nD\nE\nF\nG",
content: "B\nC\nD\nE\nF\nG\n",
op: Equal,
}, {
content: "H\n",
Expand Down Expand Up @@ -164,13 +164,13 @@ var fixtures []*fixture = []*fixture{{
seed: "hello\nbug\n",
},
chunks: []testChunk{{
content: "hello",
content: "hello\n",
op: Equal,
}, {
content: "world",
content: "world\n",
op: Delete,
}, {
content: "bug",
content: "bug\n",
op: Add,
}},
}},
Expand Down Expand Up @@ -239,18 +239,18 @@ rename to test1.txt
from: &testFile{
mode: filemode.Regular,
path: "test.txt",
seed: "test",
seed: "test\n",
},
to: &testFile{
mode: filemode.Regular,
path: "test1.txt",
seed: "test1",
seed: "test1\n",
},
chunks: []testChunk{{
content: "test",
content: "test\n",
op: Delete,
}, {
content: "test1",
content: "test1\n",
op: Add,
}},
}},
Expand All @@ -260,7 +260,7 @@ rename to test1.txt
diff: `diff --git a/test.txt b/test1.txt
rename from test.txt
rename to test1.txt
index 30d74d258442c7c65512eafab474568dd706c430..f079749c42ffdcc5f52ed2d3a6f15b09307e975e 100644
index 9daeafb9864cf43055ae93beb0afd6c7d144bfa4..a5bce3fd2565d8f458555a0c6f42d0504a848bd5 100644
--- a/test.txt
+++ b/test1.txt
@@ -1 +1 @@
Expand Down Expand Up @@ -299,19 +299,19 @@ rename to test1.txt
from: &testFile{
mode: filemode.Regular,
path: "test.txt",
seed: "test",
seed: "test\n",
},
to: &testFile{
mode: filemode.Regular,
path: "test.txt",
seed: "test2",
seed: "test2\n",
},

chunks: []testChunk{{
content: "test",
content: "test\n",
op: Delete,
}, {
content: "test2",
content: "test2\n",
op: Add,
}},
}},
Expand All @@ -320,7 +320,7 @@ rename to test1.txt
desc: "one line change",
context: 1,
diff: `diff --git a/test.txt b/test.txt
index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d55b2ae9d 100644
index 9daeafb9864cf43055ae93beb0afd6c7d144bfa4..180cf8328022becee9aaa2577a8f84ea2b9f3827 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
Expand All @@ -334,19 +334,19 @@ index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d
from: &testFile{
mode: filemode.Regular,
path: "test.txt",
seed: "test",
seed: "test\n",
},
to: &testFile{
mode: filemode.Regular,
path: "test.txt",
seed: "test2",
seed: "test2\n",
},

chunks: []testChunk{{
content: "test",
content: "test\n",
op: Delete,
}, {
content: "test2",
content: "test2\n",
op: Add,
}},
}},
Expand All @@ -356,7 +356,7 @@ index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d
context: 1,
diff: `this is the message
diff --git a/test.txt b/test.txt
index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d55b2ae9d 100644
index 9daeafb9864cf43055ae93beb0afd6c7d144bfa4..180cf8328022becee9aaa2577a8f84ea2b9f3827 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
Expand Down Expand Up @@ -397,7 +397,9 @@ index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d
+++ b/test.txt
@@ -1 +1 @@
-test
\ No newline at end of file
+test2
\ No newline at end of file
`,
}, {
patch: testPatch{
Expand All @@ -407,7 +409,7 @@ index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d
to: &testFile{
mode: filemode.Regular,
path: "new.txt",
seed: "test\ntest2\test3",
seed: "test\ntest2\ntest3",
},

chunks: []testChunk{{
Expand All @@ -421,13 +423,14 @@ index 30d74d258442c7c65512eafab474568dd706c430..d606037cb232bfda7788a8322492312d
context: 1,
diff: `diff --git a/new.txt b/new.txt
new file mode 100644
index 0000000000000000000000000000000000000000..65c8dd02a42273038658a22b1cb29c8d9457ca12
index 0000000000000000000000000000000000000000..3ceaab5442b64a0c2b33dd25fae67ccdb4fd1ea8
--- /dev/null
+++ b/new.txt
@@ -0,0 +1,3 @@
+test
+test2
+test3
\ No newline at end of file
`,
}, {
patch: testPatch{
Expand Down Expand Up @@ -456,6 +459,7 @@ index 30d74d258442c7c65512eafab474568dd706c430..00000000000000000000000000000000
+++ /dev/null
@@ -1 +0,0 @@
-test
\ No newline at end of file
`,
}, {
patch: oneChunkPatch,
Expand Down Expand Up @@ -548,6 +552,7 @@ index ab5eed5d4a2c33aeef67e0188ee79bed666bde6f..0adddcde4fd38042c354518351820eb0
X
Y
Z
\ No newline at end of file
`,
}, {
patch: oneChunkPatch,
Expand Down Expand Up @@ -813,6 +818,47 @@ index 0adddcde4fd38042c354518351820eb06c417c82..553ae669c7a9303cf848fcc749a25692
+++ b/onechunk.txt
@@ -23 +22,0 @@ Y
-Z
\ No newline at end of file
`,
}, {
patch: testPatch{
message: "",
filePatches: []testFilePatch{{
from: &testFile{
mode: filemode.Regular,
path: "onechunk.txt",
seed: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY\nZ",
},
to: &testFile{
mode: filemode.Regular,
path: "onechunk.txt",
seed: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY",
},

chunks: []testChunk{{
content: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\n",
op: Equal,
}, {
content: "Y\nZ",
op: Delete,
}, {
content: "Y",
op: Add,
}},
}},
},
desc: "remove last letter and no newline at end of file",
context: 0,
diff: `diff --git a/onechunk.txt b/onechunk.txt
index 0adddcde4fd38042c354518351820eb06c417c82..d39ae38aad7ba9447b5e7998b2e4714f26c9218d 100644
--- a/onechunk.txt
+++ b/onechunk.txt
@@ -22,2 +21 @@ X
-Y
-Z
\ No newline at end of file
+Y
\ No newline at end of file
`,
}}

Expand Down
31 changes: 31 additions & 0 deletions utils/diff/diff_ext_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,37 @@ var doTests = [...]struct {
{Type: 1, Text: "111\nBCD\n"},
},
},
{
src: "A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nÑ\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ",
dst: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY\nZ",
exp: []diffmatchpatch.Diff{
{Type: -1, Text: "A\n"},
{Type: 0, Text: "B\nC\nD\nE\nF\nG\n"},
{Type: -1, Text: "H\n"},
{Type: 0, Text: "I\nJ\nK\nL\nM\nN\n"},
{Type: -1, Text: "Ñ\n"},
{Type: 0, Text: "O\nP\nQ\nR\nS\nT\n"},
{Type: -1, Text: "U\n"},
{Type: 0, Text: "V\nW\nX\nY\nZ"},
},
},
{
src: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY\nZ",
dst: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY\n",
exp: []diffmatchpatch.Diff{
{Type: 0, Text: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY\n"},
{Type: -1, Text: "Z"},
},
},
{
src: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY\nZ",
dst: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\nY",
exp: []diffmatchpatch.Diff{
{Type: 0, Text: "B\nC\nD\nE\nF\nG\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nV\nW\nX\n"},
{Type: -1, Text: "Y\nZ"},
{Type: 1, Text: "Y"},
},
},
}

func (s *suiteCommon) TestDo(c *C) {
Expand Down