From 01ed9a06b20d32b148446d715d6e1beb3050d069 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 1 Feb 2021 15:55:03 -0700 Subject: Tidy up cmdClass --- backend.go | 16 +--- cmd.go | 13 ++- cmd_command.go | 4 +- cmd_comment.go | 24 ++--- cmd_commit.go | 267 ---------------------------------------------------- cmd_incommit.go | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++ parse_fastimport.go | 25 ++--- 7 files changed, 304 insertions(+), 312 deletions(-) delete mode 100644 cmd_commit.go create mode 100644 cmd_incommit.go diff --git a/backend.go b/backend.go index 0486e98..c91d0ac 100644 --- a/backend.go +++ b/backend.go @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Luke Shumaker +// Copyright (C) 2017-2018, 2021 Luke Shumaker // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -89,17 +89,11 @@ func (b *Backend) Do(cmd Cmd) error { return b.err } - switch cmd.fiCmdClass() { - case cmdClassCommand: + switch { + case !cmdIs(cmd, cmdClassInCommit): _, b.inCommit = cmd.(CmdCommit) - case cmdClassCommit: - if !b.inCommit { - panic(errors.Errorf("Cannot issue commit sub-command outside of a commit: %[1]T(%#[1]v)", cmd)) - } - case cmdClassComment: - /* do nothing */ - default: - panic(errors.Errorf("invalid cmdClass: %d", cmd.fiCmdClass())) + case !b.inCommit && !cmdIs(cmd, cmdClassCommand): + panic(errors.Errorf("Cannot issue commit sub-command outside of a commit: %[1]T(%#[1]v)", cmd)) } err := cmd.fiCmdWrite(b.fastImportWrite) diff --git a/cmd.go b/cmd.go index 1665081..d1358a8 100644 --- a/cmd.go +++ b/cmd.go @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Luke Shumaker +// Copyright (C) 2017-2018, 2021 Luke Shumaker // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -41,10 +41,11 @@ type fiWriter interface { type cmdClass int const ( - cmdClassCommand cmdClass = 1 // may be a top-level command - cmdClassCommit cmdClass = 2 // may be used within in a commit + cmdClassCommand cmdClass = 1 << iota // can be a top-level command + cmdClassInCommit // can be used within in a commit + cmdClassInCommand // can be used in-between lines of another multi-line command - cmdClassComment cmdClass = cmdClassCommand | cmdClassCommit + cmdClassComment = cmdClassCommand | cmdClassInCommit | cmdClassInCommand // "can be used anywhere in the stream that comments are accepted" ) // Cmd is a command that may be found in a fast-import stream. @@ -53,3 +54,7 @@ type Cmd interface { fiCmdWrite(fiWriter) error fiCmdClass() cmdClass } + +func cmdIs(cmd Cmd, class cmdClass) bool { + return cmd.fiCmdClass()&class != 0 +} diff --git a/cmd_command.go b/cmd_command.go index ff74f80..a958b60 100644 --- a/cmd_command.go +++ b/cmd_command.go @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Luke Shumaker +// Copyright (C) 2017-2018, 2021 Luke Shumaker // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -119,7 +119,7 @@ func (CmdCommit) fiCmdRead(fir fiReader) (cmd Cmd, err error) { // Backend. type CmdCommitEnd struct{} -func (CmdCommitEnd) fiCmdClass() cmdClass { return cmdClassCommit } +func (CmdCommitEnd) fiCmdClass() cmdClass { return cmdClassInCommit } func (CmdCommitEnd) fiCmdWrite(fiw fiWriter) error { return nil } func (CmdCommitEnd) fiCmdRead(fir fiReader) (Cmd, error) { panic("not reached") } diff --git a/cmd_comment.go b/cmd_comment.go index c0325b4..2124c8e 100644 --- a/cmd_comment.go +++ b/cmd_comment.go @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Luke Shumaker +// Copyright (C) 2017-2018, 2021 Luke Shumaker // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -22,6 +22,10 @@ import ( "github.com/pkg/errors" ) +// This file deals with comments, and with commands for which the +// specification says (or said) that the command "can be used anywhere +// in the stream that comments are accepted". + // comment ///////////////////////////////////////////////////////////////////// // CmdComment is a comment line; not a real command. @@ -105,19 +109,17 @@ type CmdLs struct { Path Path } -// If you're thinking "but wait, parser_registerCmd will see CmdLs as -// cmdClassCommit, not cmdClassComment, that means it won't be allowed -// embedded inside other commands! (while still allowing it both -// inside and outside of a commit)", you're absolutely correct. -// That's the desired behavior. It's a happy accident that the little -// fiCmdClass hack works out that way, instead of having to add even -// more complexity. - func (c CmdLs) fiCmdClass() cmdClass { + // As of git v2.21, the docs say this is cmdClassComment, but + // the actual code disagrees. if c.DataRef == "" { - return cmdClassCommit + // Yeah, this will give slightly misleading info to + // parser_registerCmd(), but that's OK, + // parser_registerCmd() only really cares about the + // cmdClassInCommand bit. + return cmdClassInCommit } - return cmdClassComment + return cmdClassCommand | cmdClassInCommit } func (c CmdLs) fiCmdWrite(fiw fiWriter) error { if c.DataRef == "" { diff --git a/cmd_commit.go b/cmd_commit.go deleted file mode 100644 index 170c511..0000000 --- a/cmd_commit.go +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (C) 2017-2018 Luke Shumaker -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package libfastimport - -import ( - "strconv" - "strings" - - "github.com/pkg/errors" -) - -// M /////////////////////////////////////////////////////////////////////////// - -// FileModify appears after a CmdCommit (and before a CmdCommitEnd), -// and causes the CmdCommit to add a new file or change the content of -// an existing file. The content of the file is specified by giving -// either a mark reference (":") or by a full 40-byte SHA-1. -// -// To specify the full content of the file inline, use -// FileModifyInline instead. -type FileModify struct { - Mode Mode - Path Path - DataRef string -} - -func (o FileModify) fiCmdClass() cmdClass { return cmdClassCommit } -func (o FileModify) fiCmdWrite(fiw fiWriter) error { - return fiw.WriteLine("M", o.Mode, o.DataRef, o.Path) -} -func init() { parser_registerCmd("M ", FileModify{}) } -func (FileModify) fiCmdRead(fir fiReader) (cmd Cmd, err error) { - // NB: This parses both FileModify and FileModifyInline - line, err := fir.ReadLine() - if err != nil { - return nil, err - } - str := trimLinePrefix(line, "M ") - fields := strings.SplitN(str, " ", 3) - if len(fields) != 3 { - return nil, errors.Errorf("commit: malformed modify command: %v", line) - } - - nMode, err := strconv.ParseUint(fields[0], 8, 18) - if err != nil { - return nil, err - } - - ref := fields[1] - path := PathUnescape(fields[2]) - - if ref == "inline" { - line, err = fir.ReadLine() - if err != nil { - return nil, err - } - data, err := parse_data(line) - if err != nil { - return nil, err - } - return FileModifyInline{ - Mode: Mode(nMode), - Path: path, - Data: data, - }, nil - } else { - return FileModify{ - Mode: Mode(nMode), - Path: path, - DataRef: ref, - }, nil - } -} - -// FileModifyInline appears after a CmdCommit (and before a -// CmdCommitEnd), and causes the CmdCommit to add a new file or change -// the content of an existing file. The full content of the file are -// specified directly -// -// To instead specify the content with a mark reference (":") -// or with a full 40-byte SHA-1, use FileModify instead. -type FileModifyInline struct { - Mode Mode - Path Path - Data string -} - -func (o FileModifyInline) fiCmdClass() cmdClass { return cmdClassCommit } -func (o FileModifyInline) fiCmdWrite(fiw fiWriter) error { - ez := &ezfiw{fiw: fiw} - ez.WriteLine("M", o.Mode, "inline", o.Path) - ez.WriteData(o.Data) - return ez.err -} -func (FileModifyInline) fiCmdRead(fiReader) (Cmd, error) { panic("not reached") } - -// D /////////////////////////////////////////////////////////////////////////// - -// FileDelete appears after a CmdCommit (and before a CmdCommitEnd), -// and causes the CmdCommit to recursively remove a file or directory. -type FileDelete struct { - Path Path -} - -func (o FileDelete) fiCmdClass() cmdClass { return cmdClassCommit } -func (o FileDelete) fiCmdWrite(fiw fiWriter) error { - return fiw.WriteLine("D", o.Path) -} -func init() { parser_registerCmd("D ", FileDelete{}) } -func (FileDelete) fiCmdRead(fir fiReader) (cmd Cmd, err error) { - line, err := fir.ReadLine() - if err != nil { - return nil, err - } - return FileDelete{Path: PathUnescape(trimLinePrefix(line, "D "))}, nil -} - -// C /////////////////////////////////////////////////////////////////////////// - -// FileCopy appears after a CmdCommit (and before a CmdCommitEnd), -// and causes the CmdCommit to recursively copy an existing file or -// subdirectory to a different location. -type FileCopy struct { - Src Path - Dst Path -} - -func (o FileCopy) fiCmdClass() cmdClass { return cmdClassCommit } -func (o FileCopy) fiCmdWrite(fiw fiWriter) error { - return fiw.WriteLine("C", o.Src, o.Dst) -} -func init() { parser_registerCmd("C ", FileDelete{}) } -func (FileCopy) fiCmdRead(fir fiReader) (cmd Cmd, err error) { - // BUG(lukeshu): TODO: commit C not implemented - panic("TODO: commit C not implemented") -} - -// R /////////////////////////////////////////////////////////////////////////// - -// FileRename appears after a CmdCommit (and before a CmdCommitEnd), -// and causes the CmdCommit to rename an existing file or subdirectory -// to a different location. -type FileRename struct { - Src string - Dst string -} - -func (o FileRename) fiCmdClass() cmdClass { return cmdClassCommit } -func (o FileRename) fiCmdWrite(fiw fiWriter) error { - return fiw.WriteLine("R", o.Src, o.Dst) -} -func init() { parser_registerCmd("R ", FileDelete{}) } -func (FileRename) fiCmdRead(fir fiReader) (cmd Cmd, err error) { - // BUG(lukeshu): TODO: commit R not implemented - panic("TODO: commit R not implemented") -} - -// deleteall /////////////////////////////////////////////////////////////////// - -// FileDeleteAll appears after a CmdCommit (and before a -// CmdCommitEnd), and removes all files and directories from the -// CmdCommit. -type FileDeleteAll struct{} - -func (o FileDeleteAll) fiCmdClass() cmdClass { return cmdClassCommit } -func (o FileDeleteAll) fiCmdWrite(fiw fiWriter) error { - return fiw.WriteLine("deleteall") -} -func init() { parser_registerCmd("deleteall\n", FileDeleteAll{}) } -func (FileDeleteAll) fiCmdRead(fir fiReader) (cmd Cmd, err error) { - _, err = fir.ReadLine() - if err != nil { - return nil, err - } - return FileDeleteAll{}, nil -} - -// N /////////////////////////////////////////////////////////////////////////// - -// NoteModify appears after a CmdCommit (and before a CmdCommitEnd), -// and causes the CmdCommit to add a new note describing CommitIsh or -// change the content of an existing note describing CommitIsh. The -// content of the note is specified by giving either a mark reference -// (":") or by a full 40-byte SHA-1. -// -// To specify the full content of the note inline, use -// NoteModifyInline instead. -type NoteModify struct { - CommitIsh string - DataRef string -} - -func (o NoteModify) fiCmdClass() cmdClass { return cmdClassCommit } -func (o NoteModify) fiCmdWrite(fiw fiWriter) error { - return fiw.WriteLine("N", o.DataRef, o.CommitIsh) -} -func init() { parser_registerCmd("N ", NoteModify{}) } -func (NoteModify) fiCmdRead(fir fiReader) (cmd Cmd, err error) { - // NB: This parses both NoteModify and NoteModifyInline - line, err := fir.ReadLine() - if err != nil { - return nil, err - } - str := trimLinePrefix(line, "N ") - sp := strings.IndexByte(str, ' ') - if sp < 0 { - return nil, errors.Errorf("commit: malformed notemodify command: %v", line) - } - - ref := str[:sp] - commitish := str[sp+1:] - - if ref == "inline" { - line, err = fir.ReadLine() - if err != nil { - return nil, err - } - data, err := parse_data(line) - if err != nil { - return nil, err - } - return NoteModifyInline{ - CommitIsh: commitish, - Data: data, - }, nil - } else { - return NoteModify{ - CommitIsh: commitish, - DataRef: ref, - }, nil - } -} - -// NoteModifyInline appears after a CmdCommit (and before a -// CmdCommitEnd), and causes the CmdCommit to add a new note -// describing CommitIsh or change the content of an existing note -// describing CommitIsh. The full content of the note is specified -// directly. -// -// To instead specify the content with a mark reference (":") -// or with a full 40-byte SHA-1, use NoteModify instead. -type NoteModifyInline struct { - CommitIsh string - Data string -} - -func (o NoteModifyInline) fiCmdClass() cmdClass { return cmdClassCommit } -func (o NoteModifyInline) fiCmdWrite(fiw fiWriter) error { - ez := &ezfiw{fiw: fiw} - ez.WriteLine("N", "inline", o.CommitIsh) - ez.WriteData(o.Data) - return ez.err -} -func (NoteModifyInline) fiCmdRead(fiReader) (Cmd, error) { panic("not reached") } diff --git a/cmd_incommit.go b/cmd_incommit.go new file mode 100644 index 0000000..f58e59f --- /dev/null +++ b/cmd_incommit.go @@ -0,0 +1,267 @@ +// Copyright (C) 2017-2018, 2021 Luke Shumaker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package libfastimport + +import ( + "strconv" + "strings" + + "github.com/pkg/errors" +) + +// M /////////////////////////////////////////////////////////////////////////// + +// FileModify appears after a CmdCommit (and before a CmdCommitEnd), +// and causes the CmdCommit to add a new file or change the content of +// an existing file. The content of the file is specified by giving +// either a mark reference (":") or by a full 40-byte SHA-1. +// +// To specify the full content of the file inline, use +// FileModifyInline instead. +type FileModify struct { + Mode Mode + Path Path + DataRef string +} + +func (o FileModify) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileModify) fiCmdWrite(fiw fiWriter) error { + return fiw.WriteLine("M", o.Mode, o.DataRef, o.Path) +} +func init() { parser_registerCmd("M ", FileModify{}) } +func (FileModify) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + // NB: This parses both FileModify and FileModifyInline + line, err := fir.ReadLine() + if err != nil { + return nil, err + } + str := trimLinePrefix(line, "M ") + fields := strings.SplitN(str, " ", 3) + if len(fields) != 3 { + return nil, errors.Errorf("commit: malformed modify command: %v", line) + } + + nMode, err := strconv.ParseUint(fields[0], 8, 18) + if err != nil { + return nil, err + } + + ref := fields[1] + path := PathUnescape(fields[2]) + + if ref == "inline" { + line, err = fir.ReadLine() + if err != nil { + return nil, err + } + data, err := parse_data(line) + if err != nil { + return nil, err + } + return FileModifyInline{ + Mode: Mode(nMode), + Path: path, + Data: data, + }, nil + } else { + return FileModify{ + Mode: Mode(nMode), + Path: path, + DataRef: ref, + }, nil + } +} + +// FileModifyInline appears after a CmdCommit (and before a +// CmdCommitEnd), and causes the CmdCommit to add a new file or change +// the content of an existing file. The full content of the file are +// specified directly +// +// To instead specify the content with a mark reference (":") +// or with a full 40-byte SHA-1, use FileModify instead. +type FileModifyInline struct { + Mode Mode + Path Path + Data string +} + +func (o FileModifyInline) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileModifyInline) fiCmdWrite(fiw fiWriter) error { + ez := &ezfiw{fiw: fiw} + ez.WriteLine("M", o.Mode, "inline", o.Path) + ez.WriteData(o.Data) + return ez.err +} +func (FileModifyInline) fiCmdRead(fiReader) (Cmd, error) { panic("not reached") } + +// D /////////////////////////////////////////////////////////////////////////// + +// FileDelete appears after a CmdCommit (and before a CmdCommitEnd), +// and causes the CmdCommit to recursively remove a file or directory. +type FileDelete struct { + Path Path +} + +func (o FileDelete) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileDelete) fiCmdWrite(fiw fiWriter) error { + return fiw.WriteLine("D", o.Path) +} +func init() { parser_registerCmd("D ", FileDelete{}) } +func (FileDelete) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + line, err := fir.ReadLine() + if err != nil { + return nil, err + } + return FileDelete{Path: PathUnescape(trimLinePrefix(line, "D "))}, nil +} + +// C /////////////////////////////////////////////////////////////////////////// + +// FileCopy appears after a CmdCommit (and before a CmdCommitEnd), +// and causes the CmdCommit to recursively copy an existing file or +// subdirectory to a different location. +type FileCopy struct { + Src Path + Dst Path +} + +func (o FileCopy) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileCopy) fiCmdWrite(fiw fiWriter) error { + return fiw.WriteLine("C", o.Src, o.Dst) +} +func init() { parser_registerCmd("C ", FileDelete{}) } +func (FileCopy) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + // BUG(lukeshu): TODO: commit C not implemented + panic("TODO: commit C not implemented") +} + +// R /////////////////////////////////////////////////////////////////////////// + +// FileRename appears after a CmdCommit (and before a CmdCommitEnd), +// and causes the CmdCommit to rename an existing file or subdirectory +// to a different location. +type FileRename struct { + Src string + Dst string +} + +func (o FileRename) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileRename) fiCmdWrite(fiw fiWriter) error { + return fiw.WriteLine("R", o.Src, o.Dst) +} +func init() { parser_registerCmd("R ", FileDelete{}) } +func (FileRename) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + // BUG(lukeshu): TODO: commit R not implemented + panic("TODO: commit R not implemented") +} + +// deleteall /////////////////////////////////////////////////////////////////// + +// FileDeleteAll appears after a CmdCommit (and before a +// CmdCommitEnd), and removes all files and directories from the +// CmdCommit. +type FileDeleteAll struct{} + +func (o FileDeleteAll) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o FileDeleteAll) fiCmdWrite(fiw fiWriter) error { + return fiw.WriteLine("deleteall") +} +func init() { parser_registerCmd("deleteall\n", FileDeleteAll{}) } +func (FileDeleteAll) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + _, err = fir.ReadLine() + if err != nil { + return nil, err + } + return FileDeleteAll{}, nil +} + +// N /////////////////////////////////////////////////////////////////////////// + +// NoteModify appears after a CmdCommit (and before a CmdCommitEnd), +// and causes the CmdCommit to add a new note describing CommitIsh or +// change the content of an existing note describing CommitIsh. The +// content of the note is specified by giving either a mark reference +// (":") or by a full 40-byte SHA-1. +// +// To specify the full content of the note inline, use +// NoteModifyInline instead. +type NoteModify struct { + CommitIsh string + DataRef string +} + +func (o NoteModify) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o NoteModify) fiCmdWrite(fiw fiWriter) error { + return fiw.WriteLine("N", o.DataRef, o.CommitIsh) +} +func init() { parser_registerCmd("N ", NoteModify{}) } +func (NoteModify) fiCmdRead(fir fiReader) (cmd Cmd, err error) { + // NB: This parses both NoteModify and NoteModifyInline + line, err := fir.ReadLine() + if err != nil { + return nil, err + } + str := trimLinePrefix(line, "N ") + sp := strings.IndexByte(str, ' ') + if sp < 0 { + return nil, errors.Errorf("commit: malformed notemodify command: %v", line) + } + + ref := str[:sp] + commitish := str[sp+1:] + + if ref == "inline" { + line, err = fir.ReadLine() + if err != nil { + return nil, err + } + data, err := parse_data(line) + if err != nil { + return nil, err + } + return NoteModifyInline{ + CommitIsh: commitish, + Data: data, + }, nil + } else { + return NoteModify{ + CommitIsh: commitish, + DataRef: ref, + }, nil + } +} + +// NoteModifyInline appears after a CmdCommit (and before a +// CmdCommitEnd), and causes the CmdCommit to add a new note +// describing CommitIsh or change the content of an existing note +// describing CommitIsh. The full content of the note is specified +// directly. +// +// To instead specify the content with a mark reference (":") +// or with a full 40-byte SHA-1, use NoteModify instead. +type NoteModifyInline struct { + CommitIsh string + Data string +} + +func (o NoteModifyInline) fiCmdClass() cmdClass { return cmdClassInCommit } +func (o NoteModifyInline) fiCmdWrite(fiw fiWriter) error { + ez := &ezfiw{fiw: fiw} + ez.WriteLine("N", "inline", o.CommitIsh) + ez.WriteData(o.Data) + return ez.err +} +func (NoteModifyInline) fiCmdRead(fiReader) (Cmd, error) { panic("not reached") } diff --git a/parse_fastimport.go b/parse_fastimport.go index 491788b..7f84dfd 100644 --- a/parse_fastimport.go +++ b/parse_fastimport.go @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018, 2020 Luke Shumaker +// Copyright (C) 2017-2018, 2020-2021 Luke Shumaker // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -27,13 +27,10 @@ var parser_regularCmds = make(map[string]Cmd) var parser_commentCmds = make(map[string]Cmd) func parser_registerCmd(prefix string, cmd Cmd) { - switch cmd.fiCmdClass() { - case cmdClassCommand, cmdClassCommit: - parser_regularCmds[prefix] = cmd - case cmdClassComment: + if cmdIs(cmd, cmdClassInCommand) { parser_commentCmds[prefix] = cmd - default: - panic(errors.Errorf("invalid cmdClass: %d", cmd.fiCmdClass())) + } else { + parser_regularCmds[prefix] = cmd } } @@ -133,20 +130,14 @@ func (p *parser) parse() error { return err } - switch cmd.fiCmdClass() { - case cmdClassCommand: + switch { + case !cmdIs(cmd, cmdClassInCommit): if p.inCommit { p.ret_cmd <- CmdCommitEnd{} } _, p.inCommit = cmd.(CmdCommit) - case cmdClassCommit: - if !p.inCommit { - return errors.Errorf("Got in-commit-only command outside of a commit: %[1]T(%#[1]v)", cmd) - } - case cmdClassComment: - /* do nothing */ - default: - panic(errors.Errorf("invalid cmdClass: %d", cmd.fiCmdClass())) + case !p.inCommit && !cmdIs(cmd, cmdClassCommand): + return errors.Errorf("Got in-commit-only command outside of a commit: %[1]T(%#[1]v)", cmd) } p.ret_cmd <- cmd -- cgit v1.2.3-2-g168b