diff options
Diffstat (limited to 'vendor/github.com/spf13/afero/util.go')
-rw-r--r-- | vendor/github.com/spf13/afero/util.go | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/vendor/github.com/spf13/afero/util.go b/vendor/github.com/spf13/afero/util.go new file mode 100644 index 0000000..4f253f4 --- /dev/null +++ b/vendor/github.com/spf13/afero/util.go | |||
@@ -0,0 +1,330 @@ | |||
1 | // Copyright ©2015 Steve Francia <spf@spf13.com> | ||
2 | // Portions Copyright ©2015 The Hugo Authors | ||
3 | // Portions Copyright 2016-present Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | ||
4 | // | ||
5 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | // you may not use this file except in compliance with the License. | ||
7 | // You may obtain a copy of the License at | ||
8 | // | ||
9 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | // | ||
11 | // Unless required by applicable law or agreed to in writing, software | ||
12 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | // See the License for the specific language governing permissions and | ||
15 | // limitations under the License. | ||
16 | |||
17 | package afero | ||
18 | |||
19 | import ( | ||
20 | "bytes" | ||
21 | "fmt" | ||
22 | "io" | ||
23 | "os" | ||
24 | "path/filepath" | ||
25 | "strings" | ||
26 | "unicode" | ||
27 | |||
28 | "golang.org/x/text/transform" | ||
29 | "golang.org/x/text/unicode/norm" | ||
30 | ) | ||
31 | |||
32 | // Filepath separator defined by os.Separator. | ||
33 | const FilePathSeparator = string(filepath.Separator) | ||
34 | |||
35 | // Takes a reader and a path and writes the content | ||
36 | func (a Afero) WriteReader(path string, r io.Reader) (err error) { | ||
37 | return WriteReader(a.Fs, path, r) | ||
38 | } | ||
39 | |||
40 | func WriteReader(fs Fs, path string, r io.Reader) (err error) { | ||
41 | dir, _ := filepath.Split(path) | ||
42 | ospath := filepath.FromSlash(dir) | ||
43 | |||
44 | if ospath != "" { | ||
45 | err = fs.MkdirAll(ospath, 0777) // rwx, rw, r | ||
46 | if err != nil { | ||
47 | if err != os.ErrExist { | ||
48 | return err | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | |||
53 | file, err := fs.Create(path) | ||
54 | if err != nil { | ||
55 | return | ||
56 | } | ||
57 | defer file.Close() | ||
58 | |||
59 | _, err = io.Copy(file, r) | ||
60 | return | ||
61 | } | ||
62 | |||
63 | // Same as WriteReader but checks to see if file/directory already exists. | ||
64 | func (a Afero) SafeWriteReader(path string, r io.Reader) (err error) { | ||
65 | return SafeWriteReader(a.Fs, path, r) | ||
66 | } | ||
67 | |||
68 | func SafeWriteReader(fs Fs, path string, r io.Reader) (err error) { | ||
69 | dir, _ := filepath.Split(path) | ||
70 | ospath := filepath.FromSlash(dir) | ||
71 | |||
72 | if ospath != "" { | ||
73 | err = fs.MkdirAll(ospath, 0777) // rwx, rw, r | ||
74 | if err != nil { | ||
75 | return | ||
76 | } | ||
77 | } | ||
78 | |||
79 | exists, err := Exists(fs, path) | ||
80 | if err != nil { | ||
81 | return | ||
82 | } | ||
83 | if exists { | ||
84 | return fmt.Errorf("%v already exists", path) | ||
85 | } | ||
86 | |||
87 | file, err := fs.Create(path) | ||
88 | if err != nil { | ||
89 | return | ||
90 | } | ||
91 | defer file.Close() | ||
92 | |||
93 | _, err = io.Copy(file, r) | ||
94 | return | ||
95 | } | ||
96 | |||
97 | func (a Afero) GetTempDir(subPath string) string { | ||
98 | return GetTempDir(a.Fs, subPath) | ||
99 | } | ||
100 | |||
101 | // GetTempDir returns the default temp directory with trailing slash | ||
102 | // if subPath is not empty then it will be created recursively with mode 777 rwx rwx rwx | ||
103 | func GetTempDir(fs Fs, subPath string) string { | ||
104 | addSlash := func(p string) string { | ||
105 | if FilePathSeparator != p[len(p)-1:] { | ||
106 | p = p + FilePathSeparator | ||
107 | } | ||
108 | return p | ||
109 | } | ||
110 | dir := addSlash(os.TempDir()) | ||
111 | |||
112 | if subPath != "" { | ||
113 | // preserve windows backslash :-( | ||
114 | if FilePathSeparator == "\\" { | ||
115 | subPath = strings.Replace(subPath, "\\", "____", -1) | ||
116 | } | ||
117 | dir = dir + UnicodeSanitize((subPath)) | ||
118 | if FilePathSeparator == "\\" { | ||
119 | dir = strings.Replace(dir, "____", "\\", -1) | ||
120 | } | ||
121 | |||
122 | if exists, _ := Exists(fs, dir); exists { | ||
123 | return addSlash(dir) | ||
124 | } | ||
125 | |||
126 | err := fs.MkdirAll(dir, 0777) | ||
127 | if err != nil { | ||
128 | panic(err) | ||
129 | } | ||
130 | dir = addSlash(dir) | ||
131 | } | ||
132 | return dir | ||
133 | } | ||
134 | |||
135 | // Rewrite string to remove non-standard path characters | ||
136 | func UnicodeSanitize(s string) string { | ||
137 | source := []rune(s) | ||
138 | target := make([]rune, 0, len(source)) | ||
139 | |||
140 | for _, r := range source { | ||
141 | if unicode.IsLetter(r) || | ||
142 | unicode.IsDigit(r) || | ||
143 | unicode.IsMark(r) || | ||
144 | r == '.' || | ||
145 | r == '/' || | ||
146 | r == '\\' || | ||
147 | r == '_' || | ||
148 | r == '-' || | ||
149 | r == '%' || | ||
150 | r == ' ' || | ||
151 | r == '#' { | ||
152 | target = append(target, r) | ||
153 | } | ||
154 | } | ||
155 | |||
156 | return string(target) | ||
157 | } | ||
158 | |||
159 | // Transform characters with accents into plain forms. | ||
160 | func NeuterAccents(s string) string { | ||
161 | t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC) | ||
162 | result, _, _ := transform.String(t, string(s)) | ||
163 | |||
164 | return result | ||
165 | } | ||
166 | |||
167 | func isMn(r rune) bool { | ||
168 | return unicode.Is(unicode.Mn, r) // Mn: nonspacing marks | ||
169 | } | ||
170 | |||
171 | func (a Afero) FileContainsBytes(filename string, subslice []byte) (bool, error) { | ||
172 | return FileContainsBytes(a.Fs, filename, subslice) | ||
173 | } | ||
174 | |||
175 | // Check if a file contains a specified byte slice. | ||
176 | func FileContainsBytes(fs Fs, filename string, subslice []byte) (bool, error) { | ||
177 | f, err := fs.Open(filename) | ||
178 | if err != nil { | ||
179 | return false, err | ||
180 | } | ||
181 | defer f.Close() | ||
182 | |||
183 | return readerContainsAny(f, subslice), nil | ||
184 | } | ||
185 | |||
186 | func (a Afero) FileContainsAnyBytes(filename string, subslices [][]byte) (bool, error) { | ||
187 | return FileContainsAnyBytes(a.Fs, filename, subslices) | ||
188 | } | ||
189 | |||
190 | // Check if a file contains any of the specified byte slices. | ||
191 | func FileContainsAnyBytes(fs Fs, filename string, subslices [][]byte) (bool, error) { | ||
192 | f, err := fs.Open(filename) | ||
193 | if err != nil { | ||
194 | return false, err | ||
195 | } | ||
196 | defer f.Close() | ||
197 | |||
198 | return readerContainsAny(f, subslices...), nil | ||
199 | } | ||
200 | |||
201 | // readerContains reports whether any of the subslices is within r. | ||
202 | func readerContainsAny(r io.Reader, subslices ...[]byte) bool { | ||
203 | |||
204 | if r == nil || len(subslices) == 0 { | ||
205 | return false | ||
206 | } | ||
207 | |||
208 | largestSlice := 0 | ||
209 | |||
210 | for _, sl := range subslices { | ||
211 | if len(sl) > largestSlice { | ||
212 | largestSlice = len(sl) | ||
213 | } | ||
214 | } | ||
215 | |||
216 | if largestSlice == 0 { | ||
217 | return false | ||
218 | } | ||
219 | |||
220 | bufflen := largestSlice * 4 | ||
221 | halflen := bufflen / 2 | ||
222 | buff := make([]byte, bufflen) | ||
223 | var err error | ||
224 | var n, i int | ||
225 | |||
226 | for { | ||
227 | i++ | ||
228 | if i == 1 { | ||
229 | n, err = io.ReadAtLeast(r, buff[:halflen], halflen) | ||
230 | } else { | ||
231 | if i != 2 { | ||
232 | // shift left to catch overlapping matches | ||
233 | copy(buff[:], buff[halflen:]) | ||
234 | } | ||
235 | n, err = io.ReadAtLeast(r, buff[halflen:], halflen) | ||
236 | } | ||
237 | |||
238 | if n > 0 { | ||
239 | for _, sl := range subslices { | ||
240 | if bytes.Contains(buff, sl) { | ||
241 | return true | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | |||
246 | if err != nil { | ||
247 | break | ||
248 | } | ||
249 | } | ||
250 | return false | ||
251 | } | ||
252 | |||
253 | func (a Afero) DirExists(path string) (bool, error) { | ||
254 | return DirExists(a.Fs, path) | ||
255 | } | ||
256 | |||
257 | // DirExists checks if a path exists and is a directory. | ||
258 | func DirExists(fs Fs, path string) (bool, error) { | ||
259 | fi, err := fs.Stat(path) | ||
260 | if err == nil && fi.IsDir() { | ||
261 | return true, nil | ||
262 | } | ||
263 | if os.IsNotExist(err) { | ||
264 | return false, nil | ||
265 | } | ||
266 | return false, err | ||
267 | } | ||
268 | |||
269 | func (a Afero) IsDir(path string) (bool, error) { | ||
270 | return IsDir(a.Fs, path) | ||
271 | } | ||
272 | |||
273 | // IsDir checks if a given path is a directory. | ||
274 | func IsDir(fs Fs, path string) (bool, error) { | ||
275 | fi, err := fs.Stat(path) | ||
276 | if err != nil { | ||
277 | return false, err | ||
278 | } | ||
279 | return fi.IsDir(), nil | ||
280 | } | ||
281 | |||
282 | func (a Afero) IsEmpty(path string) (bool, error) { | ||
283 | return IsEmpty(a.Fs, path) | ||
284 | } | ||
285 | |||
286 | // IsEmpty checks if a given file or directory is empty. | ||
287 | func IsEmpty(fs Fs, path string) (bool, error) { | ||
288 | if b, _ := Exists(fs, path); !b { | ||
289 | return false, fmt.Errorf("%q path does not exist", path) | ||
290 | } | ||
291 | fi, err := fs.Stat(path) | ||
292 | if err != nil { | ||
293 | return false, err | ||
294 | } | ||
295 | if fi.IsDir() { | ||
296 | f, err := fs.Open(path) | ||
297 | if err != nil { | ||
298 | return false, err | ||
299 | } | ||
300 | defer f.Close() | ||
301 | list, err := f.Readdir(-1) | ||
302 | return len(list) == 0, nil | ||
303 | } | ||
304 | return fi.Size() == 0, nil | ||
305 | } | ||
306 | |||
307 | func (a Afero) Exists(path string) (bool, error) { | ||
308 | return Exists(a.Fs, path) | ||
309 | } | ||
310 | |||
311 | // Check if a file or directory exists. | ||
312 | func Exists(fs Fs, path string) (bool, error) { | ||
313 | _, err := fs.Stat(path) | ||
314 | if err == nil { | ||
315 | return true, nil | ||
316 | } | ||
317 | if os.IsNotExist(err) { | ||
318 | return false, nil | ||
319 | } | ||
320 | return false, err | ||
321 | } | ||
322 | |||
323 | func FullBaseFsPath(basePathFs *BasePathFs, relativePath string) string { | ||
324 | combinedPath := filepath.Join(basePathFs.path, relativePath) | ||
325 | if parent, ok := basePathFs.source.(*BasePathFs); ok { | ||
326 | return FullBaseFsPath(parent, combinedPath) | ||
327 | } | ||
328 | |||
329 | return combinedPath | ||
330 | } | ||