aboutsummaryrefslogtreecommitdiffstats
path: root/worktree_commit.go
diff options
context:
space:
mode:
Diffstat (limited to 'worktree_commit.go')
-rw-r--r--worktree_commit.go88
1 files changed, 36 insertions, 52 deletions
diff --git a/worktree_commit.go b/worktree_commit.go
index 18002f2..2faf6f0 100644
--- a/worktree_commit.go
+++ b/worktree_commit.go
@@ -2,8 +2,6 @@ package git
import (
"bytes"
- "crypto"
- "crypto/rand"
"errors"
"io"
"path"
@@ -40,36 +38,53 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error
}
}
- var treeHash plumbing.Hash
-
if opts.Amend {
head, err := w.r.Head()
if err != nil {
return plumbing.ZeroHash, err
}
-
- t, err := w.r.getTreeFromCommitHash(head.Hash())
+ headCommit, err := w.r.CommitObject(head.Hash())
if err != nil {
return plumbing.ZeroHash, err
}
- treeHash = t.Hash
- opts.Parents = []plumbing.Hash{head.Hash()}
- } else {
- idx, err := w.r.Storer.Index()
- if err != nil {
- return plumbing.ZeroHash, err
+ opts.Parents = nil
+ if len(headCommit.ParentHashes) != 0 {
+ opts.Parents = []plumbing.Hash{headCommit.ParentHashes[0]}
}
+ }
- h := &buildTreeHelper{
- fs: w.Filesystem,
- s: w.r.Storer,
- }
+ idx, err := w.r.Storer.Index()
+ if err != nil {
+ return plumbing.ZeroHash, err
+ }
- treeHash, err = h.BuildTree(idx, opts)
+ // First handle the case of the first commit in the repository being empty.
+ if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !opts.AllowEmptyCommits {
+ return plumbing.ZeroHash, ErrEmptyCommit
+ }
+
+ h := &buildTreeHelper{
+ fs: w.Filesystem,
+ s: w.r.Storer,
+ }
+
+ treeHash, err := h.BuildTree(idx, opts)
+ if err != nil {
+ return plumbing.ZeroHash, err
+ }
+
+ previousTree := plumbing.ZeroHash
+ if len(opts.Parents) > 0 {
+ parentCommit, err := w.r.CommitObject(opts.Parents[0])
if err != nil {
return plumbing.ZeroHash, err
}
+ previousTree = parentCommit.TreeHash
+ }
+
+ if treeHash == previousTree && !opts.AllowEmptyCommits {
+ return plumbing.ZeroHash, ErrEmptyCommit
}
commit, err := w.buildCommitObject(msg, opts, treeHash)
@@ -135,7 +150,7 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
signer = &gpgSigner{key: opts.SignKey}
}
if signer != nil {
- sig, err := w.buildCommitSignature(commit, signer)
+ sig, err := signObject(signer, commit)
if err != nil {
return plumbing.ZeroHash, err
}
@@ -151,44 +166,17 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb
type gpgSigner struct {
key *openpgp.Entity
+ cfg *packet.Config
}
-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(),
- }
- }
-
+func (s *gpgSigner) Sign(message io.Reader) ([]byte, error) {
var b bytes.Buffer
- if err := openpgp.ArmoredDetachSign(&b, s.key, bytes.NewReader(digest), cfg); err != nil {
+ if err := openpgp.ArmoredDetachSign(&b, s.key, message, s.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 nil, err
- }
- r, err := encoded.Reader()
- if err != nil {
- return nil, err
- }
- b, err := io.ReadAll(r)
- if err != nil {
- return nil, err
- }
-
- return signer.Sign(rand.Reader, b, nil)
-}
-
// buildTreeHelper converts a given index.Index file into multiple git objects
// reading the blobs from the given filesystem and creating the trees from the
// index structure. The created objects are pushed to a given Storer.
@@ -203,10 +191,6 @@ type buildTreeHelper struct {
// BuildTree builds the tree objects and push its to the storer, the hash
// of the root tree is returned.
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
- if len(idx.Entries) == 0 && (opts == nil || !opts.AllowEmptyCommits) {
- return plumbing.ZeroHash, ErrEmptyCommit
- }
-
const rootNode = ""
h.trees = map[string]*object.Tree{rootNode: {}}
h.entries = map[string]*object.TreeEntry{}