Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit aaeee53

Browse files
committed
Add support for signed commits
This change adds `GPGSignature` field to `Commit` object. This is used to store the signature of the commit, if any.
1 parent a99c129 commit aaeee53

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

plumbing/object/commit.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import (
1212
"gopkg.in/src-d/go-git.v4/utils/ioutil"
1313
)
1414

15+
const (
16+
beginpgp string = "-----BEGIN PGP SIGNATURE-----"
17+
endpgp string = "-----END PGP SIGNATURE-----"
18+
)
19+
1520
// Hash represents the hash of an object
1621
type Hash plumbing.Hash
1722

@@ -28,6 +33,8 @@ type Commit struct {
2833
// Committer is the one performing the commit, might be different from
2934
// Author.
3035
Committer Signature
36+
// GPGSignature is the GPG signature of the commit.
37+
GPGSignature string
3138
// Message is the commit message, contains arbitrary text.
3239
Message string
3340
// TreeHash is the hash of the root tree of the commit.
@@ -145,12 +152,33 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
145152
r := bufio.NewReader(reader)
146153

147154
var message bool
155+
var gpgsig bool
148156
for {
149157
line, err := r.ReadBytes('\n')
150158
if err != nil && err != io.EOF {
151159
return err
152160
}
153161

162+
if gpgsig {
163+
// Check if it's the end of a PGP signature.
164+
if bytes.Contains(line, []byte(endpgp)) {
165+
c.GPGSignature += string(endpgp) + "\n"
166+
gpgsig = false
167+
} else {
168+
// Trim the left padding.
169+
line = bytes.TrimLeft(line, " ")
170+
c.GPGSignature += string(line)
171+
}
172+
continue
173+
}
174+
175+
// Check if it's the beginning of a PGP signature.
176+
if bytes.Contains(line, []byte(beginpgp)) {
177+
c.GPGSignature += string(beginpgp) + "\n"
178+
gpgsig = true
179+
continue
180+
}
181+
154182
if !message {
155183
line = bytes.TrimSpace(line)
156184
if len(line) == 0 {
@@ -215,6 +243,21 @@ func (b *Commit) Encode(o plumbing.EncodedObject) error {
215243
return err
216244
}
217245

246+
if b.GPGSignature != "" {
247+
if _, err = fmt.Fprint(w, "gpgsig"); err != nil {
248+
return err
249+
}
250+
251+
// Split all the signature lines and write with a left padding and
252+
// newline at the end.
253+
lines := strings.Split(b.GPGSignature, "\n")
254+
for _, line := range lines {
255+
if _, err = fmt.Fprintf(w, " %s\n", line); err != nil {
256+
return err
257+
}
258+
}
259+
}
260+
218261
if _, err = fmt.Fprintf(w, "\n\n%s", b.Message); err != nil {
219262
return err
220263
}

plumbing/object/commit_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,29 @@ func (s *SuiteCommit) TestLongCommitMessageSerialization(c *C) {
232232
c.Assert(err, IsNil)
233233
c.Assert(decoded.Message, Equals, longMessage)
234234
}
235+
236+
func (s *SuiteCommit) TestGPGSignatureSerialization(c *C) {
237+
encoded := &plumbing.MemoryObject{}
238+
decoded := &Commit{}
239+
commit := *s.Commit
240+
241+
gpgsignature := `-----BEGIN PGP SIGNATURE-----
242+
243+
iQEcBAABAgAGBQJTZbQlAAoJEF0+sviABDDrZbQH/09PfE51KPVPlanr6q1v4/Ut
244+
LQxfojUWiLQdg2ESJItkcuweYg+kc3HCyFejeDIBw9dpXt00rY26p05qrpnG+85b
245+
hM1/PswpPLuBSr+oCIDj5GMC2r2iEKsfv2fJbNW8iWAXVLoWZRF8B0MfqX/YTMbm
246+
ecorc4iXzQu7tupRihslbNkfvfciMnSDeSvzCpWAHl7h8Wj6hhqePmLm9lAYqnKp
247+
8S5B/1SSQuEAjRZgI4IexpZoeKGVDptPHxLLS38fozsyi0QyDyzEgJxcJQVMXxVi
248+
RUysgqjcpT8+iQM1PblGfHR4XAhuOqN5Fx06PSaFZhqvWFezJ28/CLyX5q+oIVk=
249+
=EFTF
250+
-----END PGP SIGNATURE-----
251+
`
252+
commit.GPGSignature = gpgsignature
253+
254+
err := commit.Encode(encoded)
255+
c.Assert(err, IsNil)
256+
257+
err = decoded.Decode(encoded)
258+
c.Assert(err, IsNil)
259+
c.Assert(decoded.GPGSignature, Equals, gpgsignature)
260+
}

0 commit comments

Comments
 (0)