11package diff
22
33import (
4- "bufio"
54 "bytes"
65 "errors"
76 "fmt"
@@ -17,13 +16,24 @@ import (
1716// case of per-file errors. If it cannot detect when the diff of the next file
1817// begins, the hunks are added to the FileDiff of the previous file.
1918func ParseMultiFileDiff (diff []byte ) ([]* FileDiff , error ) {
20- return NewMultiFileDiffReader (bytes .NewReader (diff )).ReadAllFiles ()
19+ return ParseMultiFileDiffOptions (diff , ParseOptions {})
20+ }
21+
22+ // ParseMultiFileDiffOptions parses a multi-file unified diff with the given options.
23+ func ParseMultiFileDiffOptions (diff []byte , opts ParseOptions ) ([]* FileDiff , error ) {
24+ return NewMultiFileDiffReaderOptions (bytes .NewReader (diff ), opts ).ReadAllFiles ()
2125}
2226
2327// NewMultiFileDiffReader returns a new MultiFileDiffReader that reads
2428// a multi-file unified diff from r.
2529func NewMultiFileDiffReader (r io.Reader ) * MultiFileDiffReader {
26- return & MultiFileDiffReader {reader : newLineReader (r )}
30+ return NewMultiFileDiffReaderOptions (r , ParseOptions {})
31+ }
32+
33+ // NewMultiFileDiffReaderOptions returns a new MultiFileDiffReader that reads
34+ // a multi-file unified diff from r with the given options.
35+ func NewMultiFileDiffReaderOptions (r io.Reader , opts ParseOptions ) * MultiFileDiffReader {
36+ return & MultiFileDiffReader {reader : newLineReaderOptions (r , opts )}
2737}
2838
2939// MultiFileDiffReader reads a multi-file unified diff.
@@ -153,13 +163,24 @@ func (r *MultiFileDiffReader) ReadAllFiles() ([]*FileDiff, error) {
153163
154164// ParseFileDiff parses a file unified diff.
155165func ParseFileDiff (diff []byte ) (* FileDiff , error ) {
156- return NewFileDiffReader (bytes .NewReader (diff )).Read ()
166+ return ParseFileDiffOptions (diff , ParseOptions {})
167+ }
168+
169+ // ParseFileDiffOptions parses a file unified diff with the given options.
170+ func ParseFileDiffOptions (diff []byte , opts ParseOptions ) (* FileDiff , error ) {
171+ return NewFileDiffReaderOptions (bytes .NewReader (diff ), opts ).Read ()
157172}
158173
159174// NewFileDiffReader returns a new FileDiffReader that reads a file
160175// unified diff.
161176func NewFileDiffReader (r io.Reader ) * FileDiffReader {
162- return & FileDiffReader {reader : & lineReader {reader : bufio .NewReader (r )}}
177+ return NewFileDiffReaderOptions (r , ParseOptions {})
178+ }
179+
180+ // NewFileDiffReaderOptions returns a new FileDiffReader that reads a file
181+ // unified diff with the given options.
182+ func NewFileDiffReaderOptions (r io.Reader , opts ParseOptions ) * FileDiffReader {
183+ return & FileDiffReader {reader : newLineReaderOptions (r , opts )}
163184}
164185
165186// FileDiffReader reads a unified file diff.
@@ -405,6 +426,7 @@ func readQuotedFilename(text string) (value string, remainder string, err error)
405426// valid syntax, it may be impossible to extract filenames; if so, the
406427// function returns ("", "", true).
407428func parseDiffGitArgs (diffArgs string ) (string , string , bool ) {
429+ diffArgs = strings .TrimSuffix (diffArgs , "\r " )
408430 length := len (diffArgs )
409431 if length < 3 {
410432 return "" , "" , false
@@ -540,6 +562,7 @@ func handleEmpty(fd *FileDiff) (wasEmpty bool) {
540562 return
541563 }
542564 rawFilename := header [len (prefix ):]
565+ rawFilename = strings .TrimSuffix (rawFilename , "\r " )
543566
544567 // extract the filename prefix (e.g. "a/") from the 'diff --git' line.
545568 var prefixLetterIndex int
@@ -586,7 +609,12 @@ var (
586609// only of hunks and not include a file header; if it has a file
587610// header, use ParseFileDiff.
588611func ParseHunks (diff []byte ) ([]* Hunk , error ) {
589- r := NewHunksReader (bytes .NewReader (diff ))
612+ return ParseHunksOptions (diff , ParseOptions {})
613+ }
614+
615+ // ParseHunksOptions parses hunks from a unified diff with the given options.
616+ func ParseHunksOptions (diff []byte , opts ParseOptions ) ([]* Hunk , error ) {
617+ r := NewHunksReaderOptions (bytes .NewReader (diff ), opts )
590618 hunks , err := r .ReadAllHunks ()
591619 if err != nil {
592620 return nil , err
@@ -597,7 +625,13 @@ func ParseHunks(diff []byte) ([]*Hunk, error) {
597625// NewHunksReader returns a new HunksReader that reads unified diff hunks
598626// from r.
599627func NewHunksReader (r io.Reader ) * HunksReader {
600- return & HunksReader {reader : & lineReader {reader : bufio .NewReader (r )}}
628+ return NewHunksReaderOptions (r , ParseOptions {})
629+ }
630+
631+ // NewHunksReaderOptions returns a new HunksReader that reads unified diff hunks
632+ // from r with the given options.
633+ func NewHunksReaderOptions (r io.Reader , opts ParseOptions ) * HunksReader {
634+ return & HunksReader {reader : newLineReaderOptions (r , opts )}
601635}
602636
603637// A HunksReader reads hunks from a unified diff.
@@ -701,7 +735,7 @@ func (r *HunksReader) ReadHunk() (*Hunk, error) {
701735 // handle that case.
702736 return r .hunk , & ParseError {r .line , r .offset , & ErrBadHunkLine {Line : line }}
703737 }
704- if bytes .Equal (line , []byte (noNewlineMessage )) {
738+ if bytes .Equal (bytes . TrimSuffix ( line , [] byte ( " \r " )) , []byte (noNewlineMessage )) {
705739 if lastLineFromOrig {
706740 // Retain the newline in the body (otherwise the
707741 // diff line would be like "-a+b", where "+b" is
@@ -755,6 +789,7 @@ func linePrefix(c byte) bool {
755789// if its value is 1. normalizeHeader returns an error if the header
756790// is not in the correct format.
757791func normalizeHeader (header string ) (string , string , error ) {
792+ header = strings .TrimSuffix (header , "\r " )
758793 // Split the header into five parts: the first '@@', the two
759794 // ranges, the last '@@', and the optional section.
760795 pieces := strings .SplitN (header , " " , 5 )
@@ -815,7 +850,8 @@ func parseOnlyInMessage(line []byte) (bool, []byte, []byte) {
815850 if idx < 0 {
816851 return false , nil , nil
817852 }
818- return true , line [:idx ], line [idx + 2 :]
853+ filename := bytes .TrimSuffix (line [idx + 2 :], []byte ("\r " ))
854+ return true , line [:idx ], filename
819855}
820856
821857// A ParseError is a description of a unified diff syntax error.
0 commit comments