aboutsummaryrefslogtreecommitdiffstats
path: root/config
diff options
context:
space:
mode:
Diffstat (limited to 'config')
-rw-r--r--config/branch.go23
-rw-r--r--config/branch_test.go8
-rw-r--r--config/config.go3
-rw-r--r--config/config_test.go6
-rw-r--r--config/modules_test.go6
-rw-r--r--config/refspec.go15
-rw-r--r--config/refspec_test.go70
7 files changed, 111 insertions, 20 deletions
diff --git a/config/branch.go b/config/branch.go
index e18073c..20dde6e 100644
--- a/config/branch.go
+++ b/config/branch.go
@@ -8,8 +8,9 @@ import (
)
var (
- errBranchEmptyName = errors.New("branch config: empty name")
- errBranchInvalidMerge = errors.New("branch config: invalid merge")
+ errBranchEmptyName = errors.New("branch config: empty name")
+ errBranchInvalidMerge = errors.New("branch config: invalid merge")
+ errBranchInvalidRebase = errors.New("branch config: rebase must be one of 'true' or 'interactive'")
)
// Branch contains information on the
@@ -21,6 +22,10 @@ type Branch struct {
Remote string
// Merge is the local refspec for the branch
Merge plumbing.ReferenceName
+ // Rebase instead of merge when pulling. Valid values are
+ // "true" and "interactive". "false" is undocumented and
+ // typically represented by the non-existence of this field
+ Rebase string
raw *format.Subsection
}
@@ -35,6 +40,13 @@ func (b *Branch) Validate() error {
return errBranchInvalidMerge
}
+ if b.Rebase != "" &&
+ b.Rebase != "true" &&
+ b.Rebase != "interactive" &&
+ b.Rebase != "false" {
+ return errBranchInvalidRebase
+ }
+
return nil
}
@@ -57,6 +69,12 @@ func (b *Branch) marshal() *format.Subsection {
b.raw.SetOption(mergeKey, string(b.Merge))
}
+ if b.Rebase == "" {
+ b.raw.RemoveOption(rebaseKey)
+ } else {
+ b.raw.SetOption(rebaseKey, b.Rebase)
+ }
+
return b.raw
}
@@ -66,6 +84,7 @@ func (b *Branch) unmarshal(s *format.Subsection) error {
b.Name = b.raw.Name
b.Remote = b.raw.Options.Get(remoteSection)
b.Merge = plumbing.ReferenceName(b.raw.Options.Get(mergeKey))
+ b.Rebase = b.raw.Options.Get(rebaseKey)
return b.Validate()
}
diff --git a/config/branch_test.go b/config/branch_test.go
index d74122e..6d9ca86 100644
--- a/config/branch_test.go
+++ b/config/branch_test.go
@@ -38,12 +38,13 @@ func (b *BranchSuite) TestValidateMerge(c *C) {
c.Assert(badBranch.Validate(), NotNil)
}
-func (b *BranchSuite) TestMarshall(c *C) {
+func (b *BranchSuite) TestMarshal(c *C) {
expected := []byte(`[core]
bare = false
[branch "branch-tracking-on-clone"]
remote = fork
merge = refs/heads/branch-tracking-on-clone
+ rebase = interactive
`)
cfg := NewConfig()
@@ -51,6 +52,7 @@ func (b *BranchSuite) TestMarshall(c *C) {
Name: "branch-tracking-on-clone",
Remote: "fork",
Merge: plumbing.ReferenceName("refs/heads/branch-tracking-on-clone"),
+ Rebase: "interactive",
}
actual, err := cfg.Marshal()
@@ -58,12 +60,13 @@ func (b *BranchSuite) TestMarshall(c *C) {
c.Assert(string(actual), Equals, string(expected))
}
-func (b *BranchSuite) TestUnmarshall(c *C) {
+func (b *BranchSuite) TestUnmarshal(c *C) {
input := []byte(`[core]
bare = false
[branch "branch-tracking-on-clone"]
remote = fork
merge = refs/heads/branch-tracking-on-clone
+ rebase = interactive
`)
cfg := NewConfig()
@@ -73,4 +76,5 @@ func (b *BranchSuite) TestUnmarshall(c *C) {
c.Assert(branch.Name, Equals, "branch-tracking-on-clone")
c.Assert(branch.Remote, Equals, "fork")
c.Assert(branch.Merge, Equals, plumbing.ReferenceName("refs/heads/branch-tracking-on-clone"))
+ c.Assert(branch.Rebase, Equals, "interactive")
}
diff --git a/config/config.go b/config/config.go
index 2c3b8b9..321ca04 100644
--- a/config/config.go
+++ b/config/config.go
@@ -33,7 +33,7 @@ var (
)
// Config contains the repository configuration
-// ftp://www.kernel.org/pub/software/scm/git/docs/git-config.html#FILES
+// https://www.kernel.org/pub/software/scm/git/docs/git-config.html#FILES
type Config struct {
Core struct {
// IsBare if true this repository is assumed to be bare and has no
@@ -120,6 +120,7 @@ const (
commentCharKey = "commentChar"
windowKey = "window"
mergeKey = "merge"
+ rebaseKey = "rebase"
// DefaultPackWindow holds the number of previous objects used to
// generate deltas. The value 10 is the same used by git command.
diff --git a/config/config_test.go b/config/config_test.go
index db0932c..54eb5e1 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -9,7 +9,7 @@ type ConfigSuite struct{}
var _ = Suite(&ConfigSuite{})
-func (s *ConfigSuite) TestUnmarshall(c *C) {
+func (s *ConfigSuite) TestUnmarshal(c *C) {
input := []byte(`[core]
bare = true
worktree = foo
@@ -60,7 +60,7 @@ func (s *ConfigSuite) TestUnmarshall(c *C) {
c.Assert(cfg.Branches["master"].Merge, Equals, plumbing.ReferenceName("refs/heads/master"))
}
-func (s *ConfigSuite) TestMarshall(c *C) {
+func (s *ConfigSuite) TestMarshal(c *C) {
output := []byte(`[core]
bare = true
worktree = bar
@@ -119,7 +119,7 @@ func (s *ConfigSuite) TestMarshall(c *C) {
c.Assert(string(b), Equals, string(output))
}
-func (s *ConfigSuite) TestUnmarshallMarshall(c *C) {
+func (s *ConfigSuite) TestUnmarshalMarshal(c *C) {
input := []byte(`[core]
bare = true
worktree = foo
diff --git a/config/modules_test.go b/config/modules_test.go
index 8e10d70..8ea68e7 100644
--- a/config/modules_test.go
+++ b/config/modules_test.go
@@ -39,7 +39,7 @@ func (s *ModulesSuite) TestValidateMissingName(c *C) {
c.Assert(m.Validate(), Equals, ErrModuleEmptyPath)
}
-func (s *ModulesSuite) TestMarshall(c *C) {
+func (s *ModulesSuite) TestMarshal(c *C) {
input := []byte(`[submodule "qux"]
path = qux
url = baz
@@ -54,7 +54,7 @@ func (s *ModulesSuite) TestMarshall(c *C) {
c.Assert(output, DeepEquals, input)
}
-func (s *ModulesSuite) TestUnmarshall(c *C) {
+func (s *ModulesSuite) TestUnmarshal(c *C) {
input := []byte(`[submodule "qux"]
path = qux
url = https://github.com/foo/qux.git
@@ -79,7 +79,7 @@ func (s *ModulesSuite) TestUnmarshall(c *C) {
c.Assert(cfg.Submodules["foo/bar"].Branch, Equals, "dev")
}
-func (s *ModulesSuite) TestUnmarshallMarshall(c *C) {
+func (s *ModulesSuite) TestUnmarshalMarshal(c *C) {
input := []byte(`[submodule "foo/bar"]
path = foo/bar
url = https://github.com/foo/bar.git
diff --git a/config/refspec.go b/config/refspec.go
index 391705c..14bb400 100644
--- a/config/refspec.go
+++ b/config/refspec.go
@@ -18,7 +18,7 @@ var (
ErrRefSpecMalformedWildcard = errors.New("malformed refspec, mismatched number of wildcards")
)
-// RefSpec is a mapping from local branches to remote references
+// RefSpec is a mapping from local branches to remote references.
// The format of the refspec is an optional +, followed by <src>:<dst>, where
// <src> is the pattern for references on the remote side and <dst> is where
// those references will be written locally. The + tells Git to update the
@@ -99,11 +99,11 @@ func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool {
var prefix, suffix string
prefix = src[0:wildcard]
- if len(src) < wildcard {
- suffix = src[wildcard+1 : len(suffix)]
+ if len(src) > wildcard+1 {
+ suffix = src[wildcard+1:]
}
- return len(name) > len(prefix)+len(suffix) &&
+ return len(name) >= len(prefix)+len(suffix) &&
strings.HasPrefix(name, prefix) &&
strings.HasSuffix(name, suffix)
}
@@ -127,6 +127,13 @@ func (s RefSpec) Dst(n plumbing.ReferenceName) plumbing.ReferenceName {
return plumbing.ReferenceName(dst[0:wd] + match + dst[wd+1:])
}
+func (s RefSpec) Reverse() RefSpec {
+ spec := string(s)
+ separator := strings.Index(spec, refSpecSeparator)
+
+ return RefSpec(spec[separator+1:] + refSpecSeparator + spec[:separator])
+}
+
func (s RefSpec) String() string {
return string(s)
}
diff --git a/config/refspec_test.go b/config/refspec_test.go
index 675e075..aaeac73 100644
--- a/config/refspec_test.go
+++ b/config/refspec_test.go
@@ -96,9 +96,38 @@ func (s *RefSpecSuite) TestRefSpecMatch(c *C) {
}
func (s *RefSpecSuite) TestRefSpecMatchGlob(c *C) {
- spec := RefSpec("refs/heads/*:refs/remotes/origin/*")
- c.Assert(spec.Match(plumbing.ReferenceName("refs/tag/foo")), Equals, false)
- c.Assert(spec.Match(plumbing.ReferenceName("refs/heads/foo")), Equals, true)
+ tests := map[string]map[string]bool{
+ "refs/heads/*:refs/remotes/origin/*": {
+ "refs/tag/foo": false,
+ "refs/heads/foo": true,
+ },
+ "refs/heads/*bc:refs/remotes/origin/*bc": {
+ "refs/heads/abc": true,
+ "refs/heads/bc": true,
+ "refs/heads/abx": false,
+ },
+ "refs/heads/a*c:refs/remotes/origin/a*c": {
+ "refs/heads/abc": true,
+ "refs/heads/ac": true,
+ "refs/heads/abx": false,
+ },
+ "refs/heads/ab*:refs/remotes/origin/ab*": {
+ "refs/heads/abc": true,
+ "refs/heads/ab": true,
+ "refs/heads/xbc": false,
+ },
+ }
+
+ for specStr, data := range tests {
+ spec := RefSpec(specStr)
+ for ref, matches := range data {
+ c.Assert(spec.Match(plumbing.ReferenceName(ref)),
+ Equals,
+ matches,
+ Commentf("while matching spec %q against ref %q", specStr, ref),
+ )
+ }
+ }
}
func (s *RefSpecSuite) TestRefSpecDst(c *C) {
@@ -110,12 +139,43 @@ func (s *RefSpecSuite) TestRefSpecDst(c *C) {
}
func (s *RefSpecSuite) TestRefSpecDstBlob(c *C) {
+ ref := "refs/heads/abc"
+ tests := map[string]string{
+ "refs/heads/*:refs/remotes/origin/*": "refs/remotes/origin/abc",
+ "refs/heads/*bc:refs/remotes/origin/*": "refs/remotes/origin/a",
+ "refs/heads/*bc:refs/remotes/origin/*bc": "refs/remotes/origin/abc",
+ "refs/heads/a*c:refs/remotes/origin/*": "refs/remotes/origin/b",
+ "refs/heads/a*c:refs/remotes/origin/a*c": "refs/remotes/origin/abc",
+ "refs/heads/ab*:refs/remotes/origin/*": "refs/remotes/origin/c",
+ "refs/heads/ab*:refs/remotes/origin/ab*": "refs/remotes/origin/abc",
+ "refs/heads/*abc:refs/remotes/origin/*abc": "refs/remotes/origin/abc",
+ "refs/heads/abc*:refs/remotes/origin/abc*": "refs/remotes/origin/abc",
+ // for these two cases, git specifically logs:
+ // error: * Ignoring funny ref 'refs/remotes/origin/' locally
+ // and ignores the ref; go-git does not currently do this validation,
+ // but probably should.
+ // "refs/heads/*abc:refs/remotes/origin/*": "",
+ // "refs/heads/abc*:refs/remotes/origin/*": "",
+ }
+
+ for specStr, dst := range tests {
+ spec := RefSpec(specStr)
+ c.Assert(spec.Dst(plumbing.ReferenceName(ref)).String(),
+ Equals,
+ dst,
+ Commentf("while getting dst from spec %q with ref %q", specStr, ref),
+ )
+ }
+}
+
+func (s *RefSpecSuite) TestRefSpecReverse(c *C) {
spec := RefSpec("refs/heads/*:refs/remotes/origin/*")
c.Assert(
- spec.Dst(plumbing.ReferenceName("refs/heads/foo")).String(), Equals,
- "refs/remotes/origin/foo",
+ spec.Reverse(), Equals,
+ RefSpec("refs/remotes/origin/*:refs/heads/*"),
)
}
+
func (s *RefSpecSuite) TestMatchAny(c *C) {
specs := []RefSpec{
"refs/heads/bar:refs/remotes/origin/foo",