diff options
Diffstat (limited to 'config')
-rw-r--r-- | config/config.go | 73 | ||||
-rw-r--r-- | config/config_test.go | 41 | ||||
-rw-r--r-- | config/modules.go | 19 | ||||
-rw-r--r-- | config/refspec.go | 12 |
4 files changed, 113 insertions, 32 deletions
diff --git a/config/config.go b/config/config.go index 866ae8e..259ebf9 100644 --- a/config/config.go +++ b/config/config.go @@ -32,14 +32,19 @@ var ( // Config contains the repository configuration // ftp://www.kernel.org/pub/software/scm/git/docs/git-config.html#FILES type Config struct { - // Core variables Core struct { // IsBare if true this repository is assumed to be bare and has no - // working directory associated with it + // working directory associated with it. IsBare bool + // Worktree is the path to the root of the working tree. + Worktree string } - // Remote list of repository remotes + // Remotes list of repository remotes, the key of the map is the name + // of the remote, should equal to RemoteConfig.Name. Remotes map[string]*RemoteConfig + // Submodules list of repository submodules, the key of the map is the name + // of the submodule, should equal to Submodule.Name. + Submodules map[string]*Submodule // contains the raw information of a config file, the main goal is preserve // the parsed information from the original format, to avoid missing @@ -47,15 +52,16 @@ type Config struct { raw *format.Config } -// NewConfig returns a new empty Config +// NewConfig returns a new empty Config. func NewConfig() *Config { return &Config{ - Remotes: make(map[string]*RemoteConfig, 0), - raw: format.New(), + Remotes: make(map[string]*RemoteConfig, 0), + Submodules: make(map[string]*Submodule, 0), + raw: format.New(), } } -// Validate validates the fields and sets the default values +// Validate validates the fields and sets the default values. func (c *Config) Validate() error { for name, r := range c.Remotes { if r.Name != name { @@ -71,14 +77,16 @@ func (c *Config) Validate() error { } const ( - remoteSection = "remote" - coreSection = "core" - fetchKey = "fetch" - urlKey = "url" - bareKey = "bare" + remoteSection = "remote" + submoduleSection = "submodule" + coreSection = "core" + fetchKey = "fetch" + urlKey = "url" + bareKey = "bare" + worktreeKey = "worktree" ) -// Unmarshal parses a git-config file and stores it +// Unmarshal parses a git-config file and stores it. func (c *Config) Unmarshal(b []byte) error { r := bytes.NewBuffer(b) d := format.NewDecoder(r) @@ -89,6 +97,7 @@ func (c *Config) Unmarshal(b []byte) error { } c.unmarshalCore() + c.unmarshalSubmodules() return c.unmarshalRemotes() } @@ -97,6 +106,8 @@ func (c *Config) unmarshalCore() { if s.Options.Get(bareKey) == "true" { c.Core.IsBare = true } + + c.Core.Worktree = s.Options.Get(worktreeKey) } func (c *Config) unmarshalRemotes() error { @@ -113,10 +124,21 @@ func (c *Config) unmarshalRemotes() error { return nil } -// Marshal returns Config encoded as a git-config file +func (c *Config) unmarshalSubmodules() { + s := c.raw.Section(submoduleSection) + for _, sub := range s.Subsections { + m := &Submodule{} + m.unmarshal(sub) + + c.Submodules[m.Name] = m + } +} + +// Marshal returns Config encoded as a git-config file. func (c *Config) Marshal() ([]byte, error) { c.marshalCore() c.marshalRemotes() + c.marshalSubmodules() buf := bytes.NewBuffer(nil) if err := format.NewEncoder(buf).Encode(c.raw); err != nil { @@ -129,6 +151,10 @@ func (c *Config) Marshal() ([]byte, error) { func (c *Config) marshalCore() { s := c.raw.Section(coreSection) s.SetOption(bareKey, fmt.Sprintf("%t", c.Core.IsBare)) + + if c.Core.Worktree != "" { + s.SetOption(worktreeKey, c.Core.Worktree) + } } func (c *Config) marshalRemotes() { @@ -142,7 +168,22 @@ func (c *Config) marshalRemotes() { } } -// RemoteConfig contains the configuration for a given remote repository +func (c *Config) marshalSubmodules() { + s := c.raw.Section(submoduleSection) + s.Subsections = make(format.Subsections, len(c.Submodules)) + + var i int + for _, r := range c.Submodules { + section := r.marshal() + // the submodule section at config is a subset of the .gitmodule file + // we should remove the non-valid options for the config file. + section.RemoveOption(pathKey) + s.Subsections[i] = section + i++ + } +} + +// RemoteConfig contains the configuration for a given remote repository. type RemoteConfig struct { // Name of the remote Name string @@ -156,7 +197,7 @@ type RemoteConfig struct { raw *format.Subsection } -// Validate validates the fields and sets the default values +// Validate validates the fields and sets the default values. func (c *RemoteConfig) Validate() error { if c.Name == "" { return ErrRemoteConfigEmptyName diff --git a/config/config_test.go b/config/config_test.go index 2bcefe4..cfab36d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -9,9 +9,14 @@ var _ = Suite(&ConfigSuite{}) func (s *ConfigSuite) TestUnmarshall(c *C) { input := []byte(`[core] bare = true + worktree = foo [remote "origin"] url = git@github.com:mcuadros/go-git.git fetch = +refs/heads/*:refs/remotes/origin/* +[submodule "qux"] + path = qux + url = https://github.com/foo/qux.git + branch = bar [branch "master"] remote = origin merge = refs/heads/master @@ -22,15 +27,51 @@ func (s *ConfigSuite) TestUnmarshall(c *C) { c.Assert(err, IsNil) c.Assert(cfg.Core.IsBare, Equals, true) + c.Assert(cfg.Core.Worktree, Equals, "foo") c.Assert(cfg.Remotes, HasLen, 1) c.Assert(cfg.Remotes["origin"].Name, Equals, "origin") c.Assert(cfg.Remotes["origin"].URL, Equals, "git@github.com:mcuadros/go-git.git") c.Assert(cfg.Remotes["origin"].Fetch, DeepEquals, []RefSpec{"+refs/heads/*:refs/remotes/origin/*"}) + c.Assert(cfg.Submodules, HasLen, 1) + c.Assert(cfg.Submodules["qux"].Name, Equals, "qux") + c.Assert(cfg.Submodules["qux"].URL, Equals, "https://github.com/foo/qux.git") + c.Assert(cfg.Submodules["qux"].Branch, Equals, "bar") + +} + +func (s *ConfigSuite) TestMarshall(c *C) { + output := []byte(`[core] + bare = true + worktree = bar +[remote "origin"] + url = git@github.com:mcuadros/go-git.git +[submodule "qux"] + url = https://github.com/foo/qux.git +`) + + cfg := NewConfig() + cfg.Core.IsBare = true + cfg.Core.Worktree = "bar" + cfg.Remotes["origin"] = &RemoteConfig{ + Name: "origin", + URL: "git@github.com:mcuadros/go-git.git", + } + + cfg.Submodules["qux"] = &Submodule{ + Name: "qux", + URL: "https://github.com/foo/qux.git", + } + + b, err := cfg.Marshal() + c.Assert(err, IsNil) + + c.Assert(string(b), Equals, string(output)) } func (s *ConfigSuite) TestUnmarshallMarshall(c *C) { input := []byte(`[core] bare = true + worktree = foo custom = ignored [remote "origin"] url = git@github.com:mcuadros/go-git.git diff --git a/config/modules.go b/config/modules.go index 4d98b16..3d01117 100644 --- a/config/modules.go +++ b/config/modules.go @@ -15,7 +15,7 @@ var ( // Modules defines the submodules properties, represents a .gitmodules file // https://www.kernel.org/pub/software/scm/git/docs/gitmodules.html type Modules struct { - // Submodules is a map of submodules being the key the name of the submodule + // Submodules is a map of submodules being the key the name of the submodule. Submodules map[string]*Submodule raw *format.Config @@ -30,12 +30,11 @@ func NewModules() *Modules { } const ( - submoduleSection = "submodule" - pathKey = "path" - branchKey = "branch" + pathKey = "path" + branchKey = "branch" ) -// Unmarshal parses a git-config file and stores it +// Unmarshal parses a git-config file and stores it. func (m *Modules) Unmarshal(b []byte) error { r := bytes.NewBuffer(b) d := format.NewDecoder(r) @@ -56,7 +55,7 @@ func (m *Modules) Unmarshal(b []byte) error { return nil } -// Marshal returns Modules encoded as a git-config file +// Marshal returns Modules encoded as a git-config file. func (m *Modules) Marshal() ([]byte, error) { s := m.raw.Section(submoduleSection) s.Subsections = make(format.Subsections, len(m.Submodules)) @@ -75,12 +74,12 @@ func (m *Modules) Marshal() ([]byte, error) { return buf.Bytes(), nil } -// Submodule defines a submodule +// Submodule defines a submodule. type Submodule struct { // Name module name Name string // Path defines the path, relative to the top-level directory of the Git - // working tree, + // working tree. Path string // URL defines a URL from which the submodule repository can be cloned. URL string @@ -89,11 +88,11 @@ type Submodule struct { Branch string // raw representation of the subsection, filled by marshal or unmarshal are - // called + // called. raw *format.Subsection } -// Validate validates the fields and sets the default values +// Validate validates the fields and sets the default values. func (m *Submodule) Validate() error { if m.Path == "" { return ErrModuleEmptyPath diff --git a/config/refspec.go b/config/refspec.go index dd68edc..9441df8 100644 --- a/config/refspec.go +++ b/config/refspec.go @@ -49,7 +49,7 @@ func (s RefSpec) Validate() error { return ErrRefSpecMalformedWildcard } -// IsForceUpdate returns if update is allowed in non fast-forward merges +// IsForceUpdate returns if update is allowed in non fast-forward merges. func (s RefSpec) IsForceUpdate() bool { if s[0] == refSpecForce[0] { return true @@ -67,7 +67,7 @@ func (s RefSpec) IsDelete() bool { return false } -// Src return the src side +// Src return the src side. func (s RefSpec) Src() string { spec := string(s) start := strings.Index(spec, refSpecForce) + 1 @@ -76,7 +76,7 @@ func (s RefSpec) Src() string { return spec[start:end] } -// Match match the given plumbing.ReferenceName against the source +// Match match the given plumbing.ReferenceName against the source. func (s RefSpec) Match(n plumbing.ReferenceName) bool { if !s.IsWildcard() { return s.matchExact(n) @@ -85,7 +85,7 @@ func (s RefSpec) Match(n plumbing.ReferenceName) bool { return s.matchGlob(n) } -// IsWildcard returns true if the RefSpec contains a wildcard +// IsWildcard returns true if the RefSpec contains a wildcard. func (s RefSpec) IsWildcard() bool { return strings.Index(string(s), refSpecWildcard) != -1 } @@ -110,7 +110,7 @@ func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool { strings.HasSuffix(name, suffix) } -// Dst returns the destination for the given remote reference +// Dst returns the destination for the given remote reference. func (s RefSpec) Dst(n plumbing.ReferenceName) plumbing.ReferenceName { spec := string(s) start := strings.Index(spec, refSpecSeparator) + 1 @@ -133,7 +133,7 @@ func (s RefSpec) String() string { return string(s) } -// MatchAny returns true if any of the RefSpec match with the given ReferenceName +// MatchAny returns true if any of the RefSpec match with the given ReferenceName. func MatchAny(l []RefSpec, n plumbing.ReferenceName) bool { for _, r := range l { if r.Match(n) { |