github.com/coveo/gotemplate@v2.7.7+incompatible/utils/io.go (about) 1 package utils 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 8 "github.com/coveo/gotemplate/collections" 9 "github.com/coveo/gotemplate/errors" 10 ) 11 12 var must = errors.Must 13 14 // FindFiles returns the list of the files matching the array of patterns 15 func FindFiles(folder string, recursive, followLinks bool, patterns ...string) ([]string, error) { 16 depth := 0 17 if recursive { 18 depth = 1 << 16 19 } 20 return FindFilesMaxDepth(folder, depth, followLinks, patterns...) 21 } 22 23 // FindFilesMaxDepth returns the list of the files matching the array of patterns 24 func FindFilesMaxDepth(folder string, maxDepth int, followLinks bool, patterns ...string) ([]string, error) { 25 visited := map[string]bool{} 26 var walker func(folder string) ([]string, error) 27 walker = func(folder string) ([]string, error) { 28 results := must(findFiles(folder, patterns...)).([]string) 29 folder, _ = filepath.Abs(folder) 30 if maxDepth == 0 { 31 return results, nil 32 } 33 34 filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { 35 if info == nil || path == folder { 36 return nil 37 } 38 if info.IsDir() { 39 visited[path] = true 40 depth := strings.Count(must(filepath.Rel(path, folder)).(string), "..") 41 if depth > maxDepth { 42 return filepath.SkipDir 43 } 44 files, err := findFiles(path, patterns...) 45 if err != nil { 46 return err 47 } 48 results = append(results, files...) 49 return nil 50 } 51 52 if info.Mode()&os.ModeSymlink != 0 && followLinks { 53 link, err := os.Readlink(path) 54 if err != nil { 55 return err 56 } 57 58 if !filepath.IsAbs(link) { 59 link = filepath.Join(filepath.Dir(path), link) 60 } 61 link, _ = filepath.Abs(link) 62 if !visited[link] { 63 // Check if we already visited that link to avoid recursive loop 64 linkFiles, err := walker(link) 65 if err != nil { 66 return err 67 } 68 results = append(results, linkFiles...) 69 } 70 } 71 return nil 72 }) 73 return results, nil 74 } 75 return walker(folder) 76 } 77 78 // FindFiles returns the list of files in the specified folder that match one of the supplied patterns 79 func findFiles(folder string, patterns ...string) ([]string, error) { 80 var matches []string 81 for _, pattern := range patterns { 82 files, err := filepath.Glob(filepath.Join(folder, pattern)) 83 if err != nil { 84 return nil, err 85 } 86 matches = append(matches, files...) 87 } 88 return matches, nil 89 } 90 91 // MustFindFiles returns the list of the files matching the array of patterns with panic on error 92 func MustFindFiles(folder string, recursive, followLinks bool, patterns ...string) []string { 93 return must(FindFiles(folder, recursive, followLinks, patterns...)).([]string) 94 } 95 96 // MustFindFilesMaxDepth returns the list of the files matching the array of patterns with panic on error 97 func MustFindFilesMaxDepth(folder string, maxDepth int, followLinks bool, patterns ...string) []string { 98 return must(FindFilesMaxDepth(folder, maxDepth, followLinks, patterns...)).([]string) 99 } 100 101 func globFunc(trimUnmatch bool, args ...interface{}) (result []string) { 102 for _, arg := range collections.ToStrings(args) { 103 if strings.ContainsAny(arg, "*?[]") { 104 if expanded, _ := filepath.Glob(arg); expanded != nil { 105 result = append(result, expanded...) 106 continue 107 } 108 if trimUnmatch { 109 continue 110 } 111 } 112 result = append(result, arg) 113 } 114 return 115 } 116 117 // GlobFunc returns an array of string representing the expansion of the supplied arguments using filepath.Glob function 118 func GlobFunc(args ...interface{}) []string { return globFunc(false, args...) } 119 120 // GlobFuncTrim returns an array of string representing the expansion of the supplied arguments using filepath.Glob function, it removes the unmatched arguments 121 func GlobFuncTrim(args ...interface{}) []string { return globFunc(true, args...) } 122 123 // Pwd returns the current folder 124 func Pwd() string { 125 return must(os.Getwd()).(string) 126 } 127 128 // Relative returns the relative path of file from folder 129 func Relative(folder, file string) string { 130 if !filepath.IsAbs(file) { 131 return file 132 } 133 return must(filepath.Rel(folder, file)).(string) 134 }