From bca8d0806e3b1b8e6478b8262155ea41a67afef0 Mon Sep 17 00:00:00 2001 From: Billy Keyes Date: Thu, 14 Mar 2019 21:55:06 -0700 Subject: [PATCH] Detach parseFragmentHeader from parser struct This operates on a single line and doesn't need any parser state. --- gitdiff/parser.go | 73 +++++++++++++++++++++--------------------- gitdiff/parser_test.go | 5 +-- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/gitdiff/parser.go b/gitdiff/parser.go index 074c567..b08a2b7 100644 --- a/gitdiff/parser.go +++ b/gitdiff/parser.go @@ -75,7 +75,7 @@ func (p *parser) ParseNextFileHeader() (file *File, err error) { // check for disconnected fragment headers (corrupt patch) if isMaybeFragmentHeader(line) { var frag Fragment - if err := p.ParseFragmentHeader(&frag, line); err != nil { + if err := parseFragmentHeader(&frag, line); err != nil { // not a valid header, nothing to worry about continue } @@ -134,41 +134,6 @@ func (p *parser) ParseTraditionalFileHeader(f *File, oldFile, newFile string) er panic("unimplemented") } -func (p *parser) ParseFragmentHeader(f *Fragment, header string) error { - match := fragmentHeaderRegexp.FindStringSubmatch(header) - if len(match) < 5 { - return p.Errorf("invalid fragment header") - } - - parseInt := func(s string, v *int64) (err error) { - if *v, err = strconv.ParseInt(s, 10, 64); err != nil { - nerr := err.(*strconv.NumError) - return p.Errorf("invalid fragment header value: %s: %v", s, nerr.Err) - } - return - } - - if err := parseInt(match[1], &f.OldPosition); err != nil { - return err - } - if err := parseInt(match[2], &f.OldLines); err != nil { - return err - } - - if err := parseInt(match[3], &f.NewPosition); err != nil { - return err - } - - f.NewLines = 1 - if match[4] != "" { - if err := parseInt(match[4], &f.NewLines); err != nil { - return err - } - } - - return nil -} - // Line reads and returns the next line. The first call to Line after a call to // PeekLine will never retrun an error. func (p *parser) Line() (line string, err error) { @@ -202,3 +167,39 @@ func isMaybeFragmentHeader(line string) bool { shortestValidHeader := "@@ -0,0 +1 @@\n" return len(line) >= len(shortestValidHeader) && strings.HasPrefix(line, fragmentHeaderPrefix) } + +func parseFragmentHeader(f *Fragment, header string) error { + // TODO(bkeyes): use strings.FieldsFunc instead of regexp + match := fragmentHeaderRegexp.FindStringSubmatch(header) + if len(match) < 5 { + return fmt.Errorf("invalid fragment header") + } + + parseInt := func(s string, v *int64) (err error) { + if *v, err = strconv.ParseInt(s, 10, 64); err != nil { + nerr := err.(*strconv.NumError) + return fmt.Errorf("invalid fragment header value: %s: %v", s, nerr.Err) + } + return + } + + if err := parseInt(match[1], &f.OldPosition); err != nil { + return err + } + if err := parseInt(match[2], &f.OldLines); err != nil { + return err + } + + if err := parseInt(match[3], &f.NewPosition); err != nil { + return err + } + + f.NewLines = 1 + if match[4] != "" { + if err := parseInt(match[4], &f.NewLines); err != nil { + return err + } + } + + return nil +} diff --git a/gitdiff/parser_test.go b/gitdiff/parser_test.go index 60a98bc..474e767 100644 --- a/gitdiff/parser_test.go +++ b/gitdiff/parser_test.go @@ -109,11 +109,8 @@ func TestParseFragmentHeader(t *testing.T) { for _, test := range tests { t.Run(test.Name, func(t *testing.T) { - p := &parser{r: bufio.NewReader(strings.NewReader(test.Input))} - line, _ := p.Line() - var frag Fragment - err := p.ParseFragmentHeader(&frag, line) + err := parseFragmentHeader(&frag, test.Input) if test.Invalid { if err == nil {