summaryrefslogtreecommitdiffstats
path: root/vendor/gopkg.in/src-d/go-git.v4/config
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gopkg.in/src-d/go-git.v4/config')
-rw-r--r--vendor/gopkg.in/src-d/go-git.v4/config/branch.go71
-rw-r--r--vendor/gopkg.in/src-d/go-git.v4/config/config.go401
-rw-r--r--vendor/gopkg.in/src-d/go-git.v4/config/modules.go139
-rw-r--r--vendor/gopkg.in/src-d/go-git.v4/config/refspec.go143
4 files changed, 754 insertions, 0 deletions
diff --git a/vendor/gopkg.in/src-d/go-git.v4/config/branch.go b/vendor/gopkg.in/src-d/go-git.v4/config/branch.go
new file mode 100644
index 0000000000..e18073c968
--- /dev/null
+++ b/vendor/gopkg.in/src-d/go-git.v4/config/branch.go
@@ -0,0 +1,71 @@
+package config
+
+import (
+ "errors"
+
+ "gopkg.in/src-d/go-git.v4/plumbing"
+ format "gopkg.in/src-d/go-git.v4/plumbing/format/config"
+)
+
+var (
+ errBranchEmptyName = errors.New("branch config: empty name")
+ errBranchInvalidMerge = errors.New("branch config: invalid merge")
+)
+
+// Branch contains information on the
+// local branches and which remote to track
+type Branch struct {
+ // Name of branch
+ Name string
+ // Remote name of remote to track
+ Remote string
+ // Merge is the local refspec for the branch
+ Merge plumbing.ReferenceName
+
+ raw *format.Subsection
+}
+
+// Validate validates fields of branch
+func (b *Branch) Validate() error {
+ if b.Name == "" {
+ return errBranchEmptyName
+ }
+
+ if b.Merge != "" && !b.Merge.IsBranch() {
+ return errBranchInvalidMerge
+ }
+
+ return nil
+}
+
+func (b *Branch) marshal() *format.Subsection {
+ if b.raw == nil {
+ b.raw = &format.Subsection{}
+ }
+
+ b.raw.Name = b.Name
+
+ if b.Remote == "" {
+ b.raw.RemoveOption(remoteSection)
+ } else {
+ b.raw.SetOption(remoteSection, b.Remote)
+ }
+
+ if b.Merge == "" {
+ b.raw.RemoveOption(mergeKey)
+ } else {
+ b.raw.SetOption(mergeKey, string(b.Merge))
+ }
+
+ return b.raw
+}
+
+func (b *Branch) unmarshal(s *format.Subsection) error {
+ b.raw = s
+
+ b.Name = b.raw.Name
+ b.Remote = b.raw.Options.Get(remoteSection)
+ b.Merge = plumbing.ReferenceName(b.raw.Options.Get(mergeKey))
+
+ return b.Validate()
+}
diff --git a/vendor/gopkg.in/src-d/go-git.v4/config/config.go b/vendor/gopkg.in/src-d/go-git.v4/config/config.go
new file mode 100644
index 0000000000..a637f6d709
--- /dev/null
+++ b/vendor/gopkg.in/src-d/go-git.v4/config/config.go
@@ -0,0 +1,401 @@
+// Package config contains the abstraction of multiple config files
+package config
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "sort"
+ "strconv"
+
+ format "gopkg.in/src-d/go-git.v4/plumbing/format/config"
+)
+
+const (
+ // DefaultFetchRefSpec is the default refspec used for fetch.
+ DefaultFetchRefSpec = "+refs/heads/*:refs/remotes/%s/*"
+ // DefaultPushRefSpec is the default refspec used for push.
+ DefaultPushRefSpec = "refs/heads/*:refs/heads/*"
+)
+
+// ConfigStorer generic storage of Config object
+type ConfigStorer interface {
+ Config() (*Config, error)
+ SetConfig(*Config) error
+}
+
+var (
+ ErrInvalid = errors.New("config invalid key in remote or branch")
+ ErrRemoteConfigNotFound = errors.New("remote config not found")
+ ErrRemoteConfigEmptyURL = errors.New("remote config: empty URL")
+ ErrRemoteConfigEmptyName = errors.New("remote config: empty name")
+)
+
+// Config contains the repository configuration
+// ftp://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
+ // working directory associated with it.
+ IsBare bool
+ // Worktree is the path to the root of the working tree.
+ Worktree string
+ // CommentChar is the character indicating the start of a
+ // comment for commands like commit and tag
+ CommentChar string
+ }
+
+ Pack struct {
+ // Window controls the size of the sliding window for delta
+ // compression. The default is 10. A value of 0 turns off
+ // delta compression entirely.
+ Window uint
+ }
+
+ // 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
+ // Branches list of branches, the key is the branch name and should
+ // equal Branch.Name
+ Branches map[string]*Branch
+ // Raw contains the raw information of a config file. The main goal is
+ // preserve the parsed information from the original format, to avoid
+ // dropping unsupported fields.
+ Raw *format.Config
+}
+
+// NewConfig returns a new empty Config.
+func NewConfig() *Config {
+ config := &Config{
+ Remotes: make(map[string]*RemoteConfig),
+ Submodules: make(map[string]*Submodule),
+ Branches: make(map[string]*Branch),
+ Raw: format.New(),
+ }
+
+ config.Pack.Window = DefaultPackWindow
+
+ return config
+}
+
+// Validate validates the fields and sets the default values.
+func (c *Config) Validate() error {
+ for name, r := range c.Remotes {
+ if r.Name != name {
+ return ErrInvalid
+ }
+
+ if err := r.Validate(); err != nil {
+ return err
+ }
+ }
+
+ for name, b := range c.Branches {
+ if b.Name != name {
+ return ErrInvalid
+ }
+
+ if err := b.Validate(); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+const (
+ remoteSection = "remote"
+ submoduleSection = "submodule"
+ branchSection = "branch"
+ coreSection = "core"
+ packSection = "pack"
+ fetchKey = "fetch"
+ urlKey = "url"
+ bareKey = "bare"
+ worktreeKey = "worktree"
+ commentCharKey = "commentChar"
+ windowKey = "window"
+ mergeKey = "merge"
+
+ // DefaultPackWindow holds the number of previous objects used to
+ // generate deltas. The value 10 is the same used by git command.
+ DefaultPackWindow = uint(10)
+)
+
+// Unmarshal parses a git-config file and stores it.
+func (c *Config) Unmarshal(b []byte) error {
+ r := bytes.NewBuffer(b)
+ d := format.NewDecoder(r)
+
+ c.Raw = format.New()
+ if err := d.Decode(c.Raw); err != nil {
+ return err
+ }
+
+ c.unmarshalCore()
+ if err := c.unmarshalPack(); err != nil {
+ return err
+ }
+ unmarshalSubmodules(c.Raw, c.Submodules)
+
+ if err := c.unmarshalBranches(); err != nil {
+ return err
+ }
+
+ return c.unmarshalRemotes()
+}
+
+func (c *Config) unmarshalCore() {
+ s := c.Raw.Section(coreSection)
+ if s.Options.Get(bareKey) == "true" {
+ c.Core.IsBare = true
+ }
+
+ c.Core.Worktree = s.Options.Get(worktreeKey)
+ c.Core.CommentChar = s.Options.Get(commentCharKey)
+}
+
+func (c *Config) unmarshalPack() error {
+ s := c.Raw.Section(packSection)
+ window := s.Options.Get(windowKey)
+ if window == "" {
+ c.Pack.Window = DefaultPackWindow
+ } else {
+ winUint, err := strconv.ParseUint(window, 10, 32)
+ if err != nil {
+ return err
+ }
+ c.Pack.Window = uint(winUint)
+ }
+ return nil
+}
+
+func (c *Config) unmarshalRemotes() error {
+ s := c.Raw.Section(remoteSection)
+ for _, sub := range s.Subsections {
+ r := &RemoteConfig{}
+ if err := r.unmarshal(sub); err != nil {
+ return err
+ }
+
+ c.Remotes[r.Name] = r
+ }
+
+ return nil
+}
+
+func unmarshalSubmodules(fc *format.Config, submodules map[string]*Submodule) {
+ s := fc.Section(submoduleSection)
+ for _, sub := range s.Subsections {
+ m := &Submodule{}
+ m.unmarshal(sub)
+
+ if m.Validate() == ErrModuleBadPath {
+ continue
+ }
+
+ submodules[m.Name] = m
+ }
+}
+
+func (c *Config) unmarshalBranches() error {
+ bs := c.Raw.Section(branchSection)
+ for _, sub := range bs.Subsections {
+ b := &Branch{}
+
+ if err := b.unmarshal(sub); err != nil {
+ return err
+ }
+
+ c.Branches[b.Name] = b
+ }
+ return nil
+}
+
+// Marshal returns Config encoded as a git-config file.
+func (c *Config) Marshal() ([]byte, error) {
+ c.marshalCore()
+ c.marshalPack()
+ c.marshalRemotes()
+ c.marshalSubmodules()
+ c.marshalBranches()
+
+ buf := bytes.NewBuffer(nil)
+ if err := format.NewEncoder(buf).Encode(c.Raw); err != nil {
+ return nil, err
+ }
+
+ return buf.Bytes(), nil
+}
+
+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) marshalPack() {
+ s := c.Raw.Section(packSection)
+ if c.Pack.Window != DefaultPackWindow {
+ s.SetOption(windowKey, fmt.Sprintf("%d", c.Pack.Window))
+ }
+}
+
+func (c *Config) marshalRemotes() {
+ s := c.Raw.Section(remoteSection)
+ newSubsections := make(format.Subsections, 0, len(c.Remotes))
+ added := make(map[string]bool)
+ for _, subsection := range s.Subsections {
+ if remote, ok := c.Remotes[subsection.Name]; ok {
+ newSubsections = append(newSubsections, remote.marshal())
+ added[subsection.Name] = true
+ }
+ }
+
+ remoteNames := make([]string, 0, len(c.Remotes))
+ for name := range c.Remotes {
+ remoteNames = append(remoteNames, name)
+ }
+
+ sort.Strings(remoteNames)
+
+ for _, name := range remoteNames {
+ if !added[name] {
+ newSubsections = append(newSubsections, c.Remotes[name].marshal())
+ }
+ }
+
+ s.Subsections = newSubsections
+}
+
+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++
+ }
+}
+
+func (c *Config) marshalBranches() {
+ s := c.Raw.Section(branchSection)
+ newSubsections := make(format.Subsections, 0, len(c.Branches))
+ added := make(map[string]bool)
+ for _, subsection := range s.Subsections {
+ if branch, ok := c.Branches[subsection.Name]; ok {
+ newSubsections = append(newSubsections, branch.marshal())
+ added[subsection.Name] = true
+ }
+ }
+
+ branchNames := make([]string, 0, len(c.Branches))
+ for name := range c.Branches {
+ branchNames = append(branchNames, name)
+ }
+
+ sort.Strings(branchNames)
+
+ for _, name := range branchNames {
+ if !added[name] {
+ newSubsections = append(newSubsections, c.Branches[name].marshal())
+ }
+ }
+
+ s.Subsections = newSubsections
+}
+
+// RemoteConfig contains the configuration for a given remote repository.
+type RemoteConfig struct {
+ // Name of the remote
+ Name string
+ // URLs the URLs of a remote repository. It must be non-empty. Fetch will
+ // always use the first URL, while push will use all of them.
+ URLs []string
+ // Fetch the default set of "refspec" for fetch operation
+ Fetch []RefSpec
+
+ // 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 (c *RemoteConfig) Validate() error {
+ if c.Name == "" {
+ return ErrRemoteConfigEmptyName
+ }
+
+ if len(c.URLs) == 0 {
+ return ErrRemoteConfigEmptyURL
+ }
+
+ for _, r := range c.Fetch {
+ if err := r.Validate(); err != nil {
+ return err
+ }
+ }
+
+ if len(c.Fetch) == 0 {
+ c.Fetch = []RefSpec{RefSpec(fmt.Sprintf(DefaultFetchRefSpec, c.Name))}
+ }
+
+ return nil
+}
+
+func (c *RemoteConfig) unmarshal(s *format.Subsection) error {
+ c.raw = s
+
+ fetch := []RefSpec{}
+ for _, f := range c.raw.Options.GetAll(fetchKey) {
+ rs := RefSpec(f)
+ if err := rs.Validate(); err != nil {
+ return err
+ }
+
+ fetch = append(fetch, rs)
+ }
+
+ c.Name = c.raw.Name
+ c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...)
+ c.Fetch = fetch
+
+ return nil
+}
+
+func (c *RemoteConfig) marshal() *format.Subsection {
+ if c.raw == nil {
+ c.raw = &format.Subsection{}
+ }
+
+ c.raw.Name = c.Name
+ if len(c.URLs) == 0 {
+ c.raw.RemoveOption(urlKey)
+ } else {
+ c.raw.SetOption(urlKey, c.URLs...)
+ }
+
+ if len(c.Fetch) == 0 {
+ c.raw.RemoveOption(fetchKey)
+ } else {
+ var values []string
+ for _, rs := range c.Fetch {
+ values = append(values, rs.String())
+ }
+
+ c.raw.SetOption(fetchKey, values...)
+ }
+
+ return c.raw
+}
diff --git a/vendor/gopkg.in/src-d/go-git.v4/config/modules.go b/vendor/gopkg.in/src-d/go-git.v4/config/modules.go
new file mode 100644
index 0000000000..90758d9327
--- /dev/null
+++ b/vendor/gopkg.in/src-d/go-git.v4/config/modules.go
@@ -0,0 +1,139 @@
+package config
+
+import (
+ "bytes"
+ "errors"
+ "regexp"
+
+ 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")
+ ErrModuleBadPath = errors.New("submodule has an invalid path")
+)
+
+var (
+ // Matches module paths with dotdot ".." components.
+ dotdotPath = regexp.MustCompile(`(^|[/\\])\.\.([/\\]|$)`)
+)
+
+// 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),
+ raw: format.New(),
+ }
+}
+
+const (
+ 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
+ }
+
+ unmarshalSubmodules(m.raw, m.Submodules)
+ 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
+ }
+
+ if dotdotPath.MatchString(m.Path) {
+ return ErrModuleBadPath
+ }
+
+ 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
+}
diff --git a/vendor/gopkg.in/src-d/go-git.v4/config/refspec.go b/vendor/gopkg.in/src-d/go-git.v4/config/refspec.go
new file mode 100644
index 0000000000..391705cccc
--- /dev/null
+++ b/vendor/gopkg.in/src-d/go-git.v4/config/refspec.go
@@ -0,0 +1,143 @@
+package config
+
+import (
+ "errors"
+ "strings"
+
+ "gopkg.in/src-d/go-git.v4/plumbing"
+)
+
+const (
+ refSpecWildcard = "*"
+ refSpecForce = "+"
+ refSpecSeparator = ":"
+)
+
+var (
+ ErrRefSpecMalformedSeparator = errors.New("malformed refspec, separators are wrong")
+ ErrRefSpecMalformedWildcard = errors.New("malformed refspec, mismatched number of wildcards")
+)
+
+// 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
+// reference even if it isn’t a fast-forward.
+// eg.: "+refs/heads/*:refs/remotes/origin/*"
+//
+// https://git-scm.com/book/es/v2/Git-Internals-The-Refspec
+type RefSpec string
+
+// Validate validates the RefSpec
+func (s RefSpec) Validate() error {
+ spec := string(s)
+ if strings.Count(spec, refSpecSeparator) != 1 {
+ return ErrRefSpecMalformedSeparator
+ }
+
+ sep := strings.Index(spec, refSpecSeparator)
+ if sep == len(spec)-1 {
+ return ErrRefSpecMalformedSeparator
+ }
+
+ ws := strings.Count(spec[0:sep], refSpecWildcard)
+ wd := strings.Count(spec[sep+1:], refSpecWildcard)
+ if ws == wd && ws < 2 && wd < 2 {
+ return nil
+ }
+
+ return ErrRefSpecMalformedWildcard
+}
+
+// IsForceUpdate returns if update is allowed in non fast-forward merges.
+func (s RefSpec) IsForceUpdate() bool {
+ return s[0] == refSpecForce[0]
+}
+
+// IsDelete returns true if the refspec indicates a delete (empty src).
+func (s RefSpec) IsDelete() bool {
+ return s[0] == refSpecSeparator[0]
+}
+
+// Src return the src side.
+func (s RefSpec) Src() string {
+ spec := string(s)
+
+ var start int
+ if s.IsForceUpdate() {
+ start = 1
+ } else {
+ start = 0
+ }
+ end := strings.Index(spec, refSpecSeparator)
+
+ return spec[start:end]
+}
+
+// Match match the given plumbing.ReferenceName against the source.
+func (s RefSpec) Match(n plumbing.ReferenceName) bool {
+ if !s.IsWildcard() {
+ return s.matchExact(n)
+ }
+
+ return s.matchGlob(n)
+}
+
+// IsWildcard returns true if the RefSpec contains a wildcard.
+func (s RefSpec) IsWildcard() bool {
+ return strings.Contains(string(s), refSpecWildcard)
+}
+
+func (s RefSpec) matchExact(n plumbing.ReferenceName) bool {
+ return s.Src() == n.String()
+}
+
+func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool {
+ src := s.Src()
+ name := n.String()
+ wildcard := strings.Index(src, refSpecWildcard)
+
+ var prefix, suffix string
+ prefix = src[0:wildcard]
+ if len(src) < wildcard {
+ suffix = src[wildcard+1 : len(suffix)]
+ }
+
+ return len(name) > len(prefix)+len(suffix) &&
+ strings.HasPrefix(name, prefix) &&
+ strings.HasSuffix(name, suffix)
+}
+
+// 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
+ dst := spec[start:]
+ src := s.Src()
+
+ if !s.IsWildcard() {
+ return plumbing.ReferenceName(dst)
+ }
+
+ name := n.String()
+ ws := strings.Index(src, refSpecWildcard)
+ wd := strings.Index(dst, refSpecWildcard)
+ match := name[ws : len(name)-(len(src)-(ws+1))]
+
+ return plumbing.ReferenceName(dst[0:wd] + match + dst[wd+1:])
+}
+
+func (s RefSpec) String() string {
+ return string(s)
+}
+
+// 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) {
+ return true
+ }
+ }
+
+ return false
+}