aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/email/parser.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-04-17 12:49:12 +0200
committerAleksandr Nogikh <wp32pw@gmail.com>2023-04-27 11:42:09 +0200
commit030e10720439813a9e4a7e4586bdc2bdc781a4c9 (patch)
treefd173364ef340c6c95b7e32f767d7f513c7cfbfd /pkg/email/parser.go
parent3187536a2e79fb4a7c5d76ef46e69614696c3497 (diff)
pkg/email: support multiple commands
It's not always convenient that we can receive only one command per email. Update pkg/email parsing code to extract everything which there is. Update reporting_email.go to handle multiple email commands. Set different limits for bug email commands and bug list commands.
Diffstat (limited to 'pkg/email/parser.go')
-rw-r--r--pkg/email/parser.go69
1 files changed, 41 insertions, 28 deletions
diff --git a/pkg/email/parser.go b/pkg/email/parser.go
index 5b472a57e..152f5e555 100644
--- a/pkg/email/parser.go
+++ b/pkg/email/parser.go
@@ -29,18 +29,21 @@ type Email struct {
Author string
OwnEmail bool
Cc []string
- Body string // text/plain part
- Patch string // attached patch, if any
- Command Command // command to bot
- CommandStr string // string representation of the command
- CommandArgs string // arguments for the command
+ Body string // text/plain part
+ Patch string // attached patch, if any
+ Commands []*SingleCommand
+}
+
+type SingleCommand struct {
+ Command Command
+ Str string // string representation
+ Args string // arguments for the command
}
type Command int
const (
CmdUnknown Command = iota
- CmdNone
CmdUpstream
CmdFix
CmdUnFix
@@ -130,8 +133,8 @@ func Parse(r io.Reader, ownEmails, goodLists, domains []string) (*Email, error)
}
bodyStr := string(body)
subject := msg.Header.Get("Subject")
- cmd := CmdNone
- patch, cmdStr, cmdArgs := "", "", ""
+ var cmds []*SingleCommand
+ var patch string
if !fromMe {
for _, a := range attachments {
patch = ParsePatch(a)
@@ -142,7 +145,7 @@ func Parse(r io.Reader, ownEmails, goodLists, domains []string) (*Email, error)
if patch == "" {
patch = ParsePatch(body)
}
- cmd, cmdStr, cmdArgs = extractCommand(subject + "\n" + bodyStr)
+ cmds = extractCommands(subject + "\n" + bodyStr)
}
bugIDs = append(bugIDs, extractBodyBugIDs(bodyStr, ownAddrs, domains)...)
@@ -180,9 +183,7 @@ func Parse(r io.Reader, ownEmails, goodLists, domains []string) (*Email, error)
Cc: ccList,
Body: bodyStr,
Patch: patch,
- Command: cmd,
- CommandStr: cmdStr,
- CommandArgs: cmdArgs,
+ Commands: cmds,
}
return email, nil
}
@@ -241,25 +242,35 @@ func CanonicalEmail(email string) string {
return strings.ToLower(addr.Address)
}
+func extractCommands(body string) []*SingleCommand {
+ var ret []*SingleCommand
+ for body != "" {
+ cmd, end := extractCommand(body)
+ if cmd == nil {
+ break
+ }
+ ret = append(ret, cmd)
+ body = body[end:]
+ }
+ return ret
+}
+
const commandPrefix = "#syz"
+var commandStartRe = regexp.MustCompile(`(?:^|\n)(` + regexp.QuoteMeta(commandPrefix) + `[ \t-:])`)
+
// extractCommand extracts command to syzbot from email body.
// Commands are of the following form:
// ^#syz cmd args...
-func extractCommand(body string) (cmd Command, str, args string) {
- nbody := "\n" + body
- cmdPos := -1
- for _, delim := range []string{" ", "\t", "-", ":"} {
- cmdPos = strings.Index(nbody, "\n"+commandPrefix+delim)
- if cmdPos != -1 {
- break
- }
- }
- if cmdPos == -1 {
- cmd = CmdNone
- return
+func extractCommand(body string) (*SingleCommand, int) {
+ var cmd Command
+ var str, args string
+
+ match := commandStartRe.FindStringSubmatchIndex(body)
+ if match == nil {
+ return nil, 0
}
- cmdPos += len(commandPrefix) + 1
+ cmdPos := match[2] + len(commandPrefix) + 1
for cmdPos < len(body) && unicode.IsSpace(rune(body[cmdPos])) {
cmdPos++
}
@@ -292,15 +303,17 @@ func extractCommand(body string) (cmd Command, str, args string) {
case CmdFix, CmdDup:
args = extractArgsLine(body[cmdPos+cmdEnd:])
}
- return
+ return &SingleCommand{
+ Command: cmd,
+ Str: str,
+ Args: args,
+ }, cmdPos + cmdEnd
}
func strToCmd(str string) Command {
switch str {
default:
return CmdUnknown
- case "":
- return CmdNone
case "upstream":
return CmdUpstream
case "fix", "fix:":