From 43a997529328c0ebbe50b79ccb6ad830abbcd983 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 31 Aug 2021 19:54:25 -0600 Subject: Fix that failing test --- backend.go | 4 ++-- cmd.go | 15 ++++++++++++--- cmd_command.go | 23 ++++++++++++----------- cmd_comment.go | 23 +++++++++++++++++++---- cmd_incommit.go | 16 ++++++++-------- parse_fastimport.go | 33 +++++++++++++++++++++++++-------- 6 files changed, 78 insertions(+), 36 deletions(-) diff --git a/backend.go b/backend.go index c91d0ac..cb3439e 100644 --- a/backend.go +++ b/backend.go @@ -90,9 +90,9 @@ func (b *Backend) Do(cmd Cmd) error { } switch { - case !cmdIs(cmd, cmdClassInCommit): + case !cmdIs(noopReaderState{}, cmd, cmdClassInCommit): _, b.inCommit = cmd.(CmdCommit) - case !b.inCommit && !cmdIs(cmd, cmdClassCommand): + case !b.inCommit && !cmdIs(noopReaderState{}, cmd, cmdClassCommand): panic(errors.Errorf("Cannot issue commit sub-command outside of a commit: %[1]T(%#[1]v)", cmd)) } diff --git a/cmd.go b/cmd.go index 73ea14c..77b1d67 100644 --- a/cmd.go +++ b/cmd.go @@ -33,6 +33,11 @@ package libfastimport type fiReader interface { PeekLine() (string, error) ReadLine() (string, error) + SetCommandMark(int) +} + +type fiReaderState interface { + GetCommandMark() int } type fiWriter interface { @@ -54,9 +59,13 @@ const ( type Cmd interface { fiCmdRead(fiReader) (Cmd, error) fiCmdWrite(fiWriter) error - fiCmdClass() cmdClass + fiCmdClass(fiReaderState) cmdClass } -func cmdIs(cmd Cmd, class cmdClass) bool { - return cmd.fiCmdClass()&class != 0 +type noopReaderState struct{} + +func (_ noopReaderState) GetCommandMark() int { return 0 } + +func cmdIs(state fiReaderState, cmd Cmd, class cmdClass) bool { + return cmd.fiCmdClass(state)&class != 0 } diff --git a/cmd_command.go b/cmd_command.go index 819d6eb..5698efa 100644 --- a/cmd_command.go +++ b/cmd_command.go @@ -48,7 +48,7 @@ type CmdCommit struct { Merge []string } -func (c CmdCommit) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdCommit) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdCommit) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} @@ -93,6 +93,7 @@ func (CmdCommit) fiCmdRead(fir fiReader) (cmd Cmd, err error) { c.Mark, err = strconv.Atoi(trimLinePrefix(ez.ReadLine(), "mark :")) ez.Errcheck(err) } + fir.SetCommandMark(c.Mark) // original-oid? if strings.HasPrefix(ez.PeekLine(), "original-oid ") { @@ -152,7 +153,7 @@ func (CmdCommit) fiCmdRead(fir fiReader) (cmd Cmd, err error) { // Backend. type CmdCommitEnd struct{} -func (CmdCommitEnd) fiCmdClass() cmdClass { return cmdClassInCommit } +func (CmdCommitEnd) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (CmdCommitEnd) fiCmdWrite(fiw fiWriter) error { return nil } func (CmdCommitEnd) fiCmdRead(fir fiReader) (Cmd, error) { panic("not reached") } @@ -172,7 +173,7 @@ type CmdTag struct { Data string } -func (c CmdTag) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdTag) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdTag) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} @@ -249,7 +250,7 @@ type CmdReset struct { CommitIsh string // optional } -func (c CmdReset) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdReset) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdReset) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} @@ -289,7 +290,7 @@ type CmdBlob struct { Data string } -func (c CmdBlob) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdBlob) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdBlob) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} @@ -340,7 +341,7 @@ type CmdAlias struct { CommitIsh string } -func (c CmdAlias) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdAlias) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdAlias) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} ez.WriteLine("alias") @@ -379,7 +380,7 @@ func (CmdAlias) fiCmdRead(fir fiReader) (cmd Cmd, err error) { // CmdCheckpoint requests that the Backend flush already-sent data. type CmdCheckpoint struct{} -func (c CmdCheckpoint) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdCheckpoint) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdCheckpoint) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("checkpoint") } @@ -400,7 +401,7 @@ type CmdProgress struct { Str string } -func (c CmdProgress) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdProgress) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdProgress) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("progress", c.Str) } @@ -422,7 +423,7 @@ type CmdFeature struct { Argument string } -func (c CmdFeature) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdFeature) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdFeature) fiCmdWrite(fiw fiWriter) error { if c.Argument != "" { return fiw.WriteLine("feature", c.Feature+"="+c.Argument) @@ -456,7 +457,7 @@ type CmdOption struct { Option string } -func (c CmdOption) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdOption) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdOption) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("option", c.Option) } @@ -476,7 +477,7 @@ func (CmdOption) fiCmdRead(fir fiReader) (cmd Cmd, err error) { // sent. type CmdDone struct{} -func (c CmdDone) fiCmdClass() cmdClass { return cmdClassCommand } +func (c CmdDone) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassCommand } func (c CmdDone) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("done") } diff --git a/cmd_comment.go b/cmd_comment.go index 684c92b..3e50b9a 100644 --- a/cmd_comment.go +++ b/cmd_comment.go @@ -33,7 +33,7 @@ type CmdComment struct { Comment string } -func (c CmdComment) fiCmdClass() cmdClass { return cmdClassComment } +func (c CmdComment) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassComment } func (c CmdComment) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("#" + c.Comment) } @@ -55,12 +55,15 @@ type CmdGetMark struct { Mark int } -func (c CmdGetMark) fiCmdClass() cmdClass { +func (c CmdGetMark) fiCmdClass(fir fiReaderState) cmdClass { // Prior to git v2.22.0 this was 'cmdClassComment', but in // v2.22.0 it was changed to a stricter // 'cmdClassCommand|cmdClassInCommit'. I want to have better // backward compatibility, so I'm keeping it as // 'cmdClassComment'. + if c.Mark == fir.GetCommandMark() { + return cmdClassCommand + } return cmdClassComment } func (c CmdGetMark) fiCmdWrite(fiw fiWriter) error { @@ -90,13 +93,19 @@ type CmdCatBlob struct { DataRef string } -func (c CmdCatBlob) fiCmdClass() cmdClass { +func (c CmdCatBlob) fiCmdClass(fir fiReaderState) cmdClass { // Prior to git v2.22.0 this was 'cmdClassComment', but in // v2.22.0 it was changed to a stricter // 'cmdClassCommand|cmdClassInCommit|cmdClassInFileModify'. I // don't want to implement cmdClassInFileModify for just this // one command, and also I want to have better backward // compatibility; so I'm keeping it as 'cmdClassComment'. + if strings.HasPrefix(c.DataRef, ":") && fir.GetCommandMark() > 0 { + mark, _ := strconv.Atoi(c.DataRef[1:]) + if mark == fir.GetCommandMark() { + return cmdClassCommand + } + } return cmdClassComment } func (c CmdCatBlob) fiCmdWrite(fiw fiWriter) error { @@ -124,7 +133,7 @@ type CmdLs struct { Path Path } -func (c CmdLs) fiCmdClass() cmdClass { +func (c CmdLs) fiCmdClass(fir fiReaderState) cmdClass { // Prior to git v2.22.0 the docs said 'ls' was allowed // anywhere a comment was allowed, but that was never really // true, and in v2.22.0 the docs were updated to match the @@ -136,6 +145,12 @@ func (c CmdLs) fiCmdClass() cmdClass { // cmdClassInCommand bit. return cmdClassInCommit } + if strings.HasPrefix(c.DataRef, ":") && fir.GetCommandMark() > 0 { + mark, _ := strconv.Atoi(c.DataRef[1:]) + if mark == fir.GetCommandMark() { + return cmdClassCommand + } + } return cmdClassCommand | cmdClassInCommit } func (c CmdLs) fiCmdWrite(fiw fiWriter) error { diff --git a/cmd_incommit.go b/cmd_incommit.go index c8ae15f..aea1566 100644 --- a/cmd_incommit.go +++ b/cmd_incommit.go @@ -37,7 +37,7 @@ type FileModify struct { DataRef string } -func (o FileModify) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileModify) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o FileModify) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("M", o.Mode, o.DataRef, o.Path) } @@ -98,7 +98,7 @@ type FileModifyInline struct { Data string } -func (o FileModifyInline) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileModifyInline) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o FileModifyInline) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} ez.WriteLine("M", o.Mode, "inline", o.Path) @@ -115,7 +115,7 @@ type FileDelete struct { Path Path } -func (o FileDelete) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileDelete) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o FileDelete) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("D", o.Path) } @@ -138,7 +138,7 @@ type FileCopy struct { Dst Path } -func (o FileCopy) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileCopy) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o FileCopy) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("C", o.Src, o.Dst) } @@ -158,7 +158,7 @@ type FileRename struct { Dst string } -func (o FileRename) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileRename) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o FileRename) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("R", o.Src, o.Dst) } @@ -175,7 +175,7 @@ func (FileRename) fiCmdRead(fir fiReader) (cmd Cmd, err error) { // CmdCommit. type FileDeleteAll struct{} -func (o FileDeleteAll) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileDeleteAll) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o FileDeleteAll) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("deleteall") } @@ -203,7 +203,7 @@ type NoteModify struct { DataRef string } -func (o NoteModify) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o NoteModify) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o NoteModify) fiCmdWrite(fiw fiWriter) error { return fiw.WriteLine("N", o.DataRef, o.CommitIsh) } @@ -257,7 +257,7 @@ type NoteModifyInline struct { Data string } -func (o NoteModifyInline) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o NoteModifyInline) fiCmdClass(_ fiReaderState) cmdClass { return cmdClassInCommit } func (o NoteModifyInline) fiCmdWrite(fiw fiWriter) error { ez := &ezfiw{fiw: fiw} ez.WriteLine("N", "inline", o.CommitIsh) diff --git a/parse_fastimport.go b/parse_fastimport.go index 7f84dfd..422f261 100644 --- a/parse_fastimport.go +++ b/parse_fastimport.go @@ -27,7 +27,7 @@ var parser_regularCmds = make(map[string]Cmd) var parser_commentCmds = make(map[string]Cmd) func parser_registerCmd(prefix string, cmd Cmd) { - if cmdIs(cmd, cmdClassInCommand) { + if cmdIs(noopReaderState{}, cmd, cmdClassInCommand) { parser_commentCmds[prefix] = cmd } else { parser_regularCmds[prefix] = cmd @@ -76,7 +76,8 @@ func parser_compile(cmds map[string]Cmd) func(line string) func(fiReader) (Cmd, type parser struct { fir *textproto.FIReader - inCommit bool + inCommit bool + commandMark int buf_line *string buf_err error @@ -130,15 +131,23 @@ func (p *parser) parse() error { return err } + // I've tried many times to rewrite this to be more + // readable. I have failed each time. switch { - case !cmdIs(cmd, cmdClassInCommit): - if p.inCommit { - p.ret_cmd <- CmdCommitEnd{} - } - _, p.inCommit = cmd.(CmdCommit) - case !p.inCommit && !cmdIs(cmd, cmdClassCommand): + case p.inCommit && !cmdIs(p, cmd, cmdClassInCommit): + p.ret_cmd <- CmdCommitEnd{} + p.inCommit = false + case !p.inCommit && !cmdIs(p, cmd, cmdClassCommand): return errors.Errorf("Got in-commit-only command outside of a commit: %[1]T(%#[1]v)", cmd) } + if _, newCommit := cmd.(CmdCommit); newCommit { + p.inCommit = true + // DO NOT reset p.commandMark; cmd.fiCmdRead + // already did that. + } + if !p.inCommit { + p.commandMark = 0 + } p.ret_cmd <- cmd } @@ -171,3 +180,11 @@ func (p *parser) ReadLine() (string, error) { p.buf_err = nil return line, err } + +func (p *parser) SetCommandMark(mark int) { + p.commandMark = mark +} + +func (p *parser) GetCommandMark() int { + return p.commandMark +} -- cgit v1.2.3