Skip to content

Commit c818281

Browse files
committed
Always accept newline as a name terminator
This avoids including the newline character as part of the name when it is the last name on a line. Also split out functions for quoted and unquoted names to clarify the logic.
1 parent 631c705 commit c818281

File tree

2 files changed

+42
-27
lines changed

2 files changed

+42
-27
lines changed

gitdiff/file_header.go

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -199,41 +199,53 @@ func parseMode(s string) (os.FileMode, error) {
199199
// slashes are collapsed.
200200
func parseName(s string, term rune, dropPrefix int) (name string, n int, err error) {
201201
if len(s) > 0 && s[0] == '"' {
202-
// find matching end quote and then unquote the section
203-
for n = 1; n < len(s); n++ {
204-
if s[n] == '"' && s[n-1] != '\\' {
205-
n++
206-
break
207-
}
208-
}
209-
if n == 2 {
210-
return "", 0, fmt.Errorf("missing name")
211-
}
212-
if name, err = strconv.Unquote(s[:n]); err != nil {
213-
return "", 0, err
214-
}
202+
name, n, err = parseQuotedName(s)
215203
} else {
216-
// find terminator and take the previous section
217-
for n = 0; n < len(s); n++ {
218-
if term >= 0 && rune(s[n]) == term {
219-
break
220-
}
221-
if term < 0 && (s[n] == ' ' || s[n] == '\t') {
222-
break
223-
}
224-
}
225-
if n == 0 {
226-
return "", 0, fmt.Errorf("missing name")
227-
}
228-
name = s[:n]
204+
name, n, err = parseUnquotedName(s, term)
205+
}
206+
if err != nil {
207+
return "", 0, err
229208
}
230-
231209
if name == devNull {
232210
return name, n, nil
233211
}
234212
return cleanName(name, dropPrefix), n, nil
235213
}
236214

215+
func parseQuotedName(s string) (name string, n int, err error) {
216+
for n = 1; n < len(s); n++ {
217+
if s[n] == '"' && s[n-1] != '\\' {
218+
n++
219+
break
220+
}
221+
}
222+
if n == 2 {
223+
return "", 0, fmt.Errorf("missing name")
224+
}
225+
if name, err = strconv.Unquote(s[:n]); err != nil {
226+
return "", 0, err
227+
}
228+
return name, n, err
229+
}
230+
231+
func parseUnquotedName(s string, term rune) (name string, n int, err error) {
232+
for n = 0; n < len(s); n++ {
233+
if s[n] == '\n' {
234+
break
235+
}
236+
if term >= 0 && rune(s[n]) == term {
237+
break
238+
}
239+
if term < 0 && (s[n] == ' ' || s[n] == '\t') {
240+
break
241+
}
242+
}
243+
if n == 0 {
244+
return "", 0, fmt.Errorf("missing name")
245+
}
246+
return s[:n], n, nil
247+
}
248+
237249
// verifyGitHeaderName checks a parsed name against state set by previous lines
238250
func verifyGitHeaderName(parsed, existing string, isNull bool, side string) error {
239251
if existing != "" {

gitdiff/file_header_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ func TestParseName(t *testing.T) {
7272
"devNull": {
7373
Input: "/dev/null", Term: '\t', Drop: 1, Output: "/dev/null", N: 9,
7474
},
75+
"newlineAlwaysSeparates": {
76+
Input: "dir/file.txt\n", Term: 0, Output: "dir/file.txt", N: 12,
77+
},
7578
"emptyString": {
7679
Input: "", Err: true,
7780
},

0 commit comments

Comments
 (0)