fork of go-git with some jj specific features
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.11.0 143 lines 3.5 kB view raw
1package config 2 3import ( 4 "errors" 5 "strings" 6 7 "gopkg.in/src-d/go-git.v4/plumbing" 8) 9 10const ( 11 refSpecWildcard = "*" 12 refSpecForce = "+" 13 refSpecSeparator = ":" 14) 15 16var ( 17 ErrRefSpecMalformedSeparator = errors.New("malformed refspec, separators are wrong") 18 ErrRefSpecMalformedWildcard = errors.New("malformed refspec, mismatched number of wildcards") 19) 20 21// RefSpec is a mapping from local branches to remote references 22// The format of the refspec is an optional +, followed by <src>:<dst>, where 23// <src> is the pattern for references on the remote side and <dst> is where 24// those references will be written locally. The + tells Git to update the 25// reference even if it isn’t a fast-forward. 26// eg.: "+refs/heads/*:refs/remotes/origin/*" 27// 28// https://git-scm.com/book/es/v2/Git-Internals-The-Refspec 29type RefSpec string 30 31// Validate validates the RefSpec 32func (s RefSpec) Validate() error { 33 spec := string(s) 34 if strings.Count(spec, refSpecSeparator) != 1 { 35 return ErrRefSpecMalformedSeparator 36 } 37 38 sep := strings.Index(spec, refSpecSeparator) 39 if sep == len(spec)-1 { 40 return ErrRefSpecMalformedSeparator 41 } 42 43 ws := strings.Count(spec[0:sep], refSpecWildcard) 44 wd := strings.Count(spec[sep+1:], refSpecWildcard) 45 if ws == wd && ws < 2 && wd < 2 { 46 return nil 47 } 48 49 return ErrRefSpecMalformedWildcard 50} 51 52// IsForceUpdate returns if update is allowed in non fast-forward merges. 53func (s RefSpec) IsForceUpdate() bool { 54 return s[0] == refSpecForce[0] 55} 56 57// IsDelete returns true if the refspec indicates a delete (empty src). 58func (s RefSpec) IsDelete() bool { 59 return s[0] == refSpecSeparator[0] 60} 61 62// Src return the src side. 63func (s RefSpec) Src() string { 64 spec := string(s) 65 66 var start int 67 if s.IsForceUpdate() { 68 start = 1 69 } else { 70 start = 0 71 } 72 end := strings.Index(spec, refSpecSeparator) 73 74 return spec[start:end] 75} 76 77// Match match the given plumbing.ReferenceName against the source. 78func (s RefSpec) Match(n plumbing.ReferenceName) bool { 79 if !s.IsWildcard() { 80 return s.matchExact(n) 81 } 82 83 return s.matchGlob(n) 84} 85 86// IsWildcard returns true if the RefSpec contains a wildcard. 87func (s RefSpec) IsWildcard() bool { 88 return strings.Contains(string(s), refSpecWildcard) 89} 90 91func (s RefSpec) matchExact(n plumbing.ReferenceName) bool { 92 return s.Src() == n.String() 93} 94 95func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool { 96 src := s.Src() 97 name := n.String() 98 wildcard := strings.Index(src, refSpecWildcard) 99 100 var prefix, suffix string 101 prefix = src[0:wildcard] 102 if len(src) < wildcard { 103 suffix = src[wildcard+1 : len(suffix)] 104 } 105 106 return len(name) > len(prefix)+len(suffix) && 107 strings.HasPrefix(name, prefix) && 108 strings.HasSuffix(name, suffix) 109} 110 111// Dst returns the destination for the given remote reference. 112func (s RefSpec) Dst(n plumbing.ReferenceName) plumbing.ReferenceName { 113 spec := string(s) 114 start := strings.Index(spec, refSpecSeparator) + 1 115 dst := spec[start:] 116 src := s.Src() 117 118 if !s.IsWildcard() { 119 return plumbing.ReferenceName(dst) 120 } 121 122 name := n.String() 123 ws := strings.Index(src, refSpecWildcard) 124 wd := strings.Index(dst, refSpecWildcard) 125 match := name[ws : len(name)-(len(src)-(ws+1))] 126 127 return plumbing.ReferenceName(dst[0:wd] + match + dst[wd+1:]) 128} 129 130func (s RefSpec) String() string { 131 return string(s) 132} 133 134// MatchAny returns true if any of the RefSpec match with the given ReferenceName. 135func MatchAny(l []RefSpec, n plumbing.ReferenceName) bool { 136 for _, r := range l { 137 if r.Match(n) { 138 return true 139 } 140 } 141 142 return false 143}