github.com/influxdata/telegraf@v1.30.3/internal/globpath/globpath.go (about) 1 package globpath 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 8 "github.com/bmatcuk/doublestar/v3" 9 "github.com/gobwas/glob" 10 ) 11 12 type GlobPath struct { 13 path string 14 hasMeta bool 15 HasSuperMeta bool 16 rootGlob string 17 g glob.Glob 18 } 19 20 func Compile(path string) (*GlobPath, error) { 21 out := GlobPath{ 22 hasMeta: hasMeta(path), 23 HasSuperMeta: hasSuperMeta(path), 24 path: filepath.FromSlash(path), 25 } 26 27 // if there are no glob meta characters in the path, don't bother compiling 28 // a glob object 29 if !out.hasMeta || !out.HasSuperMeta { 30 return &out, nil 31 } 32 33 // find the root elements of the object path, the entry point for recursion 34 // when you have a super-meta in your path (which are : 35 // glob(/your/expression/until/first/star/of/super-meta)) 36 out.rootGlob = path[:strings.Index(path, "**")+1] 37 var err error 38 if out.g, err = glob.Compile(path, os.PathSeparator); err != nil { 39 return nil, err 40 } 41 return &out, nil 42 } 43 44 // Match returns all files matching the expression. 45 // If it's a static path, returns path. 46 // All returned path will have the host platform separator. 47 func (g *GlobPath) Match() []string { 48 // This string replacement is for backwards compatibility support 49 // The original implementation allowed **.txt but the double star package requires **/**.txt 50 g.path = strings.ReplaceAll(g.path, "**/**", "**") 51 g.path = strings.ReplaceAll(g.path, "**", "**/**") 52 53 files, _ := doublestar.Glob(g.path) 54 return files 55 } 56 57 // MatchString tests the path string against the glob. The path should contain 58 // the host platform separator. 59 func (g *GlobPath) MatchString(path string) bool { 60 if !g.HasSuperMeta { 61 res, _ := filepath.Match(g.path, path) 62 return res 63 } 64 return g.g.Match(path) 65 } 66 67 // GetRoots returns a list of files and directories which should be optimal 68 // prefixes of matching files when you have a super-meta in your expression : 69 // - any directory under these roots may contain a matching file 70 // - no file outside of these roots can match the pattern 71 // Note that it returns both files and directories. 72 // All returned path will have the host platform separator. 73 func (g *GlobPath) GetRoots() []string { 74 if !g.hasMeta { 75 return []string{g.path} 76 } 77 if !g.HasSuperMeta { 78 matches, _ := filepath.Glob(g.path) 79 return matches 80 } 81 roots, _ := filepath.Glob(g.rootGlob) 82 return roots 83 } 84 85 // hasMeta reports whether path contains any magic glob characters. 86 func hasMeta(path string) bool { 87 return strings.ContainsAny(path, "*?[") 88 } 89 90 // hasSuperMeta reports whether path contains any super magic glob characters (**). 91 func hasSuperMeta(path string) bool { 92 return strings.Contains(path, "**") 93 }