github.com/gohugoio/hugo@v0.88.1/hugofs/glob/glob.go (about) 1 // Copyright 2019 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package glob 15 16 import ( 17 "path" 18 "path/filepath" 19 "strings" 20 "sync" 21 22 "github.com/gobwas/glob" 23 "github.com/gobwas/glob/syntax" 24 ) 25 26 type globErr struct { 27 glob glob.Glob 28 err error 29 } 30 31 var ( 32 globCache = make(map[string]globErr) 33 globMu sync.RWMutex 34 ) 35 36 type caseInsensitiveGlob struct { 37 g glob.Glob 38 } 39 40 func (g caseInsensitiveGlob) Match(s string) bool { 41 return g.g.Match(strings.ToLower(s)) 42 43 } 44 func GetGlob(pattern string) (glob.Glob, error) { 45 var eg globErr 46 47 globMu.RLock() 48 var found bool 49 eg, found = globCache[pattern] 50 globMu.RUnlock() 51 if found { 52 return eg.glob, eg.err 53 } 54 55 var err error 56 g, err := glob.Compile(strings.ToLower(pattern), '/') 57 eg = globErr{caseInsensitiveGlob{g: g}, err} 58 59 globMu.Lock() 60 globCache[pattern] = eg 61 globMu.Unlock() 62 63 return eg.glob, eg.err 64 } 65 66 func NormalizePath(p string) string { 67 return strings.Trim(path.Clean(filepath.ToSlash(strings.ToLower(p))), "/.") 68 } 69 70 // ResolveRootDir takes a normalized path on the form "assets/**.json" and 71 // determines any root dir, i.e. any start path without any wildcards. 72 func ResolveRootDir(p string) string { 73 parts := strings.Split(path.Dir(p), "/") 74 var roots []string 75 for _, part := range parts { 76 if HasGlobChar(part) { 77 break 78 } 79 roots = append(roots, part) 80 } 81 82 if len(roots) == 0 { 83 return "" 84 } 85 86 return strings.Join(roots, "/") 87 } 88 89 // FilterGlobParts removes any string with glob wildcard. 90 func FilterGlobParts(a []string) []string { 91 b := a[:0] 92 for _, x := range a { 93 if !HasGlobChar(x) { 94 b = append(b, x) 95 } 96 } 97 return b 98 } 99 100 // HasGlobChar returns whether s contains any glob wildcards. 101 func HasGlobChar(s string) bool { 102 for i := 0; i < len(s); i++ { 103 if syntax.Special(s[i]) { 104 return true 105 } 106 } 107 return false 108 }