@@ -7,9 +7,33 @@ import (
77 "bufio"
88 "bytes"
99 "io"
10- "strings"
1110)
1211
12+ const (
13+ commitHeaderGpgsig = "gpgsig"
14+ commitHeaderGpgsigSha256 = "gpgsig-sha256"
15+ )
16+
17+ func assignCommitFields (gitRepo * Repository , commit * Commit , headerKey string , headerValue []byte ) {
18+ if len (headerValue ) > 0 && headerValue [len (headerValue )- 1 ] == '\n' {
19+ headerValue = headerValue [:len (headerValue )- 1 ] // remove trailing newline
20+ }
21+ switch headerKey {
22+ case "tree" :
23+ commit .Tree = * NewTree (gitRepo , MustIDFromString (string (headerValue )))
24+ case "parent" :
25+ commit .Parents = append (commit .Parents , MustIDFromString (string (headerValue )))
26+ case "author" :
27+ commit .Author .Decode (headerValue )
28+ case "committer" :
29+ commit .Committer .Decode (headerValue )
30+ case commitHeaderGpgsig , commitHeaderGpgsigSha256 :
31+ // if there are duplicate "gpgsig" and "gpgsig-sha256" headers, then the signature must have already been invalid
32+ // so we don't need to handle duplicate headers here
33+ commit .Signature = & CommitSignature {Signature : string (headerValue )}
34+ }
35+ }
36+
1337// CommitFromReader will generate a Commit from a provided reader
1438// We need this to interpret commits from cat-file or cat-file --batch
1539//
@@ -21,90 +45,44 @@ func CommitFromReader(gitRepo *Repository, objectID ObjectID, reader io.Reader)
2145 Committer : & Signature {},
2246 }
2347
24- payloadSB := new (strings.Builder )
25- signatureSB := new (strings.Builder )
26- messageSB := new (strings.Builder )
27- message := false
28- pgpsig := false
29-
30- bufReader , ok := reader .(* bufio.Reader )
31- if ! ok {
32- bufReader = bufio .NewReader (reader )
33- }
34-
35- readLoop:
48+ bufReader := bufio .NewReader (reader )
49+ inHeader := true
50+ var payloadSB , messageSB bytes.Buffer
51+ var headerKey string
52+ var headerValue []byte
3653 for {
3754 line , err := bufReader .ReadBytes ('\n' )
38- if err != nil {
39- if err == io .EOF {
40- if message {
41- _ , _ = messageSB .Write (line )
42- }
43- _ , _ = payloadSB .Write (line )
44- break readLoop
45- }
46- return nil , err
55+ if len (line ) == 0 {
56+ break
4757 }
48- if pgpsig {
49- if len (line ) > 0 && line [0 ] == ' ' {
50- _ , _ = signatureSB .Write (line [1 :])
51- continue
52- }
53- pgpsig = false
58+ if err != nil && err != io .EOF {
59+ return nil , err
5460 }
5561
56- if ! message {
57- // This is probably not correct but is copied from go-gits interpretation...
58- trimmed := bytes .TrimSpace (line )
59- if len (trimmed ) == 0 {
60- message = true
61- _ , _ = payloadSB .Write (line )
62- continue
63- }
64-
65- split := bytes .SplitN (trimmed , []byte {' ' }, 2 )
66- var data []byte
67- if len (split ) > 1 {
68- data = split [1 ]
62+ if inHeader {
63+ inHeader = ! (len (line ) == 1 && line [0 ] == '\n' ) // still in header if line is not just a newline
64+ k , v , _ := bytes .Cut (line , []byte {' ' })
65+ if len (k ) != 0 || ! inHeader {
66+ if headerKey != "" {
67+ assignCommitFields (gitRepo , commit , headerKey , headerValue )
68+ }
69+ headerKey = string (k ) // it also resets the headerValue to empty string if not inHeader
70+ headerValue = v
71+ } else {
72+ headerValue = append (headerValue , v ... )
6973 }
70-
71- switch string (split [0 ]) {
72- case "tree" :
73- commit .Tree = * NewTree (gitRepo , MustIDFromString (string (data )))
74- _ , _ = payloadSB .Write (line )
75- case "parent" :
76- commit .Parents = append (commit .Parents , MustIDFromString (string (data )))
74+ if headerKey != commitHeaderGpgsig && headerKey != commitHeaderGpgsigSha256 {
7775 _ , _ = payloadSB .Write (line )
78- case "author" :
79- commit .Author = & Signature {}
80- commit .Author .Decode (data )
81- _ , _ = payloadSB .Write (line )
82- case "committer" :
83- commit .Committer = & Signature {}
84- commit .Committer .Decode (data )
85- _ , _ = payloadSB .Write (line )
86- case "encoding" :
87- _ , _ = payloadSB .Write (line )
88- case "gpgsig" :
89- fallthrough
90- case "gpgsig-sha256" : // FIXME: no intertop, so only 1 exists at present.
91- _ , _ = signatureSB .Write (data )
92- _ = signatureSB .WriteByte ('\n' )
93- pgpsig = true
9476 }
9577 } else {
9678 _ , _ = messageSB .Write (line )
9779 _ , _ = payloadSB .Write (line )
9880 }
9981 }
82+
10083 commit .CommitMessage = messageSB .String ()
101- commit .Signature = & CommitSignature {
102- Signature : signatureSB .String (),
103- Payload : payloadSB .String (),
104- }
105- if len (commit .Signature .Signature ) == 0 {
106- commit .Signature = nil
84+ if commit .Signature != nil {
85+ commit .Signature .Payload = payloadSB .String ()
10786 }
108-
10987 return commit , nil
11088}
0 commit comments