From 3efa1fc8a98d2d90c204c7bd5a0e2519e1ac7745 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Wed, 22 Nov 2017 22:04:14 -0500 Subject: split the parser up, and have read methods like write emethods --- cmd.go | 6 + cmd_command.go | 189 +++++++++++++++++++++++++++ cmd_comment.go | 67 +++++++++- cmd_commit.go | 119 +++++++++++++++++ ez.go | 65 +++++++++ ezfiw.go | 30 ----- frontend.go | 369 ++++------------------------------------------------ parse_fastimport.go | 162 +++++++++++++++++++++++ textproto/io.go | 3 + 9 files changed, 634 insertions(+), 376 deletions(-) create mode 100644 ez.go delete mode 100644 ezfiw.go create mode 100644 parse_fastimport.go diff --git a/cmd.go b/cmd.go index 7ba40e0..5e76708 100644 --- a/cmd.go +++ b/cmd.go @@ -4,6 +4,11 @@ import ( "git.lukeshu.com/go/libfastimport/textproto" ) +type fiReader interface { + PeekLine() (string, error) + ReadLine() (string, error) +} + type cmdClass int const ( @@ -14,6 +19,7 @@ const ( ) type Cmd interface { + fiCmdRead(fiReader) (Cmd, error) fiCmdWrite(*textproto.FIWriter) error fiCmdClass() cmdClass } diff --git a/cmd_command.go b/cmd_command.go index a1d1a41..b438cb6 100644 --- a/cmd_command.go +++ b/cmd_command.go @@ -1,9 +1,15 @@ package libfastimport import ( + "fmt" + "strconv" + "strings" + "git.lukeshu.com/go/libfastimport/textproto" ) +// commit ////////////////////////////////////////////////////////////////////// + type CmdCommit struct { Ref string Mark int // optional; < 1 for non-use @@ -36,6 +42,59 @@ func (c CmdCommit) fiCmdWrite(fiw *textproto.FIWriter) error { return ez.err } +func init() { parser_registerCmd("commit ", CmdCommit{}) } +func (CmdCommit) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + ez := &ezfir{fir: fir} + defer func() { err = ez.Defer() }() + + // 'commit' SP LF + c := CmdCommit{Ref: trimLinePrefix(ez.ReadLine(), "commit ")} + + // mark? + if strings.HasPrefix(ez.PeekLine(), "mark :") { + c.Mark, err = strconv.Atoi(trimLinePrefix(ez.ReadLine(), "mark :")) + ez.Errcheck(err) + } + + // ('author' (SP )? SP LT GT SP LF)? + if strings.HasPrefix(ez.PeekLine(), "author ") { + author, err := textproto.ParseIdent(trimLinePrefix(ez.ReadLine(), "author ")) + ez.Errcheck(err) + c.Author = &author + } + + // 'committer' (SP )? SP LT GT SP LF + if !strings.HasPrefix(ez.PeekLine(), "committer ") { + ez.Errcheck(fmt.Errorf("commit: expected committer command: %v", ez.ReadLine())) + } + c.Committer, err = textproto.ParseIdent(trimLinePrefix(ez.ReadLine(), "committer ")) + ez.Errcheck(err) + + // data + c.Msg, err = parse_data(ez.ReadLine()) + ez.Errcheck(err) + + // ('from' SP LF)? + if strings.HasPrefix(ez.PeekLine(), "from ") { + c.From = trimLinePrefix(ez.ReadLine(), "from ") + } + + // ('merge' SP LF)* + for strings.HasPrefix(ez.PeekLine(), "merge ") { + c.Merge = append(c.Merge, trimLinePrefix(ez.ReadLine(), "merge ")) + } + + cmd = c + return +} + +type CmdCommitEnd struct{} + +func (CmdCommitEnd) fiCmdClass() cmdClass { return cmdClassCommit } +func (CmdCommitEnd) fiCmdWrite(fiw *textproto.FIWriter) error { return nil } +func (CmdCommitEnd) fiCmdRead(fir fiReader) (Cmd, error) { panic("not reached") } + +// tag ///////////////////////////////////////////////////////////////////////// type CmdTag struct { RefName string @@ -55,6 +114,36 @@ func (c CmdTag) fiCmdWrite(fiw *textproto.FIWriter) error { return ez.err } +func init() { parser_registerCmd("tag ", CmdTag{}) } +func (CmdTag) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + ez := &ezfir{fir: fir} + defer func() { err = ez.Defer() }() + + // 'tag' SP LF + c := CmdTag{RefName: trimLinePrefix(ez.ReadLine(), "tag ")} + + // 'from' SP LF + if !strings.HasPrefix(ez.PeekLine(), "from ") { + ez.Errcheck(fmt.Errorf("tag: expected from command: %v", ez.ReadLine())) + } + c.CommitIsh = trimLinePrefix(ez.ReadLine(), "from ") + + // 'tagger' (SP )? SP LT GT SP LF + if !strings.HasPrefix(ez.PeekLine(), "tagger ") { + ez.Errcheck(fmt.Errorf("tag: expected tagger command: %v", ez.ReadLine())) + } + c.Tagger, err = textproto.ParseIdent(trimLinePrefix(ez.ReadLine(), "tagger ")) + ez.Errcheck(err) + + // data + c.Data, err = parse_data(ez.ReadLine()) + ez.Errcheck(err) + + cmd = c + return +} + +// reset /////////////////////////////////////////////////////////////////////// type CmdReset struct { RefName string @@ -72,6 +161,24 @@ func (c CmdReset) fiCmdWrite(fiw *textproto.FIWriter) error { return ez.err } +func init() { parser_registerCmd("reset ", CmdReset{}) } +func (CmdReset) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + ez := &ezfir{fir: fir} + defer func() { err = ez.Defer() }() + + // 'reset' SP LF + c := CmdReset{RefName: trimLinePrefix(ez.ReadLine(), "reset ")} + + // ('from' SP LF)? + if strings.HasPrefix(ez.PeekLine(), "from ") { + c.CommitIsh = trimLinePrefix(ez.ReadLine(), "from ") + } + + cmd = c + return +} + +// blob //////////////////////////////////////////////////////////////////////// type CmdBlob struct { Mark int @@ -90,6 +197,29 @@ func (c CmdBlob) fiCmdWrite(fiw *textproto.FIWriter) error { return ez.err } +func init() { parser_registerCmd("blob\n", CmdBlob{}) } +func (CmdBlob) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + ez := &ezfir{fir: fir} + defer func() { err = ez.Defer() }() + + // 'blob' LF + _ = ez.ReadLine() + c := CmdBlob{} + + // mark? + if strings.HasPrefix(ez.PeekLine(), "mark :") { + c.Mark, err = strconv.Atoi(trimLinePrefix(ez.ReadLine(), "mark :")) + } + + // data + c.Data, err = parse_data(ez.ReadLine()) + ez.Errcheck(err) + + cmd = c + return +} + +// checkpoint ////////////////////////////////////////////////////////////////// type CmdCheckpoint struct{} @@ -97,6 +227,16 @@ func (c CmdCheckpoint) fiCmdClass() cmdClass { return cmdClassCommand } func (c CmdCheckpoint) fiCmdWrite(fiw *textproto.FIWriter) error { return fiw.WriteLine("checkpoint") } +func init() { parser_registerCmd("checkpoint\n", CmdCheckpoint{}) } +func (CmdCheckpoint) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + _, err = fir.ReadLine() + if err != nil { + return nil, err + } + return CmdCheckpoint{}, nil +} + +// progress //////////////////////////////////////////////////////////////////// type CmdProgress struct { Str string @@ -106,6 +246,16 @@ func (c CmdProgress) fiCmdClass() cmdClass { return cmdClassCommand } func (c CmdProgress) fiCmdWrite(fiw *textproto.FIWriter) error { return fiw.WriteLine("progress", c.Str) } +func init() { parser_registerCmd("progress ", CmdProgress{}) } +func (CmdProgress) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + line, err := fir.ReadLine() + if err != nil { + return nil, err + } + return CmdProgress{Str: trimLinePrefix(line, "progress ")}, nil +} + +// feature ///////////////////////////////////////////////////////////////////// type CmdFeature struct { Feature string @@ -120,6 +270,26 @@ func (c CmdFeature) fiCmdWrite(fiw *textproto.FIWriter) error { return fiw.WriteLine("feature", c.Feature) } } +func init() { parser_registerCmd("feature ", CmdFeature{}) } +func (CmdFeature) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + // 'feature' SP ('=' )? LF + line, err := fir.ReadLine() + if err != nil { + return nil, err + } + str := trimLinePrefix(line, "feature ") + eq := strings.IndexByte(str, '=') + if eq < 0 { + return CmdFeature{Feature: str}, nil + } else { + return CmdFeature{ + Feature: str[:eq], + Argument: str[eq+1:], + }, nil + } +} + +// option ////////////////////////////////////////////////////////////////////// type CmdOption struct { Option string @@ -129,6 +299,17 @@ func (c CmdOption) fiCmdClass() cmdClass { return cmdClassCommand } func (c CmdOption) fiCmdWrite(fiw *textproto.FIWriter) error { return fiw.WriteLine("option", c.Option) } +func init() { parser_registerCmd("option ", CmdOption{}) } +func (CmdOption) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + // 'option' SP