Repository: bluekeyes/go-gitdiff
Pull request #9 (2020-05-03 05:32:38)

Check for leftover content after a full delete
When applying a text fragment that deletes all content in the file, make
sure there is no content left in the source after using all the lines in
the fragment. If there is is extra content, it's a conflict: something
added more lines to the file after generating the patch.


Patch:
diff --git a/gitdiff/apply.go b/gitdiff/apply.go
index 9348286..4397d99 100644
--- a/gitdiff/apply.go
+++ b/gitdiff/apply.go
@@ -259,6 +259,19 @@ func (a *Applier) ApplyTextFragment(dst io.Writer, f *TextFragment) error {
 		}
 	}
 	a.nextLine = fragStart + used
+
+	// new position of +0,0 mean a full delete, so check for leftovers
+	if f.NewPosition == 0 && f.NewLines == 0 {
+		var b [1][]byte
+		n, err := a.lineSrc.ReadLinesAt(b[:], a.nextLine)
+		if err != nil && err != io.EOF {
+			return applyError(err, lineNum(a.nextLine))
+		}
+		if n > 0 {
+			return applyError(&Conflict{"src still has content after full delete"}, lineNum(a.nextLine))
+		}
+	}
+
 	return nil
 }
 


Test patch:
diff --git a/gitdiff/apply_test.go b/gitdiff/apply_test.go
index edbbe03..d981e96 100644
--- a/gitdiff/apply_test.go
+++ b/gitdiff/apply_test.go
@@ -185,9 +185,33 @@ func TestApplyBinaryFragment(t *testing.T) {
 
 func TestApplyFile(t *testing.T) {
 	tests := map[string]applyTest{
-		"textModify":   {Files: getApplyFiles("text_file_modify")},
-		"binaryModify": {Files: getApplyFiles("bin_file_modify")},
-		"modeChange":   {Files: getApplyFiles("file_mode_change")},
+		"textModify": {
+			Files: applyFiles{
+				Src:   "file_text.src",
+				Patch: "file_text_modify.patch",
+				Out:   "file_text_modify.out",
+			},
+		},
+		"textDelete": {
+			Files: applyFiles{
+				Src:   "file_text.src",
+				Patch: "file_text_delete.patch",
+				Out:   "file_text_delete.out",
+			},
+		},
+		"textErrorPartialDelete": {
+			Files: applyFiles{
+				Src:   "file_text.src",
+				Patch: "file_text_error_partial_delete.patch",
+			},
+			Err: &Conflict{},
+		},
+		"binaryModify": {
+			Files: getApplyFiles("file_bin_modify"),
+		},
+		"modeChange": {
+			Files: getApplyFiles("file_mode_change"),
+		},
 	}
 
 	for name, test := range tests {
@@ -233,7 +257,7 @@ func (at applyTest) run(t *testing.T, apply func(io.Writer, *Applier, *File) err
 	}
 
 	if !bytes.Equal(out, dst.Bytes()) {
-		t.Errorf("incorrect result after apply\nexpected:\n%x\nactual:\n%x", out, dst.Bytes())
+		t.Errorf("incorrect result after apply\nexpected:\n%q\nactual:\n%q", out, dst.Bytes())
 	}
 }
 
diff --git a/gitdiff/testdata/apply/bin_file_modify.out b/gitdiff/testdata/apply/file_bin_modify.out
similarity index 100%
rename from gitdiff/testdata/apply/bin_file_modify.out
rename to gitdiff/testdata/apply/file_bin_modify.out
diff --git a/gitdiff/testdata/apply/bin_file_modify.patch b/gitdiff/testdata/apply/file_bin_modify.patch
similarity index 81%
rename from gitdiff/testdata/apply/bin_file_modify.patch
rename to gitdiff/testdata/apply/file_bin_modify.patch
index 7058e37..af38f36 100644
--- a/gitdiff/testdata/apply/bin_file_modify.patch
+++ b/gitdiff/testdata/apply/file_bin_modify.patch
@@ -1,4 +1,4 @@
-diff --git a/gitdiff/testdata/apply/bin_file_modify.src b/gitdiff/testdata/apply/bin_file_modify.src
+diff --git a/gitdiff/testdata/apply/file_bin_modify.src b/gitdiff/testdata/apply/file_bin_modify.src
 GIT binary patch
 delta 172
 zcmV;d08{^f2)qc8AP{I3VQ>J`s>wb0HU+h#6w8q?tUO~cHmDjZi2<8yZ9XmKhhMdo
diff --git a/gitdiff/testdata/apply/bin_file_modify.src b/gitdiff/testdata/apply/file_bin_modify.src
similarity index 100%
rename from gitdiff/testdata/apply/bin_file_modify.src
rename to gitdiff/testdata/apply/file_bin_modify.src
diff --git a/gitdiff/testdata/apply/text_file_modify.src b/gitdiff/testdata/apply/file_text.src
similarity index 100%
rename from gitdiff/testdata/apply/text_file_modify.src
rename to gitdiff/testdata/apply/file_text.src
diff --git a/gitdiff/testdata/apply/file_text_delete.out b/gitdiff/testdata/apply/file_text_delete.out
new file mode 100644
index 0000000..e69de29
diff --git a/gitdiff/testdata/apply/file_text_delete.patch b/gitdiff/testdata/apply/file_text_delete.patch
new file mode 100644
index 0000000..9ac710b
--- /dev/null
+++ b/gitdiff/testdata/apply/file_text_delete.patch
@@ -0,0 +1,206 @@
+diff --git a/gitdiff/testdata/apply/file_text.src.src b/gitdiff/testdata/apply/file_text.src
+deleted file mode 100644
+index 3805ad4..0000000
+--- a/gitdiff/testdata/apply/file_text.src.src
++++ /dev/null
+@@ -1,200 +0,0 @@
+-this is line 1
+-this is line 2
+-this is line 3
+-this is line 4
+-this is line 5
+-this is line 6
+-this is line 7
+-this is line 8
+-this is line 9
+-this is line 10
+-this is line 11
+-this is line 12
+-this is line 13
+-this is line 14
+-this is line 15
+-this is line 16
+-this is line 17
+-this is line 18
+-this is line 19
+-this is line 20
+-this is line 21
+-this is line 22
+-this is line 23
+-this is line 24
+-this is line 25
+-this is line 26
+-this is line 27
+-this is line 28
+-this is line 29
+-this is line 30
+-this is line 31
+-this is line 32
+-this is line 33
+-this is line 34
+-this is line 35
+-this is line 36
+-this is line 37
+-this is line 38
+-this is line 39
+-this is line 40
+-this is line 41
+-this is line 42
+-this is line 43
+-this is line 44
+-this is line 45
+-this is line 46
+-this is line 47
+-this is line 48
+-this is line 49
+-this is line 50
+-this is line 51
+-this is line 52
+-this is line 53
+-this is line 54
+-this is line 55
+-this is line 56
+-this is line 57
+-this is line 58
+-this is line 59
+-this is line 60
+-this is line 61
+-this is line 62
+-this is line 63
+-this is line 64
+-this is line 65
+-this is line 66
+-this is line 67
+-this is line 68
+-this is line 69
+-this is line 70
+-this is line 71
+-this is line 72
+-this is line 73
+-this is line 74
+-this is line 75
+-this is line 76
+-this is line 77
+-this is line 78
+-this is line 79
+-this is line 80
+-this is line 81
+-this is line 82
+-this is line 83
+-this is line 84
+-this is line 85
+-this is line 86
+-this is line 87
+-this is line 88
+-this is line 89
+-this is line 90
+-this is line 91
+-this is line 92
+-this is line 93
+-this is line 94
+-this is line 95
+-this is line 96
+-this is line 97
+-this is line 98
+-this is line 99
+-this is line 100
+-this is line 101
+-this is line 102
+-this is line 103
+-this is line 104
+-this is line 105
+-this is line 106
+-this is line 107
+-this is line 108
+-this is line 109
+-this is line 110
+-this is line 111
+-this is line 112
+-this is line 113
+-this is line 114
+-this is line 115
+-this is line 116
+-this is line 117
+-this is line 118
+-this is line 119
+-this is line 120
+-this is line 121
+-this is line 122
+-this is line 123
+-this is line 124
+-this is line 125
+-this is line 126
+-this is line 127
+-this is line 128
+-this is line 129
+-this is line 130
+-this is line 131
+-this is line 132
+-this is line 133
+-this is line 134
+-this is line 135
+-this is line 136
+-this is line 137
+-this is line 138
+-this is line 139
+-this is line 140
+-this is line 141
+-this is line 142
+-this is line 143
+-this is line 144
+-this is line 145
+-this is line 146
+-this is line 147
+-this is line 148
+-this is line 149
+-this is line 150
+-this is line 151
+-this is line 152
+-this is line 153
+-this is line 154
+-this is line 155
+-this is line 156
+-this is line 157
+-this is line 158
+-this is line 159
+-this is line 160
+-this is line 161
+-this is line 162
+-this is line 163
+-this is line 164
+-this is line 165
+-this is line 166
+-this is line 167
+-this is line 168
+-this is line 169
+-this is line 170
+-this is line 171
+-this is line 172
+-this is line 173
+-this is line 174
+-this is line 175
+-this is line 176
+-this is line 177
+-this is line 178
+-this is line 179
+-this is line 180
+-this is line 181
+-this is line 182
+-this is line 183
+-this is line 184
+-this is line 185
+-this is line 186
+-this is line 187
+-this is line 188
+-this is line 189
+-this is line 190
+-this is line 191
+-this is line 192
+-this is line 193
+-this is line 194
+-this is line 195
+-this is line 196
+-this is line 197
+-this is line 198
+-this is line 199
+-this is line 200
diff --git a/gitdiff/testdata/apply/file_text_error_partial_delete.patch b/gitdiff/testdata/apply/file_text_error_partial_delete.patch
new file mode 100644
index 0000000..01d2a6f
--- /dev/null
+++ b/gitdiff/testdata/apply/file_text_error_partial_delete.patch
@@ -0,0 +1,106 @@
+diff --git a/gitdiff/testdata/apply/file_text.src.src b/gitdiff/testdata/apply/file_text.src
+deleted file mode 100644
+index 3805ad4..0000000
+--- a/gitdiff/testdata/apply/file_text.src.src
++++ /dev/null
+@@ -1,100 +0,0 @@
+-this is line 1
+-this is line 2
+-this is line 3
+-this is line 4
+-this is line 5
+-this is line 6
+-this is line 7
+-this is line 8
+-this is line 9
+-this is line 10
+-this is line 11
+-this is line 12
+-this is line 13
+-this is line 14
+-this is line 15
+-this is line 16
+-this is line 17
+-this is line 18
+-this is line 19
+-this is line 20
+-this is line 21
+-this is line 22
+-this is line 23
+-this is line 24
+-this is line 25
+-this is line 26
+-this is line 27
+-this is line 28
+-this is line 29
+-this is line 30
+-this is line 31
+-this is line 32
+-this is line 33
+-this is line 34
+-this is line 35
+-this is line 36
+-this is line 37
+-this is line 38
+-this is line 39
+-this is line 40
+-this is line 41
+-this is line 42
+-this is line 43
+-this is line 44
+-this is line 45
+-this is line 46
+-this is line 47
+-this is line 48
+-this is line 49
+-this is line 50
+-this is line 51
+-this is line 52
+-this is line 53
+-this is line 54
+-this is line 55
+-this is line 56
+-this is line 57
+-this is line 58
+-this is line 59
+-this is line 60
+-this is line 61
+-this is line 62
+-this is line 63
+-this is line 64
+-this is line 65
+-this is line 66
+-this is line 67
+-this is line 68
+-this is line 69
+-this is line 70
+-this is line 71
+-this is line 72
+-this is line 73
+-this is line 74
+-this is line 75
+-this is line 76
+-this is line 77
+-this is line 78
+-this is line 79
+-this is line 80
+-this is line 81
+-this is line 82
+-this is line 83
+-this is line 84
+-this is line 85
+-this is line 86
+-this is line 87
+-this is line 88
+-this is line 89
+-this is line 90
+-this is line 91
+-this is line 92
+-this is line 93
+-this is line 94
+-this is line 95
+-this is line 96
+-this is line 97
+-this is line 98
+-this is line 99
+-this is line 100
diff --git a/gitdiff/testdata/apply/text_file_modify.out b/gitdiff/testdata/apply/file_text_modify.out
similarity index 100%
rename from gitdiff/testdata/apply/text_file_modify.out
rename to gitdiff/testdata/apply/file_text_modify.out
diff --git a/gitdiff/testdata/apply/text_file_modify.patch b/gitdiff/testdata/apply/file_text_modify.patch
similarity index 86%
rename from gitdiff/testdata/apply/text_file_modify.patch
rename to gitdiff/testdata/apply/file_text_modify.patch
index 8d4c766..362d9a9 100644
--- a/gitdiff/testdata/apply/text_file_modify.patch
+++ b/gitdiff/testdata/apply/file_text_modify.patch
@@ -1,6 +1,6 @@
-diff --git a/gitdiff/testdata/apply/text_file_modify.src b/gitdiff/testdata/apply/text_file_modify.src
---- a/gitdiff/testdata/apply/text_file_modify.src
-+++ b/gitdiff/testdata/apply/text_file_modify.src
+diff --git a/gitdiff/testdata/apply/file_text.src b/gitdiff/testdata/apply/file_text.src
+--- a/gitdiff/testdata/apply/file_text.src
++++ b/gitdiff/testdata/apply/file_text.src
 @@ -1,4 +1,4 @@
 -this is line 1
 +the first line is different