OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / spf13 / afero / README.md
1 ![afero logo-sm](https://cloud.githubusercontent.com/assets/173412/11490338/d50e16dc-97a5-11e5-8b12-019a300d0fcb.png)
2
3 A FileSystem Abstraction System for Go
4
5 [![Build Status](https://travis-ci.org/spf13/afero.svg)](https://travis-ci.org/spf13/afero) [![Build status](https://ci.appveyor.com/api/projects/status/github/spf13/afero?branch=master&svg=true)](https://ci.appveyor.com/project/spf13/afero) [![GoDoc](https://godoc.org/github.com/spf13/afero?status.svg)](https://godoc.org/github.com/spf13/afero) [![Join the chat at https://gitter.im/spf13/afero](https://badges.gitter.im/Dev%20Chat.svg)](https://gitter.im/spf13/afero?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
7 # Overview
8
9 Afero is an filesystem framework providing a simple, uniform and universal API
10 interacting with any filesystem, as an abstraction layer providing interfaces,
11 types and methods. Afero has an exceptionally clean interface and simple design
12 without needless constructors or initialization methods.
13
14 Afero is also a library providing a base set of interoperable backend
15 filesystems that make it easy to work with afero while retaining all the power
16 and benefit of the os and ioutil packages.
17
18 Afero provides significant improvements over using the os package alone, most
19 notably the ability to create mock and testing filesystems without relying on the disk.
20
21 It is suitable for use in a any situation where you would consider using the OS
22 package as it provides an additional abstraction that makes it easy to use a
23 memory backed file system during testing. It also adds support for the http
24 filesystem for full interoperability.
25
26
27 ## Afero Features
28
29 * A single consistent API for accessing a variety of filesystems
30 * Interoperation between a variety of file system types
31 * A set of interfaces to encourage and enforce interoperability between backends
32 * An atomic cross platform memory backed file system
33 * Support for compositional (union) file systems by combining multiple file systems acting as one
34 * Specialized backends which modify existing filesystems (Read Only, Regexp filtered)
35 * A set of utility functions ported from io, ioutil & hugo to be afero aware
36
37
38 # Using Afero
39
40 Afero is easy to use and easier to adopt.
41
42 A few different ways you could use Afero:
43
44 * Use the interfaces alone to define you own file system.
45 * Wrap for the OS packages.
46 * Define different filesystems for different parts of your application.
47 * Use Afero for mock filesystems while testing
48
49 ## Step 1: Install Afero
50
51 First use go get to install the latest version of the library.
52
53     $ go get github.com/spf13/afero
54
55 Next include Afero in your application.
56 ```go
57 import "github.com/spf13/afero"
58 ```
59
60 ## Step 2: Declare a backend
61
62 First define a package variable and set it to a pointer to a filesystem.
63 ```go
64 var AppFs = afero.NewMemMapFs()
65
66 or
67
68 var AppFs = afero.NewOsFs()
69 ```
70 It is important to note that if you repeat the composite literal you
71 will be using a completely new and isolated filesystem. In the case of
72 OsFs it will still use the same underlying filesystem but will reduce
73 the ability to drop in other filesystems as desired.
74
75 ## Step 3: Use it like you would the OS package
76
77 Throughout your application use any function and method like you normally
78 would.
79
80 So if my application before had:
81 ```go
82 os.Open('/tmp/foo')
83 ```
84 We would replace it with:
85 ```go
86 AppFs.Open('/tmp/foo')
87 ```
88
89 `AppFs` being the variable we defined above.
90
91
92 ## List of all available functions
93
94 File System Methods Available:
95 ```go
96 Chmod(name string, mode os.FileMode) : error
97 Chtimes(name string, atime time.Time, mtime time.Time) : error
98 Create(name string) : File, error
99 Mkdir(name string, perm os.FileMode) : error
100 MkdirAll(path string, perm os.FileMode) : error
101 Name() : string
102 Open(name string) : File, error
103 OpenFile(name string, flag int, perm os.FileMode) : File, error
104 Remove(name string) : error
105 RemoveAll(path string) : error
106 Rename(oldname, newname string) : error
107 Stat(name string) : os.FileInfo, error
108 ```
109 File Interfaces and Methods Available:
110 ```go
111 io.Closer
112 io.Reader
113 io.ReaderAt
114 io.Seeker
115 io.Writer
116 io.WriterAt
117
118 Name() : string
119 Readdir(count int) : []os.FileInfo, error
120 Readdirnames(n int) : []string, error
121 Stat() : os.FileInfo, error
122 Sync() : error
123 Truncate(size int64) : error
124 WriteString(s string) : ret int, err error
125 ```
126 In some applications it may make sense to define a new package that
127 simply exports the file system variable for easy access from anywhere.
128
129 ## Using Afero's utility functions
130
131 Afero provides a set of functions to make it easier to use the underlying file systems.
132 These functions have been primarily ported from io & ioutil with some developed for Hugo.
133
134 The afero utilities support all afero compatible backends.
135
136 The list of utilities includes:
137
138 ```go
139 DirExists(path string) (bool, error)
140 Exists(path string) (bool, error)
141 FileContainsBytes(filename string, subslice []byte) (bool, error)
142 GetTempDir(subPath string) string
143 IsDir(path string) (bool, error)
144 IsEmpty(path string) (bool, error)
145 ReadDir(dirname string) ([]os.FileInfo, error)
146 ReadFile(filename string) ([]byte, error)
147 SafeWriteReader(path string, r io.Reader) (err error)
148 TempDir(dir, prefix string) (name string, err error)
149 TempFile(dir, prefix string) (f File, err error)
150 Walk(root string, walkFn filepath.WalkFunc) error
151 WriteFile(filename string, data []byte, perm os.FileMode) error
152 WriteReader(path string, r io.Reader) (err error)
153 ```
154 For a complete list see [Afero's GoDoc](https://godoc.org/github.com/spf13/afero)
155
156 They are available under two different approaches to use. You can either call
157 them directly where the first parameter of each function will be the file
158 system, or you can declare a new `Afero`, a custom type used to bind these
159 functions as methods to a given filesystem.
160
161 ### Calling utilities directly
162
163 ```go
164 fs := new(afero.MemMapFs)
165 f, err := afero.TempFile(fs,"", "ioutil-test")
166
167 ```
168
169 ### Calling via Afero
170
171 ```go
172 fs := afero.NewMemMapFs()
173 afs := &afero.Afero{Fs: fs}
174 f, err := afs.TempFile("", "ioutil-test")
175 ```
176
177 ## Using Afero for Testing
178
179 There is a large benefit to using a mock filesystem for testing. It has a
180 completely blank state every time it is initialized and can be easily
181 reproducible regardless of OS. You could create files to your heart’s content
182 and the file access would be fast while also saving you from all the annoying
183 issues with deleting temporary files, Windows file locking, etc. The MemMapFs
184 backend is perfect for testing.
185
186 * Much faster than performing I/O operations on disk
187 * Avoid security issues and permissions
188 * Far more control. 'rm -rf /' with confidence
189 * Test setup is far more easier to do
190 * No test cleanup needed
191
192 One way to accomplish this is to define a variable as mentioned above.
193 In your application this will be set to afero.NewOsFs() during testing you
194 can set it to afero.NewMemMapFs().
195
196 It wouldn't be uncommon to have each test initialize a blank slate memory
197 backend. To do this I would define my `appFS = afero.NewOsFs()` somewhere
198 appropriate in my application code. This approach ensures that Tests are order
199 independent, with no test relying on the state left by an earlier test.
200
201 Then in my tests I would initialize a new MemMapFs for each test:
202 ```go
203 func TestExist(t *testing.T) {
204         appFS := afero.NewMemMapFs()
205         // create test files and directories
206         appFS.MkdirAll("src/a", 0755)
207         afero.WriteFile(appFS, "src/a/b", []byte("file b"), 0644)
208         afero.WriteFile(appFS, "src/c", []byte("file c"), 0644)
209         name := "src/c"
210         _, err := appFS.Stat(name)
211         if os.IsNotExist(err) {
212                 t.Errorf("file \"%s\" does not exist.\n", name)
213         }
214 }
215 ```
216
217 # Available Backends
218
219 ## Operating System Native
220
221 ### OsFs
222
223 The first is simply a wrapper around the native OS calls. This makes it
224 very easy to use as all of the calls are the same as the existing OS
225 calls. It also makes it trivial to have your code use the OS during
226 operation and a mock filesystem during testing or as needed.
227
228 ```go
229 appfs := afero.NewOsFs()
230 appfs.MkdirAll("src/a", 0755))
231 ```
232
233 ## Memory Backed Storage
234
235 ### MemMapFs
236
237 Afero also provides a fully atomic memory backed filesystem perfect for use in
238 mocking and to speed up unnecessary disk io when persistence isn’t
239 necessary. It is fully concurrent and will work within go routines
240 safely.
241
242 ```go
243 mm := afero.NewMemMapFs()
244 mm.MkdirAll("src/a", 0755))
245 ```
246
247 #### InMemoryFile
248
249 As part of MemMapFs, Afero also provides an atomic, fully concurrent memory
250 backed file implementation. This can be used in other memory backed file
251 systems with ease. Plans are to add a radix tree memory stored file
252 system using InMemoryFile.
253
254 ## Network Interfaces
255
256 ### SftpFs
257
258 Afero has experimental support for secure file transfer protocol (sftp). Which can
259 be used to perform file operations over a encrypted channel.
260
261 ## Filtering Backends
262
263 ### BasePathFs
264
265 The BasePathFs restricts all operations to a given path within an Fs.
266 The given file name to the operations on this Fs will be prepended with
267 the base path before calling the source Fs.
268
269 ```go
270 bp := afero.NewBasePathFs(afero.NewOsFs(), "/base/path")
271 ```
272
273 ### ReadOnlyFs
274
275 A thin wrapper around the source Fs providing a read only view.
276
277 ```go
278 fs := afero.NewReadOnlyFs(afero.NewOsFs())
279 _, err := fs.Create("/file.txt")
280 // err = syscall.EPERM
281 ```
282
283 # RegexpFs
284
285 A filtered view on file names, any file NOT matching
286 the passed regexp will be treated as non-existing.
287 Files not matching the regexp provided will not be created.
288 Directories are not filtered.
289
290 ```go
291 fs := afero.NewRegexpFs(afero.NewMemMapFs(), regexp.MustCompile(`\.txt$`))
292 _, err := fs.Create("/file.html")
293 // err = syscall.ENOENT
294 ```
295
296 ### HttpFs
297
298 Afero provides an http compatible backend which can wrap any of the existing
299 backends.
300
301 The Http package requires a slightly specific version of Open which
302 returns an http.File type.
303
304 Afero provides an httpFs file system which satisfies this requirement.
305 Any Afero FileSystem can be used as an httpFs.
306
307 ```go
308 httpFs := afero.NewHttpFs(<ExistingFS>)
309 fileserver := http.FileServer(httpFs.Dir(<PATH>)))
310 http.Handle("/", fileserver)
311 ```
312
313 ## Composite Backends
314
315 Afero provides the ability have two filesystems (or more) act as a single
316 file system.
317
318 ### CacheOnReadFs
319
320 The CacheOnReadFs will lazily make copies of any accessed files from the base
321 layer into the overlay. Subsequent reads will be pulled from the overlay
322 directly permitting the request is within the cache duration of when it was
323 created in the overlay.
324
325 If the base filesystem is writeable, any changes to files will be
326 done first to the base, then to the overlay layer. Write calls to open file
327 handles like `Write()` or `Truncate()` to the overlay first.
328
329 To writing files to the overlay only, you can use the overlay Fs directly (not
330 via the union Fs).
331
332 Cache files in the layer for the given time.Duration, a cache duration of 0
333 means "forever" meaning the file will not be re-requested from the base ever.
334
335 A read-only base will make the overlay also read-only but still copy files
336 from the base to the overlay when they're not present (or outdated) in the
337 caching layer.
338
339 ```go
340 base := afero.NewOsFs()
341 layer := afero.NewMemMapFs()
342 ufs := afero.NewCacheOnReadFs(base, layer, 100 * time.Second)
343 ```
344
345 ### CopyOnWriteFs()
346
347 The CopyOnWriteFs is a read only base file system with a potentially
348 writeable layer on top.
349
350 Read operations will first look in the overlay and if not found there, will
351 serve the file from the base.
352
353 Changes to the file system will only be made in the overlay.
354
355 Any attempt to modify a file found only in the base will copy the file to the
356 overlay layer before modification (including opening a file with a writable
357 handle).
358
359 Removing and Renaming files present only in the base layer is not currently
360 permitted. If a file is present in the base layer and the overlay, only the
361 overlay will be removed/renamed.
362
363 ```go
364         base := afero.NewOsFs()
365         roBase := afero.NewReadOnlyFs(base)
366         ufs := afero.NewCopyOnWriteFs(roBase, afero.NewMemMapFs())
367
368         fh, _ = ufs.Create("/home/test/file2.txt")
369         fh.WriteString("This is a test")
370         fh.Close()
371 ```
372
373 In this example all write operations will only occur in memory (MemMapFs)
374 leaving the base filesystem (OsFs) untouched.
375
376
377 ## Desired/possible backends
378
379 The following is a short list of possible backends we hope someone will
380 implement:
381
382 * SSH
383 * ZIP
384 * TAR
385 * S3
386
387 # About the project
388
389 ## What's in the name
390
391 Afero comes from the latin roots Ad-Facere.
392
393 **"Ad"** is a prefix meaning "to".
394
395 **"Facere"** is a form of the root "faciō" making "make or do".
396
397 The literal meaning of afero is "to make" or "to do" which seems very fitting
398 for a library that allows one to make files and directories and do things with them.
399
400 The English word that shares the same roots as Afero is "affair". Affair shares
401 the same concept but as a noun it means "something that is made or done" or "an
402 object of a particular type".
403
404 It's also nice that unlike some of my other libraries (hugo, cobra, viper) it
405 Googles very well.
406
407 ## Release Notes
408
409 * **0.10.0** 2015.12.10
410   * Full compatibility with Windows
411   * Introduction of afero utilities
412   * Test suite rewritten to work cross platform
413   * Normalize paths for MemMapFs
414   * Adding Sync to the file interface
415   * **Breaking Change** Walk and ReadDir have changed parameter order
416   * Moving types used by MemMapFs to a subpackage
417   * General bugfixes and improvements
418 * **0.9.0** 2015.11.05
419   * New Walk function similar to filepath.Walk
420   * MemMapFs.OpenFile handles O_CREATE, O_APPEND, O_TRUNC
421   * MemMapFs.Remove now really deletes the file
422   * InMemoryFile.Readdir and Readdirnames work correctly
423   * InMemoryFile functions lock it for concurrent access
424   * Test suite improvements
425 * **0.8.0** 2014.10.28
426   * First public version
427   * Interfaces feel ready for people to build using
428   * Interfaces satisfy all known uses
429   * MemMapFs passes the majority of the OS test suite
430   * OsFs passes the majority of the OS test suite
431
432 ## Contributing
433
434 1. Fork it
435 2. Create your feature branch (`git checkout -b my-new-feature`)
436 3. Commit your changes (`git commit -am 'Add some feature'`)
437 4. Push to the branch (`git push origin my-new-feature`)
438 5. Create new Pull Request
439
440 ## Contributors
441
442 Names in no particular order:
443
444 * [spf13](https://github.com/spf13)
445 * [jaqx0r](https://github.com/jaqx0r)
446 * [mbertschler](https://github.com/mbertschler)
447 * [xor-gate](https://github.com/xor-gate)
448
449 ## License
450
451 Afero is released under the Apache 2.0 license. See
452 [LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt)