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 v5.13.1 155 lines 3.8 kB view raw
1package config 2 3import ( 4 "errors" 5 "strings" 6 7 "github.com/go-git/go-git/v5/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/en/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// IsExactSHA1 returns true if the source is a SHA1 hash. 63func (s RefSpec) IsExactSHA1() bool { 64 return plumbing.IsHash(s.Src()) 65} 66 67// Src returns the src side. 68func (s RefSpec) Src() string { 69 spec := string(s) 70 71 var start int 72 if s.IsForceUpdate() { 73 start = 1 74 } else { 75 start = 0 76 } 77 78 end := strings.Index(spec, refSpecSeparator) 79 return spec[start:end] 80} 81 82// Match match the given plumbing.ReferenceName against the source. 83func (s RefSpec) Match(n plumbing.ReferenceName) bool { 84 if !s.IsWildcard() { 85 return s.matchExact(n) 86 } 87 88 return s.matchGlob(n) 89} 90 91// IsWildcard returns true if the RefSpec contains a wildcard. 92func (s RefSpec) IsWildcard() bool { 93 return strings.Contains(string(s), refSpecWildcard) 94} 95 96func (s RefSpec) matchExact(n plumbing.ReferenceName) bool { 97 return s.Src() == n.String() 98} 99 100func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool { 101 src := s.Src() 102 name := n.String() 103 wildcard := strings.Index(src, refSpecWildcard) 104 105 var prefix, suffix string 106 prefix = src[0:wildcard] 107 if len(src) > wildcard+1 { 108 suffix = src[wildcard+1:] 109 } 110 111 return len(name) >= len(prefix)+len(suffix) && 112 strings.HasPrefix(name, prefix) && 113 strings.HasSuffix(name, suffix) 114} 115 116// Dst returns the destination for the given remote reference. 117func (s RefSpec) Dst(n plumbing.ReferenceName) plumbing.ReferenceName { 118 spec := string(s) 119 start := strings.Index(spec, refSpecSeparator) + 1 120 dst := spec[start:] 121 src := s.Src() 122 123 if !s.IsWildcard() { 124 return plumbing.ReferenceName(dst) 125 } 126 127 name := n.String() 128 ws := strings.Index(src, refSpecWildcard) 129 wd := strings.Index(dst, refSpecWildcard) 130 match := name[ws : len(name)-(len(src)-(ws+1))] 131 132 return plumbing.ReferenceName(dst[0:wd] + match + dst[wd+1:]) 133} 134 135func (s RefSpec) Reverse() RefSpec { 136 spec := string(s) 137 separator := strings.Index(spec, refSpecSeparator) 138 139 return RefSpec(spec[separator+1:] + refSpecSeparator + spec[:separator]) 140} 141 142func (s RefSpec) String() string { 143 return string(s) 144} 145 146// MatchAny returns true if any of the RefSpec match with the given ReferenceName. 147func MatchAny(l []RefSpec, n plumbing.ReferenceName) bool { 148 for _, r := range l { 149 if r.Match(n) { 150 return true 151 } 152 } 153 154 return false 155}