diff options
Diffstat (limited to 'worktree_commit.go')
-rw-r--r-- | worktree_commit.go | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/worktree_commit.go b/worktree_commit.go index 4d811f3..18002f2 100644 --- a/worktree_commit.go +++ b/worktree_commit.go @@ -2,7 +2,10 @@ package git import ( "bytes" + "crypto" + "crypto/rand" "errors" + "io" "path" "sort" "strings" @@ -14,6 +17,7 @@ import ( "github.com/go-git/go-git/v5/storage" "github.com/ProtonMail/go-crypto/openpgp" + "github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/go-git/go-billy/v5" ) @@ -125,12 +129,17 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb ParentHashes: opts.Parents, } - if opts.SignKey != nil { - sig, err := w.buildCommitSignature(commit, opts.SignKey) + // Convert SignKey into a Signer if set. Existing Signer should take priority. + signer := opts.Signer + if signer == nil && opts.SignKey != nil { + signer = &gpgSigner{key: opts.SignKey} + } + if signer != nil { + sig, err := w.buildCommitSignature(commit, signer) if err != nil { return plumbing.ZeroHash, err } - commit.PGPSignature = sig + commit.PGPSignature = string(sig) } obj := w.r.Storer.NewEncodedObject() @@ -140,20 +149,44 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb return w.r.Storer.SetEncodedObject(obj) } -func (w *Worktree) buildCommitSignature(commit *object.Commit, signKey *openpgp.Entity) (string, error) { +type gpgSigner struct { + key *openpgp.Entity +} + +func (s *gpgSigner) Public() crypto.PublicKey { + return s.key.PrimaryKey +} + +func (s *gpgSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { + var cfg *packet.Config + if opts != nil { + cfg = &packet.Config{ + DefaultHash: opts.HashFunc(), + } + } + + var b bytes.Buffer + if err := openpgp.ArmoredDetachSign(&b, s.key, bytes.NewReader(digest), cfg); err != nil { + return nil, err + } + return b.Bytes(), nil +} + +func (w *Worktree) buildCommitSignature(commit *object.Commit, signer crypto.Signer) ([]byte, error) { encoded := &plumbing.MemoryObject{} if err := commit.Encode(encoded); err != nil { - return "", err + return nil, err } r, err := encoded.Reader() if err != nil { - return "", err + return nil, err } - var b bytes.Buffer - if err := openpgp.ArmoredDetachSign(&b, signKey, r, nil); err != nil { - return "", err + b, err := io.ReadAll(r) + if err != nil { + return nil, err } - return b.String(), nil + + return signer.Sign(rand.Reader, b, nil) } // buildTreeHelper converts a given index.Index file into multiple git objects |