summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/stefanhaller/git-todo-parser/todo/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/stefanhaller/git-todo-parser/todo/parse.go')
-rw-r--r--vendor/github.com/stefanhaller/git-todo-parser/todo/parse.go158
1 files changed, 158 insertions, 0 deletions
diff --git a/vendor/github.com/stefanhaller/git-todo-parser/todo/parse.go b/vendor/github.com/stefanhaller/git-todo-parser/todo/parse.go
new file mode 100644
index 000000000..12bec439b
--- /dev/null
+++ b/vendor/github.com/stefanhaller/git-todo-parser/todo/parse.go
@@ -0,0 +1,158 @@
+package todo
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "strings"
+)
+
+var (
+ ErrUnexpectedCommand = errors.New("unexpected command")
+ ErrMissingLabel = errors.New("missing label")
+ ErrMissingCommit = errors.New("missing commit")
+ ErrMissingExecCmd = errors.New("missing command for exec")
+ ErrMissingRef = errors.New("missing ref")
+)
+
+func Parse(f io.Reader, commentChar byte) ([]Todo, error) {
+ var result []Todo
+
+ scanner := bufio.NewScanner(f)
+ scanner.Split(bufio.ScanLines)
+
+ for scanner.Scan() {
+ line := scanner.Text()
+
+ trimmed := strings.TrimSpace(line)
+ if trimmed == "" {
+ continue
+ }
+
+ cmd, err := parseLine(line, commentChar)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse line %q: %w", line, err)
+ }
+
+ result = append(result, cmd)
+ }
+
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("failed to parse input: %w", err)
+ }
+
+ return result, nil
+}
+
+func parseLine(line string, commentChar byte) (Todo, error) {
+ var todo Todo
+
+ if line[0] == commentChar {
+ todo.Command = Comment
+ todo.Comment = line[1:]
+ return todo, nil
+ }
+
+ fields := strings.Fields(line)
+
+ var commandLen int
+ for i := Pick; i < Comment; i++ {
+ if isCommand(i, fields[0]) {
+ todo.Command = i
+ commandLen = len(fields[0])
+ fields = fields[1:]
+ break
+ }
+ }
+
+ if todo.Command == 0 {
+ // unexpected command
+ return todo, ErrUnexpectedCommand
+ }
+
+ if todo.Command == Break || todo.Command == NoOp {
+ return todo, nil
+ }
+
+ if todo.Command == Label || todo.Command == Reset {
+ restOfLine := strings.TrimSpace(line[commandLen:])
+ if todo.Command == Reset && restOfLine == "[new root]" {
+ todo.Label = restOfLine
+ } else if len(fields) == 0 {
+ return todo, ErrMissingLabel
+ } else {
+ todo.Label = fields[0]
+ }
+ return todo, nil
+ }
+
+ if todo.Command == Exec {
+ if len(fields) == 0 {
+ return todo, ErrMissingExecCmd
+ }
+ todo.ExecCommand = strings.Join(fields, " ")
+ return todo, nil
+ }
+
+ if todo.Command == Merge {
+ if fields[0] == "-C" || fields[0] == "-c" {
+ todo.Flag = fields[0]
+ fields = fields[1:]
+ if len(fields) == 0 {
+ return todo, ErrMissingCommit
+ }
+ todo.Commit = fields[0]
+ fields = fields[1:]
+ }
+ if len(fields) == 0 {
+ return todo, ErrMissingLabel
+ }
+ todo.Label = fields[0]
+ fields = fields[1:]
+ if fields[0] == "#" {
+ fields = fields[1:]
+ todo.Msg = strings.Join(fields, " ")
+ }
+ return todo, nil
+ }
+
+ if todo.Command == Fixup {
+ if len(fields) == 0 {
+ return todo, ErrMissingCommit
+ }
+ // Skip flags
+ if fields[0] == "-C" || fields[0] == "-c" {
+ todo.Flag = fields[0]
+ fields = fields[1:]
+ }
+ }
+
+ if todo.Command == UpdateRef {
+ if len(fields) == 0 {
+ return todo, ErrMissingRef
+ }
+ todo.Ref = fields[0]
+ return todo, nil
+ }
+
+ if len(fields) == 0 {
+ return todo, ErrMissingCommit
+ }
+
+ todo.Commit = fields[0]
+ fields = fields[1:]
+
+ // Trim comment char and whitespace
+ todo.Msg = strings.TrimPrefix(strings.Join(fields, " "), fmt.Sprintf("%c ", commentChar))
+
+ return todo, nil
+}
+
+func isCommand(i TodoCommand, s string) bool {
+ if i < 0 || i > Comment {
+ return false
+ }
+ return len(s) > 0 &&
+ (todoCommandInfo[i].cmd == s || todoCommandInfo[i].nickname == s)
+}