@@ -2,7 +2,10 @@ package git
2
2
3
3
import (
4
4
"bytes"
5
+ "crypto"
6
+ "crypto/rand"
5
7
"errors"
8
+ "io"
6
9
"path"
7
10
"sort"
8
11
"strings"
@@ -14,6 +17,7 @@ import (
14
17
"github.com/go-git/go-git/v5/storage"
15
18
16
19
"github.com/ProtonMail/go-crypto/openpgp"
20
+ "github.com/ProtonMail/go-crypto/openpgp/packet"
17
21
"github.com/go-git/go-billy/v5"
18
22
)
19
23
@@ -125,12 +129,17 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
125
129
ParentHashes : opts .Parents ,
126
130
}
127
131
128
- if opts .SignKey != nil {
129
- sig , err := w .buildCommitSignature (commit , opts .SignKey )
132
+ // Convert SignKey into a Signer if set. Existing Signer should take priority.
133
+ signer := opts .Signer
134
+ if signer == nil && opts .SignKey != nil {
135
+ signer = & gpgSigner {key : opts .SignKey }
136
+ }
137
+ if signer != nil {
138
+ sig , err := w .buildCommitSignature (commit , signer )
130
139
if err != nil {
131
140
return plumbing .ZeroHash , err
132
141
}
133
- commit .PGPSignature = sig
142
+ commit .PGPSignature = string ( sig )
134
143
}
135
144
136
145
obj := w .r .Storer .NewEncodedObject ()
@@ -140,20 +149,44 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
140
149
return w .r .Storer .SetEncodedObject (obj )
141
150
}
142
151
143
- func (w * Worktree ) buildCommitSignature (commit * object.Commit , signKey * openpgp.Entity ) (string , error ) {
152
+ type gpgSigner struct {
153
+ key * openpgp.Entity
154
+ }
155
+
156
+ func (s * gpgSigner ) Public () crypto.PublicKey {
157
+ return s .key .PrimaryKey
158
+ }
159
+
160
+ func (s * gpgSigner ) Sign (rand io.Reader , digest []byte , opts crypto.SignerOpts ) ([]byte , error ) {
161
+ var cfg * packet.Config
162
+ if opts != nil {
163
+ cfg = & packet.Config {
164
+ DefaultHash : opts .HashFunc (),
165
+ }
166
+ }
167
+
168
+ var b bytes.Buffer
169
+ if err := openpgp .ArmoredDetachSign (& b , s .key , bytes .NewReader (digest ), cfg ); err != nil {
170
+ return nil , err
171
+ }
172
+ return b .Bytes (), nil
173
+ }
174
+
175
+ func (w * Worktree ) buildCommitSignature (commit * object.Commit , signer crypto.Signer ) ([]byte , error ) {
144
176
encoded := & plumbing.MemoryObject {}
145
177
if err := commit .Encode (encoded ); err != nil {
146
- return "" , err
178
+ return nil , err
147
179
}
148
180
r , err := encoded .Reader ()
149
181
if err != nil {
150
- return "" , err
182
+ return nil , err
151
183
}
152
- var b bytes. Buffer
153
- if err := openpgp . ArmoredDetachSign ( & b , signKey , r , nil ); err != nil {
154
- return "" , err
184
+ b , err := io . ReadAll ( r )
185
+ if err != nil {
186
+ return nil , err
155
187
}
156
- return b .String (), nil
188
+
189
+ return signer .Sign (rand .Reader , b , nil )
157
190
}
158
191
159
192
// buildTreeHelper converts a given index.Index file into multiple git objects
0 commit comments