fork of go-git with some jj specific features
at main 106 lines 1.9 kB view raw
1package gitattributes 2 3import ( 4 "path/filepath" 5 "strings" 6) 7 8const ( 9 patternDirSep = "/" 10 zeroToManyDirs = "**" 11) 12 13// Pattern defines a gitattributes pattern. 14type Pattern interface { 15 // Match matches the given path to the pattern. 16 Match(path []string) bool 17} 18 19type pattern struct { 20 domain []string 21 pattern []string 22} 23 24// ParsePattern parses a gitattributes pattern string into the Pattern 25// structure. 26func ParsePattern(p string, domain []string) Pattern { 27 return &pattern{ 28 domain: domain, 29 pattern: strings.Split(p, patternDirSep), 30 } 31} 32 33func (p *pattern) Match(path []string) bool { 34 if len(path) <= len(p.domain) { 35 return false 36 } 37 for i, e := range p.domain { 38 if path[i] != e { 39 return false 40 } 41 } 42 43 if len(p.pattern) == 1 { 44 // for a simple rule, .gitattribute matching rules differs from 45 // .gitignore and only the last part of the path is considered. 46 path = path[len(path)-1:] 47 } else { 48 path = path[len(p.domain):] 49 } 50 51 pattern := p.pattern 52 var match, doublestar bool 53 var err error 54 for _, part := range path { 55 // path is deeper than pattern 56 if len(pattern) == 0 { 57 return false 58 } 59 60 // skip empty 61 if pattern[0] == "" { 62 pattern = pattern[1:] 63 } 64 65 // eat doublestar 66 if pattern[0] == zeroToManyDirs { 67 pattern = pattern[1:] 68 if len(pattern) == 0 { 69 return true 70 } 71 doublestar = true 72 } 73 74 switch { 75 case strings.Contains(pattern[0], "**"): 76 return false 77 78 // keep going down the path until we hit a match 79 case doublestar: 80 match, err = filepath.Match(pattern[0], part) 81 if err != nil { 82 return false 83 } 84 85 if match { 86 doublestar = false 87 pattern = pattern[1:] 88 } 89 90 default: 91 match, err = filepath.Match(pattern[0], part) 92 if err != nil { 93 return false 94 } 95 if !match { 96 return false 97 } 98 pattern = pattern[1:] 99 } 100 } 101 102 if len(pattern) > 0 { 103 return false 104 } 105 return match 106}