diff options
Diffstat (limited to 'config')
-rw-r--r-- | config/branch.go | 23 | ||||
-rw-r--r-- | config/branch_test.go | 8 | ||||
-rw-r--r-- | config/config.go | 3 | ||||
-rw-r--r-- | config/config_test.go | 6 | ||||
-rw-r--r-- | config/modules_test.go | 6 | ||||
-rw-r--r-- | config/refspec.go | 15 | ||||
-rw-r--r-- | config/refspec_test.go | 70 |
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", |