github.com/please-build/puku@v1.7.3-0.20240516143641-f7d7f4941f57/glob/glob.go (about) 1 package glob 2 3 import ( 4 "os" 5 "path/filepath" 6 ) 7 8 type pattern struct { 9 dir, glob string 10 } 11 12 type Globber struct { 13 cache map[pattern][]string 14 } 15 16 type Args struct { 17 Include, Exclude []string 18 } 19 20 func New() *Globber { 21 return &Globber{cache: map[pattern][]string{}} 22 } 23 24 // Glob is a specialised version of the glob builtin from Please. It assumes: 25 // 1) globs should only match .go files as they're being used in go rules 26 // 2) go rules will never depend on files outside the package dir, so we don't need to support ** 27 // 3) we don't want symlinks, directories and other non-regular files 28 func (g *Globber) Glob(dir string, args *Args) ([]string, error) { 29 inc := map[string]struct{}{} 30 for _, i := range args.Include { 31 fs, err := g.glob(dir, i) 32 if err != nil { 33 return nil, err 34 } 35 36 for _, f := range fs { 37 inc[f] = struct{}{} 38 } 39 } 40 41 for _, i := range args.Exclude { 42 fs, err := g.glob(dir, i) 43 if err != nil { 44 return nil, err 45 } 46 47 for _, f := range fs { 48 delete(inc, f) 49 } 50 } 51 52 ret := make([]string, 0, len(inc)) 53 for i := range inc { 54 ret = append(ret, i) 55 } 56 return ret, nil 57 } 58 59 // glob matches all regular files in a directory based on a glob pattern 60 func (g *Globber) glob(dir, glob string) ([]string, error) { 61 p := pattern{dir: dir, glob: glob} 62 if res, ok := g.cache[p]; ok { 63 return res, nil 64 } 65 66 entries, err := os.ReadDir(dir) 67 if err != nil { 68 return nil, err 69 } 70 71 var files []string 72 for _, e := range entries { 73 // Ignore dirs, symlinks etc. 74 if !e.Type().IsRegular() { 75 continue 76 } 77 78 // We're globbing for Go files to determine their imports. We can skip any other files. 79 if filepath.Ext(e.Name()) != ".go" { 80 continue 81 } 82 83 match, err := filepath.Match(glob, e.Name()) 84 if err != nil { 85 return nil, err 86 } 87 88 if match { 89 files = append(files, e.Name()) 90 } 91 } 92 93 g.cache[p] = files 94 return files, nil 95 }