| // Copyright 2017 syzkaller project authors. All rights reserved. |
| // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. |
| |
| package email |
| |
| import ( |
| "bufio" |
| "bytes" |
| "regexp" |
| "strings" |
| ) |
| |
| func ParsePatch(message []byte) (diff string) { |
| s := bufio.NewScanner(bytes.NewReader(message)) |
| diffStarted := false |
| for s.Scan() { |
| ln := s.Text() |
| if lineMatchesDiffStart(ln) { |
| diffStarted = true |
| diff += ln + "\n" |
| continue |
| } |
| if diffStarted { |
| if ln == "" || ln == "--" || ln == "-- " || ln[0] == '>' { |
| diffStarted = false |
| continue |
| } |
| if strings.HasPrefix(ln, " ") || strings.HasPrefix(ln, "+") || |
| strings.HasPrefix(ln, "-") || strings.HasPrefix(ln, "@") || |
| strings.HasPrefix(ln, "================") { |
| diff += ln + "\n" |
| continue |
| } |
| } |
| } |
| err := s.Err() |
| if err == bufio.ErrTooLong { |
| // It's a problem of the incoming patch, rather than anything else. |
| // Anyway, if a patch contains too long lines, we're probably not |
| // interested in it, so let's pretent we didn't see it. |
| diff = "" |
| return |
| } else if err != nil { |
| panic("error while scanning from memory: " + err.Error()) |
| } |
| return |
| } |
| |
| var diffRegexps = []*regexp.Regexp{ |
| regexp.MustCompile(`^(---|\+\+\+) [^\s]`), |
| regexp.MustCompile(`^diff --git`), |
| regexp.MustCompile(`^index [0-9a-f]+\.\.[0-9a-f]+`), |
| regexp.MustCompile(`^new file mode [0-9]+`), |
| regexp.MustCompile(`^Index: [^\s]`), |
| } |
| |
| func lineMatchesDiffStart(ln string) bool { |
| for _, re := range diffRegexps { |
| if re.MatchString(ln) { |
| return true |
| } |
| } |
| return false |
| } |