summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend.go4
-rw-r--r--cmd.go15
-rw-r--r--cmd_command.go23
-rw-r--r--cmd_comment.go23
-rw-r--r--cmd_incommit.go16
-rw-r--r--parse_fastimport.go33
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
+}