summaryrefslogtreecommitdiff
path: root/pkg/gitdiff/patch_identity.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/gitdiff/patch_identity.go')
-rw-r--r--pkg/gitdiff/patch_identity.go166
1 files changed, 0 insertions, 166 deletions
diff --git a/pkg/gitdiff/patch_identity.go b/pkg/gitdiff/patch_identity.go
deleted file mode 100644
index 018f80c..0000000
--- a/pkg/gitdiff/patch_identity.go
+++ /dev/null
@@ -1,166 +0,0 @@
-package gitdiff
-
-import (
- "fmt"
- "strings"
-)
-
-// PatchIdentity identifies a person who authored or committed a patch.
-type PatchIdentity struct {
- Name string
- Email string
-}
-
-func (i PatchIdentity) String() string {
- name := i.Name
- if name == "" {
- name = `""`
- }
- return fmt.Sprintf("%s <%s>", name, i.Email)
-}
-
-// ParsePatchIdentity parses a patch identity string. A patch identity contains
-// an email address and an optional name in [RFC 5322] format. This is either a
-// plain email adddress or a name followed by an address in angle brackets:
-//
-// author@example.com
-// Author Name <author@example.com>
-//
-// If the input is not one of these formats, ParsePatchIdentity applies a
-// heuristic to separate the name and email portions. If both the name and
-// email are missing or empty, ParsePatchIdentity returns an error. It
-// otherwise does not validate the result.
-//
-// [RFC 5322]: https://datatracker.ietf.org/doc/html/rfc5322
-func ParsePatchIdentity(s string) (PatchIdentity, error) {
- s = normalizeSpace(s)
- s = unquotePairs(s)
-
- var name, email string
- if at := strings.IndexByte(s, '@'); at >= 0 {
- start, end := at, at
- for start >= 0 && !isRFC5332Space(s[start]) && s[start] != '<' {
- start--
- }
- for end < len(s) && !isRFC5332Space(s[end]) && s[end] != '>' {
- end++
- }
- email = s[start+1 : end]
-
- // Adjust the boundaries so that we drop angle brackets, but keep
- // spaces when removing the email to form the name.
- if start < 0 || s[start] != '<' {
- start++
- }
- if end >= len(s) || s[end] != '>' {
- end--
- }
- name = s[:start] + s[end+1:]
- } else {
- start, end := 0, 0
- for i := 0; i < len(s); i++ {
- if s[i] == '<' && start == 0 {
- start = i + 1
- }
- if s[i] == '>' && start > 0 {
- end = i
- break
- }
- }
- if start > 0 && end >= start {
- email = strings.TrimSpace(s[start:end])
- name = s[:start-1]
- }
- }
-
- // After extracting the email, the name might contain extra whitespace
- // again and may be surrounded by comment characters. The git source gives
- // these examples of when this can happen:
- //
- // "Name <email@domain>"
- // "email@domain (Name)"
- // "Name <email@domain> (Comment)"
- //
- name = normalizeSpace(name)
- if strings.HasPrefix(name, "(") && strings.HasSuffix(name, ")") {
- name = name[1 : len(name)-1]
- }
- name = strings.TrimSpace(name)
-
- // If the name is empty or contains email-like characters, use the email
- // instead (assuming one exists)
- if name == "" || strings.ContainsAny(name, "@<>") {
- name = email
- }
-
- if name == "" && email == "" {
- return PatchIdentity{}, fmt.Errorf("invalid identity string %q", s)
- }
- return PatchIdentity{Name: name, Email: email}, nil
-}
-
-// unquotePairs process the RFC5322 tokens "quoted-string" and "comment" to
-// remove any "quoted-pairs" (backslash-espaced characters). It also removes
-// the quotes from any quoted strings, but leaves the comment delimiters.
-func unquotePairs(s string) string {
- quote := false
- comments := 0
- escaped := false
-
- var out strings.Builder
- for i := 0; i < len(s); i++ {
- if escaped {
- escaped = false
- } else {
- switch s[i] {
- case '\\':
- // quoted-pair is only allowed in quoted-string/comment
- if quote || comments > 0 {
- escaped = true
- continue // drop '\' character
- }
-
- case '"':
- if comments == 0 {
- quote = !quote
- continue // drop '"' character
- }
-
- case '(':
- if !quote {
- comments++
- }
- case ')':
- if comments > 0 {
- comments--
- }
- }
- }
- out.WriteByte(s[i])
- }
- return out.String()
-}
-
-// normalizeSpace trims leading and trailing whitespace from s and converts
-// inner sequences of one or more whitespace characters to single spaces.
-func normalizeSpace(s string) string {
- var sb strings.Builder
- for i := 0; i < len(s); i++ {
- c := s[i]
- if !isRFC5332Space(c) {
- if sb.Len() > 0 && isRFC5332Space(s[i-1]) {
- sb.WriteByte(' ')
- }
- sb.WriteByte(c)
- }
- }
- return sb.String()
-}
-
-func isRFC5332Space(c byte) bool {
- switch c {
- case '\t', '\n', '\r', ' ':
- return true
- }
- return false
-}