Repository: bluekeyes/go-gitdiff
Pull request #20 (2020-10-30 18:05:09)

Working/relax email requirements
OK, last PR for a while.  `git am` is actually somewhat relaxed in what it accepts as far as email-looking things.   There are two things I've encountered so far which go-gitdiff chokes on that git am accepts:

1. `git am` will accept a file which starts with the `From:` line

2. `git am` will accept email-only "From" lines of the form `From: <foo@company.com>`.

With these changes, everything works for my use case.


Patch:
diff --git a/gitdiff/patch_header.go b/gitdiff/patch_header.go
index ae50870..16e3d3e 100644
--- a/gitdiff/patch_header.go
+++ b/gitdiff/patch_header.go
@@ -13,8 +13,9 @@ import (
 )
 
 const (
-	mailHeaderPrefix   = "From "
-	prettyHeaderPrefix = "commit "
+	mailHeaderPrefix        = "From "
+	prettyHeaderPrefix      = "commit "
+	mailMinimumHeaderPrefix = "From:"
 )
 
 // PatchHeader is a parsed version of the preamble content that appears before
@@ -210,6 +211,9 @@ func ParsePatchHeader(s string) (*PatchHeader, error) {
 	switch {
 	case strings.HasPrefix(line, mailHeaderPrefix):
 		return parseHeaderMail(line, r)
+	case strings.HasPrefix(line, mailMinimumHeaderPrefix):
+		r = bufio.NewReader(strings.NewReader(s))
+		return parseHeaderMail("", r)
 	case strings.HasPrefix(line, prettyHeaderPrefix):
 		return parseHeaderPretty(line, r)
 	}
@@ -368,9 +372,11 @@ func parseHeaderMail(mailLine string, r io.Reader) (*PatchHeader, error) {
 
 	h := &PatchHeader{}
 
-	mailLine = mailLine[len(mailHeaderPrefix):]
-	if i := strings.IndexByte(mailLine, ' '); i > 0 {
-		h.SHA = mailLine[:i]
+	if len(mailLine) > len(mailHeaderPrefix) {
+		mailLine = mailLine[len(mailHeaderPrefix):]
+		if i := strings.IndexByte(mailLine, ' '); i > 0 {
+			h.SHA = mailLine[:i]
+		}
 	}
 
 	addrs, err := msg.Header.AddressList("From")
@@ -380,7 +386,7 @@ func parseHeaderMail(mailLine string, r io.Reader) (*PatchHeader, error) {
 	if len(addrs) > 0 {
 		addr := addrs[0]
 		if addr.Name == "" {
-			return nil, fmt.Errorf("invalid user string: %s", addr)
+			addr.Name = addr.Address
 		}
 		h.Author = &PatchIdentity{Name: addr.Name, Email: addr.Address}
 	}


Test patch:
diff --git a/gitdiff/patch_header_test.go b/gitdiff/patch_header_test.go
index ca7e053..7dc7f13 100644
--- a/gitdiff/patch_header_test.go
+++ b/gitdiff/patch_header_test.go
@@ -289,6 +289,36 @@ CC: Joe Smith <joe.smith@company.com>
 				BodyAppendix: expectedBodyAppendix,
 			},
 		},
+		"mailboxMinimalNoName": {
+			Input: `From: <mhaypenny@example.com>
+Subject: [PATCH] A sample commit to test header parsing
+
+The medium format shows the body, which
+may wrap on to multiple lines.
+
+Another body line.
+`,
+			Header: PatchHeader{
+				Author: &PatchIdentity{expectedIdentity.Email, expectedIdentity.Email},
+				Title:  expectedTitle,
+				Body:   expectedBody,
+			},
+		},
+		"mailboxMinimal": {
+			Input: `From: Morton Haypenny <mhaypenny@example.com>
+Subject: [PATCH] A sample commit to test header parsing
+
+The medium format shows the body, which
+may wrap on to multiple lines.
+
+Another body line.
+`,
+			Header: PatchHeader{
+				Author: expectedIdentity,
+				Title:  expectedTitle,
+				Body:   expectedBody,
+			},
+		},
 		"unwrapTitle": {
 			Input: `commit 61f5cd90bed4d204ee3feb3aa41ee91d4734855b
 Author: Morton Haypenny <mhaypenny@example.com>