Repository: bluekeyes/go-gitdiff (go)

Issue:
git patch with empty emails causing  parse errors
I have a git patch that is triggering this line https://github.com/bluekeyes/go-gitdiff/blob/13e8639a0b49cb49741b05f11ac52c530d2d38f0/gitdiff/patch_header.go#L114


```
commit 44b179bf547c84cb588480558de71df1e9243aaf
Author: bot-deploy Github Action <>
Date:   Tue Mar 5 17:07:58 2024 +0000

    Export updated bot artifact

diff --git a/bot_exports/ba3e9571-b1d9-45cb-be06-a7b4a2e279e7.blob b/bot_exports/ba3e9571-b1d9-45cb-be06-a7b4a2e279e7.blob
index 4ea75f9..f92448c 100644
Binary files a/bot_exports/ba3e9571-b1d9-45cb-be06-a7b4a2e279e7.blob and b/bot_exports/ba3e9571-b1d9-45cb-be06-a7b4a2e279e7.blob differ
```

`Author: bot-deploy Github Action <>` is causing parsing to fail. Can this be gracefully handled, like returning an empty email?

Pull request:
Accept empty emails in ParsePatchIdentity
Git is actually more lenient here than I thought. As long as the identity contains the "<>" delimiters, Git will allow an empty email, so we should accept the same thing. I also discovered that an identity with only an email set will use the email as the name, so I've implemented that behavior as well.

Fixes #41.

Patch:
diff --git a/gitdiff/patch_header.go b/gitdiff/patch_header.go
index f935c6d..af3293b 100644
--- a/gitdiff/patch_header.go
+++ b/gitdiff/patch_header.go
@@ -82,12 +82,15 @@ func (i PatchIdentity) String() string {
 	return fmt.Sprintf("%s <%s>", name, i.Email)
 }
 
-// ParsePatchIdentity parses a patch identity string. A valid string contains a
-// non-empty name followed by an email address in angle brackets. Like Git,
-// ParsePatchIdentity does not require that the email address is valid or
-// properly formatted, only that it is non-empty. The name must not contain a
-// left angle bracket, '<', and the email address must not contain a right
-// angle bracket, '>'.
+// ParsePatchIdentity parses a patch identity string. A valid string contains
+// an optional name followed by an email address in angle brackets. The angle
+// brackets must always exist, but may enclose an empty address. At least one
+// of the name or the email address must be non-empty. If the string only
+// contains an email address, that value is also used as the name.
+//
+// The name must not contain a left angle bracket, '<', and the email address
+// must not contain a right angle bracket, '>'. Otherwise, there are no
+// restrictions on the format of either field.
 func ParsePatchIdentity(s string) (PatchIdentity, error) {
 	var emailStart, emailEnd int
 	for i, c := range s {
@@ -110,7 +113,11 @@ func ParsePatchIdentity(s string) (PatchIdentity, error) {
 	if emailStart > 0 && emailEnd > 0 {
 		email = strings.TrimSpace(s[emailStart:emailEnd])
 	}
-	if name == "" || email == "" {
+	if name == "" && email != "" {
+		name = email
+	}
+
+	if name == "" && email == "" {
 		return PatchIdentity{}, fmt.Errorf("invalid identity string: %s", s)
 	}
 


Test patch:
diff --git a/gitdiff/patch_header_test.go b/gitdiff/patch_header_test.go
index 003e8c7..33ec209 100644
--- a/gitdiff/patch_header_test.go
+++ b/gitdiff/patch_header_test.go
@@ -32,14 +32,32 @@ func TestParsePatchIdentity(t *testing.T) {
 				Email: "mhaypenny@example.com",
 			},
 		},
-		"missingName": {
+		"onlyEmail": {
 			Input: "<mhaypenny@example.com>",
-			Err:   "invalid identity",
+			Output: PatchIdentity{
+				Name:  "mhaypenny@example.com",
+				Email: "mhaypenny@example.com",
+			},
+		},
+		"emptyEmail": {
+			Input: "Morton Haypenny <>",
+			Output: PatchIdentity{
+				Name:  "Morton Haypenny",
+				Email: "",
+			},
 		},
 		"missingEmail": {
 			Input: "Morton Haypenny",
 			Err:   "invalid identity",
 		},
+		"missingNameAndEmptyEmail": {
+			Input: "<>",
+			Err:   "invalid identity",
+		},
+		"empty": {
+			Input: "",
+			Err:   "invalid identity",
+		},
 		"unclosedEmail": {
 			Input: "Morton Haypenny <mhaypenny@example.com",
 			Err:   "unclosed email",