feat(dir2config): defaults
This commit is contained in:
71
vendor/gopkg.in/src-d/go-git.v4/config/branch.go
generated
vendored
Normal file
71
vendor/gopkg.in/src-d/go-git.v4/config/branch.go
generated
vendored
Normal file
@ -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()
|
||||
}
|
406
vendor/gopkg.in/src-d/go-git.v4/config/config.go
generated
vendored
Normal file
406
vendor/gopkg.in/src-d/go-git.v4/config/config.go
generated
vendored
Normal file
@ -0,0 +1,406 @@
|
||||
// Package config contains the abstraction of multiple config files
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"gopkg.in/src-d/go-git.v4/internal/url"
|
||||
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
|
||||
}
|
||||
|
||||
func (c *RemoteConfig) IsFirstURLLocal() bool {
|
||||
return url.IsLocalEndpoint(c.URLs[0])
|
||||
}
|
139
vendor/gopkg.in/src-d/go-git.v4/config/modules.go
generated
vendored
Normal file
139
vendor/gopkg.in/src-d/go-git.v4/config/modules.go
generated
vendored
Normal file
@ -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
|
||||
}
|
143
vendor/gopkg.in/src-d/go-git.v4/config/refspec.go
generated
vendored
Normal file
143
vendor/gopkg.in/src-d/go-git.v4/config/refspec.go
generated
vendored
Normal file
@ -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
|
||||
}
|
Reference in New Issue
Block a user