...
1
2 package locafero
3
4 import (
5 "errors"
6 "io/fs"
7 "path/filepath"
8 "strings"
9
10 "github.com/sourcegraph/conc/iter"
11 "github.com/spf13/afero"
12 )
13
14
15 type Finder struct {
16
17
18
19
20
21
22
23 Paths []string
24
25
26
27
28
29
30
31
32
33
34
35
36 Names []string
37
38
39
40
41 Type FileType
42 }
43
44
45 func (f Finder) Find(fsys afero.Fs) ([]string, error) {
46
47
48
49 type searchItem struct {
50 path string
51 name string
52 }
53
54 var searchItems []searchItem
55
56 for _, searchPath := range f.Paths {
57 searchPath := searchPath
58
59 for _, searchName := range f.Names {
60 searchName := searchName
61
62 searchItems = append(searchItems, searchItem{searchPath, searchName})
63
64
65
66
67
68
69
70
71
72 }
73 }
74
75
76
77
78
79
80 allResults, err := iter.MapErr(searchItems, func(item *searchItem) ([]string, error) {
81
82 if strings.ContainsAny(item.name, "*?[]\\^") {
83 return globWalkSearch(fsys, item.path, item.name, f.Type)
84 }
85
86 return statSearch(fsys, item.path, item.name, f.Type)
87 })
88 if err != nil {
89 return nil, err
90 }
91
92 var results []string
93
94 for _, r := range allResults {
95 results = append(results, r...)
96 }
97
98
99
100
101 return results, nil
102 }
103
104 func globWalkSearch(fsys afero.Fs, searchPath string, searchName string, searchType FileType) ([]string, error) {
105 var results []string
106
107 err := afero.Walk(fsys, searchPath, func(p string, fileInfo fs.FileInfo, err error) error {
108 if err != nil {
109 return err
110 }
111
112
113 if p == searchPath {
114 return nil
115 }
116
117 var result error
118
119
120
121 if fileInfo.IsDir() && filepath.Dir(p) == searchPath {
122 result = fs.SkipDir
123 }
124
125
126 if !searchType.matchFileInfo(fileInfo) {
127 return result
128 }
129
130 match, err := filepath.Match(searchName, fileInfo.Name())
131 if err != nil {
132 return err
133 }
134
135 if match {
136 results = append(results, p)
137 }
138
139 return result
140 })
141 if err != nil {
142 return results, err
143 }
144
145 return results, nil
146 }
147
148 func statSearch(fsys afero.Fs, searchPath string, searchName string, searchType FileType) ([]string, error) {
149 filePath := filepath.Join(searchPath, searchName)
150
151 fileInfo, err := fsys.Stat(filePath)
152 if errors.Is(err, fs.ErrNotExist) {
153 return nil, nil
154 }
155 if err != nil {
156 return nil, err
157 }
158
159
160 if !searchType.matchFileInfo(fileInfo) {
161 return nil, nil
162 }
163
164 return []string{filePath}, nil
165 }
166
View as plain text