aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--_examples/clone/auth/ssh/private_key/main.go (renamed from _examples/clone/auth/ssh/main.go)0
-rw-r--r--_examples/clone/auth/ssh/ssh_agent/main.go37
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--options.go5
-rw-r--r--plumbing/object/commit.go6
-rw-r--r--plumbing/object/commit_test.go6
-rw-r--r--worktree_commit.go53
8 files changed, 94 insertions, 19 deletions
diff --git a/_examples/clone/auth/ssh/main.go b/_examples/clone/auth/ssh/private_key/main.go
index 5f21d90..5f21d90 100644
--- a/_examples/clone/auth/ssh/main.go
+++ b/_examples/clone/auth/ssh/private_key/main.go
diff --git a/_examples/clone/auth/ssh/ssh_agent/main.go b/_examples/clone/auth/ssh/ssh_agent/main.go
new file mode 100644
index 0000000..7a2ebd3
--- /dev/null
+++ b/_examples/clone/auth/ssh/ssh_agent/main.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "fmt"
+ "os"
+
+ git "github.com/go-git/go-git/v5"
+ . "github.com/go-git/go-git/v5/_examples"
+ "github.com/go-git/go-git/v5/plumbing/transport/ssh"
+)
+
+func main() {
+ CheckArgs("<url>", "<directory>")
+ url, directory := os.Args[1], os.Args[2]
+
+ authMethod, err := ssh.NewSSHAgentAuth("git")
+ CheckIfError(err)
+
+ // Clone the given repository to the given directory
+ Info("git clone %s ", url)
+
+ r, err := git.PlainClone(directory, false, &git.CloneOptions{
+ Auth: authMethod,
+ URL: url,
+ Progress: os.Stdout,
+ })
+ CheckIfError(err)
+
+ // ... retrieving the branch being pointed by HEAD
+ ref, err := r.Head()
+ CheckIfError(err)
+ // ... retrieving the commit object
+ commit, err := r.CommitObject(ref.Hash())
+ CheckIfError(err)
+
+ fmt.Println(commit)
+}
diff --git a/go.mod b/go.mod
index 70107e0..7fcf313 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.19
require (
dario.cat/mergo v1.0.0
- github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371
+ github.com/ProtonMail/go-crypto v1.0.0
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a
github.com/emirpasic/gods v1.18.1
diff --git a/go.sum b/go.sum
index b11a6ef..588e4bc 100644
--- a/go.sum
+++ b/go.sum
@@ -3,8 +3,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
-github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
-github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
+github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
+github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
diff --git a/options.go b/options.go
index fd54aa8..0a6eb94 100644
--- a/options.go
+++ b/options.go
@@ -1,6 +1,7 @@
package git
import (
+ "crypto"
"errors"
"fmt"
"regexp"
@@ -512,6 +513,10 @@ type CommitOptions struct {
// commit will not be signed. The private key must be present and already
// decrypted.
SignKey *openpgp.Entity
+ // Signer denotes a cryptographic signer to sign the commit with.
+ // A nil value here means the commit will not be signed.
+ // Takes precedence over SignKey.
+ Signer crypto.Signer
// Amend will create a new commit object and replace the commit that HEAD currently
// points to. Cannot be used with All nor Parents.
Amend bool
diff --git a/plumbing/object/commit.go b/plumbing/object/commit.go
index ceed5d0..3d096e1 100644
--- a/plumbing/object/commit.go
+++ b/plumbing/object/commit.go
@@ -27,7 +27,7 @@ const (
// the commit with the "mergetag" header.
headermergetag string = "mergetag"
- defaultUtf8CommitMesageEncoding MessageEncoding = "UTF-8"
+ defaultUtf8CommitMessageEncoding MessageEncoding = "UTF-8"
)
// Hash represents the hash of an object
@@ -189,7 +189,7 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
}
c.Hash = o.Hash()
- c.Encoding = defaultUtf8CommitMesageEncoding
+ c.Encoding = defaultUtf8CommitMessageEncoding
reader, err := o.Reader()
if err != nil {
@@ -335,7 +335,7 @@ func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
}
}
- if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMesageEncoding {
+ if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMessageEncoding {
if _, err = fmt.Fprintf(w, "\n%s %s", headerencoding, c.Encoding); err != nil {
return err
}
diff --git a/plumbing/object/commit_test.go b/plumbing/object/commit_test.go
index 3e1fe1b..6651ef8 100644
--- a/plumbing/object/commit_test.go
+++ b/plumbing/object/commit_test.go
@@ -228,7 +228,7 @@ change
Message: "Message\n\nFoo\nBar\nWith trailing blank lines\n\n",
TreeHash: plumbing.NewHash("f000000000000000000000000000000000000001"),
ParentHashes: []plumbing.Hash{plumbing.NewHash("f000000000000000000000000000000000000002")},
- Encoding: defaultUtf8CommitMesageEncoding,
+ Encoding: defaultUtf8CommitMessageEncoding,
},
{
Author: Signature{Name: "Foo", Email: "foo@example.local", When: ts},
@@ -253,7 +253,7 @@ change
plumbing.NewHash("f000000000000000000000000000000000000003"),
},
MergeTag: tag,
- Encoding: defaultUtf8CommitMesageEncoding,
+ Encoding: defaultUtf8CommitMessageEncoding,
},
{
Author: Signature{Name: "Foo", Email: "foo@example.local", When: ts},
@@ -266,7 +266,7 @@ change
},
MergeTag: tag,
PGPSignature: pgpsignature,
- Encoding: defaultUtf8CommitMesageEncoding,
+ Encoding: defaultUtf8CommitMessageEncoding,
},
}
for _, commit := range commits {
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