Skip to content

Commit 86c0c01

Browse files
committed
Repository.ConfigScoped and Repository.Commit with empty author support
1 parent 26d02b3 commit 86c0c01

File tree

8 files changed

+117
-27
lines changed

8 files changed

+117
-27
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/go-git/go-billy/v5 v5.0.0
1111
github.com/go-git/go-git-fixtures/v4 v4.0.1
1212
github.com/google/go-cmp v0.3.0
13+
github.com/imdario/mergo v0.3.9
1314
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
1415
github.com/jessevdk/go-flags v1.4.0
1516
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp
2222
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
2323
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
2424
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
25+
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
26+
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
2527
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
2628
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
2729
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=

options.go

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import (
66
"strings"
77
"time"
88

9-
"golang.org/x/crypto/openpgp"
109
"github.com/go-git/go-git/v5/config"
1110
"github.com/go-git/go-git/v5/plumbing"
1211
"github.com/go-git/go-git/v5/plumbing/object"
1312
"github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
1413
"github.com/go-git/go-git/v5/plumbing/transport"
14+
"golang.org/x/crypto/openpgp"
1515
)
1616

1717
// SubmoduleRescursivity defines how depth will affect any submodule recursive
@@ -375,7 +375,8 @@ type CommitOptions struct {
375375
// All automatically stage files that have been modified and deleted, but
376376
// new files you have not told Git about are not affected.
377377
All bool
378-
// Author is the author's signature of the commit.
378+
// Author is the author's signature of the commit. If Author is empty the
379+
// Name and Email is read from the config, and time.Now it's used as When.
379380
Author *object.Signature
380381
// Committer is the committer's signature of the commit. If Committer is
381382
// nil the Author signature is used.
@@ -392,7 +393,9 @@ type CommitOptions struct {
392393
// Validate validates the fields and sets the default values.
393394
func (o *CommitOptions) Validate(r *Repository) error {
394395
if o.Author == nil {
395-
return ErrMissingAuthor
396+
if err := o.loadConfigAuthorAndCommitter(r); err != nil {
397+
return err
398+
}
396399
}
397400

398401
if o.Committer == nil {
@@ -413,6 +416,43 @@ func (o *CommitOptions) Validate(r *Repository) error {
413416
return nil
414417
}
415418

419+
func (o *CommitOptions) loadConfigAuthorAndCommitter(r *Repository) error {
420+
cfg, err := r.ConfigScoped(config.SystemScope)
421+
if err != nil {
422+
return err
423+
}
424+
425+
if o.Author == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
426+
o.Author = &object.Signature{
427+
Name: cfg.Author.Name,
428+
Email: cfg.Author.Email,
429+
When: time.Now(),
430+
}
431+
}
432+
433+
if o.Committer == nil && cfg.Committer.Email != "" && cfg.Committer.Name != "" {
434+
o.Committer = &object.Signature{
435+
Name: cfg.Committer.Name,
436+
Email: cfg.Committer.Email,
437+
When: time.Now(),
438+
}
439+
}
440+
441+
if o.Author == nil && cfg.User.Email != "" && cfg.User.Name != "" {
442+
o.Author = &object.Signature{
443+
Name: cfg.User.Name,
444+
Email: cfg.User.Email,
445+
When: time.Now(),
446+
}
447+
}
448+
449+
if o.Author == nil {
450+
return ErrMissingAuthor
451+
}
452+
453+
return nil
454+
}
455+
416456
var (
417457
ErrMissingName = errors.New("name field is required")
418458
ErrMissingTagger = errors.New("tagger field is required")

options_test.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package git
22

33
import (
4-
. "gopkg.in/check.v1"
54
"github.com/go-git/go-git/v5/plumbing/object"
5+
. "gopkg.in/check.v1"
66
)
77

88
type OptionsSuite struct {
@@ -18,12 +18,6 @@ func (s *OptionsSuite) TestCommitOptionsParentsFromHEAD(c *C) {
1818
c.Assert(o.Parents, HasLen, 1)
1919
}
2020

21-
func (s *OptionsSuite) TestCommitOptionsMissingAuthor(c *C) {
22-
o := CommitOptions{}
23-
err := o.Validate(s.Repository)
24-
c.Assert(err, Equals, ErrMissingAuthor)
25-
}
26-
2721
func (s *OptionsSuite) TestCommitOptionsCommitter(c *C) {
2822
sig := &object.Signature{}
2923

repository.go

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"strings"
1414
"time"
1515

16-
"golang.org/x/crypto/openpgp"
1716
"github.com/go-git/go-git/v5/config"
1817
"github.com/go-git/go-git/v5/internal/revision"
1918
"github.com/go-git/go-git/v5/plumbing"
@@ -24,6 +23,8 @@ import (
2423
"github.com/go-git/go-git/v5/storage"
2524
"github.com/go-git/go-git/v5/storage/filesystem"
2625
"github.com/go-git/go-git/v5/utils/ioutil"
26+
"github.com/imdario/mergo"
27+
"golang.org/x/crypto/openpgp"
2728

2829
"github.com/go-git/go-billy/v5"
2930
"github.com/go-git/go-billy/v5/osfs"
@@ -155,7 +156,7 @@ func setConfigWorktree(r *Repository, worktree, storage billy.Filesystem) error
155156
return nil
156157
}
157158

158-
cfg, err := r.Storer.Config()
159+
cfg, err := r.Config()
159160
if err != nil {
160161
return err
161162
}
@@ -439,9 +440,42 @@ func (r *Repository) Config() (*config.Config, error) {
439440
return r.Storer.Config()
440441
}
441442

443+
// ConfigScoped returns the repository config, merged with requested scope and
444+
// lower. For example if, config.GlobalScope is given the local and global config
445+
// are returned merged in one config value.
446+
func (r *Repository) ConfigScoped(scope config.Scope) (*config.Config, error) {
447+
// TODO(mcuadros): v6, add this as ConfigOptions.Scoped
448+
449+
var err error
450+
system := config.NewConfig()
451+
if scope >= config.SystemScope {
452+
system, err = config.LoadConfig(config.SystemScope)
453+
if err != nil {
454+
return nil, err
455+
}
456+
}
457+
458+
global := config.NewConfig()
459+
if scope >= config.GlobalScope {
460+
global, err = config.LoadConfig(config.GlobalScope)
461+
if err != nil {
462+
return nil, err
463+
}
464+
}
465+
466+
local, err := r.Storer.Config()
467+
if err != nil {
468+
return nil, err
469+
}
470+
471+
_ = mergo.Merge(global, system)
472+
_ = mergo.Merge(local, global)
473+
return local, nil
474+
}
475+
442476
// Remote return a remote if exists
443477
func (r *Repository) Remote(name string) (*Remote, error) {
444-
cfg, err := r.Storer.Config()
478+
cfg, err := r.Config()
445479
if err != nil {
446480
return nil, err
447481
}
@@ -456,7 +490,7 @@ func (r *Repository) Remote(name string) (*Remote, error) {
456490

457491
// Remotes returns a list with all the remotes
458492
func (r *Repository) Remotes() ([]*Remote, error) {
459-
cfg, err := r.Storer.Config()
493+
cfg, err := r.Config()
460494
if err != nil {
461495
return nil, err
462496
}
@@ -480,7 +514,7 @@ func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error) {
480514

481515
remote := NewRemote(r.Storer, c)
482516

483-
cfg, err := r.Storer.Config()
517+
cfg, err := r.Config()
484518
if err != nil {
485519
return nil, err
486520
}
@@ -511,7 +545,7 @@ func (r *Repository) CreateRemoteAnonymous(c *config.RemoteConfig) (*Remote, err
511545

512546
// DeleteRemote delete a remote from the repository and delete the config
513547
func (r *Repository) DeleteRemote(name string) error {
514-
cfg, err := r.Storer.Config()
548+
cfg, err := r.Config()
515549
if err != nil {
516550
return err
517551
}
@@ -526,7 +560,7 @@ func (r *Repository) DeleteRemote(name string) error {
526560

527561
// Branch return a Branch if exists
528562
func (r *Repository) Branch(name string) (*config.Branch, error) {
529-
cfg, err := r.Storer.Config()
563+
cfg, err := r.Config()
530564
if err != nil {
531565
return nil, err
532566
}
@@ -545,7 +579,7 @@ func (r *Repository) CreateBranch(c *config.Branch) error {
545579
return err
546580
}
547581

548-
cfg, err := r.Storer.Config()
582+
cfg, err := r.Config()
549583
if err != nil {
550584
return err
551585
}
@@ -560,7 +594,7 @@ func (r *Repository) CreateBranch(c *config.Branch) error {
560594

561595
// DeleteBranch delete a Branch from the repository and delete the config
562596
func (r *Repository) DeleteBranch(name string) error {
563-
cfg, err := r.Storer.Config()
597+
cfg, err := r.Config()
564598
if err != nil {
565599
return err
566600
}
@@ -835,7 +869,7 @@ func (r *Repository) cloneRefSpec(o *CloneOptions) []config.RefSpec {
835869
}
836870

837871
func (r *Repository) setIsBare(isBare bool) error {
838-
cfg, err := r.Storer.Config()
872+
cfg, err := r.Config()
839873
if err != nil {
840874
return err
841875
}
@@ -851,7 +885,7 @@ func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.Remot
851885

852886
c.Fetch = r.cloneRefSpec(o)
853887

854-
cfg, err := r.Storer.Config()
888+
cfg, err := r.Config()
855889
if err != nil {
856890
return err
857891
}
@@ -1541,7 +1575,7 @@ func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, er
15411575
return h, err
15421576
}
15431577
defer ioutil.CheckClose(wc, &err)
1544-
scfg, err := r.Storer.Config()
1578+
scfg, err := r.Config()
15451579
if err != nil {
15461580
return h, err
15471581
}

repository_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,21 @@ func (s *RepositorySuite) TestLogLimitWithOtherParamsPass(c *C) {
18701870
c.Assert(iterErr, Equals, io.EOF)
18711871
}
18721872

1873+
func (s *RepositorySuite) TestConfigScoped(c *C) {
1874+
r, _ := Init(memory.NewStorage(), nil)
1875+
err := r.clone(context.Background(), &CloneOptions{
1876+
URL: s.GetBasicLocalRepositoryURL(),
1877+
})
1878+
1879+
cfg, err := r.ConfigScoped(config.LocalScope)
1880+
c.Assert(err, IsNil)
1881+
c.Assert(cfg.User.Email, Equals, "")
1882+
1883+
cfg, err = r.ConfigScoped(config.SystemScope)
1884+
c.Assert(err, IsNil)
1885+
c.Assert(cfg.User.Email, Not(Equals), "")
1886+
}
1887+
18731888
func (s *RepositorySuite) TestCommit(c *C) {
18741889
r, _ := Init(memory.NewStorage(), nil)
18751890
err := r.clone(context.Background(), &CloneOptions{

submodule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (s *Submodule) Config() *config.Submodule {
3535
// Init initialize the submodule reading the recorded Entry in the index for
3636
// the given submodule
3737
func (s *Submodule) Init() error {
38-
cfg, err := s.w.r.Storer.Config()
38+
cfg, err := s.w.r.Config()
3939
if err != nil {
4040
return err
4141
}

worktree_commit_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@ import (
2424
. "gopkg.in/check.v1"
2525
)
2626

27-
func (s *WorktreeSuite) TestCommitInvalidOptions(c *C) {
27+
func (s *WorktreeSuite) TestCommitEmptyOptions(c *C) {
2828
r, err := Init(memory.NewStorage(), memfs.New())
2929
c.Assert(err, IsNil)
3030

3131
w, err := r.Worktree()
3232
c.Assert(err, IsNil)
3333

34-
hash, err := w.Commit("", &CommitOptions{})
35-
c.Assert(err, Equals, ErrMissingAuthor)
36-
c.Assert(hash.IsZero(), Equals, true)
34+
hash, err := w.Commit("foo", &CommitOptions{})
35+
c.Assert(err, IsNil)
36+
c.Assert(hash.IsZero(), Equals, false)
37+
38+
commit, err := r.CommitObject(hash)
39+
c.Assert(err, IsNil)
40+
c.Assert(commit.Author.Name, Not(Equals), "")
3741
}
3842

3943
func (s *WorktreeSuite) TestCommitInitial(c *C) {

0 commit comments

Comments
 (0)