Home | History | Annotate | Download | only in email
      1 // Copyright 2017 syzkaller project authors. All rights reserved.
      2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
      3 
      4 package email
      5 
      6 import (
      7 	"bufio"
      8 	"fmt"
      9 	"strings"
     10 )
     11 
     12 func ParsePatch(text string) (title string, diff string, err error) {
     13 	s := bufio.NewScanner(strings.NewReader(text))
     14 	parsingDiff := false
     15 	diffStarted := false
     16 	lastLine := ""
     17 	for s.Scan() {
     18 		ln := s.Text()
     19 		if strings.HasPrefix(ln, "--- a/") || strings.HasPrefix(ln, "--- /dev/null") {
     20 			parsingDiff = true
     21 			if title == "" {
     22 				title = lastLine
     23 			}
     24 		}
     25 		if parsingDiff {
     26 			if ln == "" || ln == "--" || ln == "-- " || ln[0] == '>' ||
     27 				ln[0] >= 'A' && ln[0] <= 'Z' {
     28 				break
     29 			}
     30 			diff += ln + "\n"
     31 			continue
     32 		}
     33 		if strings.HasPrefix(ln, "diff --git") {
     34 			diffStarted = true
     35 			continue
     36 		}
     37 		if strings.HasPrefix(ln, "Subject: ") {
     38 			title = ln[len("Subject: "):]
     39 			continue
     40 		}
     41 		if ln == "" || title != "" || diffStarted {
     42 			continue
     43 		}
     44 		lastLine = ln
     45 		if strings.HasPrefix(ln, "    ") {
     46 			title = ln[4:]
     47 		}
     48 	}
     49 	if err = s.Err(); err != nil {
     50 		return
     51 	}
     52 	if strings.Contains(strings.ToLower(title), "[patch") {
     53 		pos := strings.IndexByte(title, ']')
     54 		if pos == -1 {
     55 			err = fmt.Errorf("title contains '[patch' but not ']'")
     56 			return
     57 		}
     58 		title = title[pos+1:]
     59 	}
     60 	title = strings.TrimSpace(title)
     61 	if title == "" {
     62 		err = fmt.Errorf("failed to extract title")
     63 		return
     64 	}
     65 	if diff == "" {
     66 		err = fmt.Errorf("failed to extract diff")
     67 		return
     68 	}
     69 	return
     70 }
     71