diff options
Diffstat (limited to 'config/modules.go')
-rw-r--r-- | config/modules.go | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/config/modules.go b/config/modules.go new file mode 100644 index 0000000..b1f35b8 --- /dev/null +++ b/config/modules.go @@ -0,0 +1,136 @@ +package config + +import ( + "bytes" + "errors" + + format "gopkg.in/src-d/go-git.v4/plumbing/format/config" +) + +var ( + ErrModuleEmptyURL = errors.New("module config: empty URL") + ErrModuleEmptyPath = errors.New("module config: empty path") +) + +// 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 map[string]*Submodule + + raw *format.Config +} + +// NewModules returns a new empty Modules +func NewModules() *Modules { + return &Modules{ + Submodules: make(map[string]*Submodule, 0), + raw: format.New(), + } +} + +const ( + submoduleSection = "submodule" + pathKey = "path" + branchKey = "branch" +) + +// Unmarshal parses a git-config file and stores it +func (m *Modules) Unmarshal(b []byte) error { + r := bytes.NewBuffer(b) + d := format.NewDecoder(r) + + m.raw = format.New() + if err := d.Decode(m.raw); err != nil { + return err + } + + s := m.raw.Section(submoduleSection) + for _, sub := range s.Subsections { + mod := &Submodule{} + mod.unmarshal(sub) + + m.Submodules[mod.Path] = mod + } + + return nil +} + +// 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)) + + var i int + for _, r := range m.Submodules { + s.Subsections[i] = r.marshal() + i++ + } + + buf := bytes.NewBuffer(nil) + if err := format.NewEncoder(buf).Encode(m.raw); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// 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, + Path string + // URL defines a URL from which the submodule repository can be cloned. + URL string + // Branch is a remote branch name for tracking updates in the upstream + // submodule. Optional value. + Branch string + + // raw representation of the subsection, filled by marshal or unmarshal are + // called + raw *format.Subsection +} + +// Validate validates the fields and sets the default values +func (m *Submodule) Validate() error { + if m.Path == "" { + return ErrModuleEmptyPath + } + + if m.URL == "" { + return ErrModuleEmptyURL + } + + return nil +} + +func (m *Submodule) unmarshal(s *format.Subsection) { + m.raw = s + + m.Name = m.raw.Name + m.Path = m.raw.Option(pathKey) + m.URL = m.raw.Option(urlKey) + m.Branch = m.raw.Option(branchKey) +} + +func (m *Submodule) marshal() *format.Subsection { + if m.raw == nil { + m.raw = &format.Subsection{} + } + + m.raw.Name = m.Name + if m.raw.Name == "" { + m.raw.Name = m.Path + } + + m.raw.SetOption(pathKey, m.Path) + m.raw.SetOption(urlKey, m.URL) + + if m.Branch != "" { + m.raw.SetOption(branchKey, m.Branch) + } + + return m.raw +} |