reorganize and update readme
diff --git a/README.md b/README.md index 022fcea..bcc4bb4 100644 --- a/README.md +++ b/README.md
@@ -4,71 +4,49 @@ [](https://travis-ci.org/spf13/afero) [](https://godoc.org/github.com/spf13/afero) -## Overview +# Overview -Package Afero provides types and methods for interacting with the filesystem, -as an abstraction layer. +Afero is an filesystem framework providing a simple, uniform and universal API +interacting with any filesystem, as an abstraction layer providing interfaces, +types and methods. Afero has an exceptionally clean interface and simple design +without needless constructors or initialization methods. -It provides a few implementations that are largely interoperable. One that -uses the operating system filesystem, one that uses memory to store files -(cross platform) and an interface that should be implemented if you want to -provide your own filesystem. +Afero is also a library providing a base set of interoperable backend +filesystems that make it easy to work with afero while retaining all the power +and benefit of the os and ioutil packages. -It is suitable for use in a any situation where you would consider using -the OS package as it provides an additional abstraction that makes it -easy to use a memory backed file system during testing. It also adds -support for the http filesystem for full interoperability. +Afero provides significant improvements over using the os package alone, most +notably the ability to create mock and testing filesystems without relying on the disk. -Afero has an exceptionally clean interface and simple design without needless -constructors or initialization methods. - -## The name - -Initially this project was called fs. Unfortunately as I used it, the -name proved confusing, there were too many fs’. In looking for -alternatives I looked up the word 'abstract' in a variety of different -languages. Afero is the Greek word for abstract and it seemed to be a -fitting name for the project. It also means ‘to do’ or ‘thing’ in -Esperanto which is also fitting. - -## Interface - -Afero simply takes the interfaces already defined throughout the standard -library and unifies them into a pair of interfaces that satisfy all -known uses. One interface for a file and one for a filesystem. - -## Filesystems - -Afero additionally comes with a few filesystems and file implementations -ready to use. - -### OsFs - -The first is simply a wrapper around the native OS calls. This makes it -very easy to use as all of the calls are the same as the existing OS -calls. It also makes it trivial to have your code use the OS during -operation and a mock filesystem during testing or as needed. - -### MemMapFs - -Afero also provides a fully atomic memory backed filesystem perfect for use in -mocking and to speed up unnecessary disk io when persistence isn’t -necessary. It is fully concurrent and will work within go routines -safely. - -#### InMemoryFile - -As part of MemMapFs, Afero also provides an atomic, fully concurrent memory -backed file implementation. This can be used in other memory backed file -systems with ease. Plans are to add a radix tree memory stored file -system using InMemoryFile. - -## Usage +It is suitable for use in a any situation where you would consider using the OS +package as it provides an additional abstraction that makes it easy to use a +memory backed file system during testing. It also adds support for the http +filesystem for full interoperability. -### Installing -Using Afero is easy. First use go get to install the latest version -of the library. +## Afero Features + +* A single consistent API for accessing a variety of filesystems +* Interoperation between a variety of file system types +* A set of interfaces to encourage and enforce interoperability between backends +* An atomic cross platform memory backed file system +* Support for compositional file systems by joining various different file systems (see httpFs) + + +# Using Afero + +Afero is easy to use and easier to adopt. + +A few different ways you could use Afero: + +* Use the interfaces alone to define you own file system. +* Wrap for the OS packages. +* Define different filesystems for different parts of your application. +* Use Afero for mock filesystems while testing + +## Step 1: Install Afero + +First use go get to install the latest version of the library. $ go get github.com/spf13/afero @@ -76,13 +54,8 @@ import "github.com/spf13/afero" -## Using Afero -There are a few different ways to use Afero. You could use the -interfaces alone to define you own file system. You could use it as a -wrapper for the OS packages. You could use it to define different -filesystems for different parts of your application. Here we will -demonstrate a basic usage. +## Step 2: Declare a backend First define a package variable and set it to a pointer to a filesystem. @@ -97,8 +70,21 @@ OsFs it will still use the same underlying filesystem but will reduce the ability to drop in other filesystems as desired. -Then throughout your functions and methods use the methods familiar -already from the OS package. +## Step 3: Use it like you would the OS package + +Throughout your application use any function and method like you normally +would. + +So if my application before had: + + os.Open('/tmp/foo') + +We would replace it with a call to `AppFs.Open('/tmp/foo')`. + +`AppFs` being the variable we defined above. + + +## List of all available functions File System Methods Available: @@ -131,28 +117,65 @@ Sync() : error Truncate(size int64) : error WriteString(s string) : ret int, err error - - -In our case we would call `AppFs.Open()` as an example because that is how we’ve defined to -access our filesystem. In some applications it may make sense to define a new package that simply exports the file system variable for easy access from anywhere. +## Using Afero for Testing -### Using a Mock Filesystem for Testing +There is a large benefit to using a mock filesystem for testing. It has a +completely blank state every time it is initialized and can be easily +reproducible regardless of OS. You could create files to your heart’s content +and the file access would be fast while also saving you from all the annoying +issues with deleting temporary files, Windows file locking, etc. The MemMapFs +backend is perfect for testing. -There is a large benefit to using a mock filesystem for testing. It has -a completely blank state every time it is initialized and can be easily -reproducible regardless of OS. It is also faster than disk which makes -the tests run faster. Lastly it doesn’t require any clean up after tests -are run. +* Much faster than performing I/O operations on disk +* Avoid security issues and permissions +* Far more control. 'rm -rf /' with confidence +* Test setup is far more easier to do +* No test cleanup needed One way to accomplish this is to define a variable as mentioned above. In your application this will be set to &afero.OsFs{} during testing you can set it to &afero.MemMapFs{}. -### Using with Http +It wouldn't be uncommon to have each test initialize a blank slate memory +backend. To do this I would define my `appFS = &afero.OsFs{}` somewhere +appropriate in my application code. This approach ensures that Tests are order +independent, with no test relying on the state left by an earlier test. + +Then in my tests I would initialize a new MemMapFs for each test: + + func TestExist(t *testing.T) { + appFS = &afero.MemMapFs{} + // create test files and directories + appFS.MkdirAll("src/a", 0755)) + appFS.WriteFile("src/a/b", []byte("file b"), 0644) + appFS.WriteFile("src/c", []byte("file c"), 0644) + testExistence("src/c", true, t) + } + + func testExistence(name string, e bool, t *testing.T) { + _, err := appFS.Stat(name) + if os.IsNotExist(err) { + if e { + t.Errorf("file \"%s\" does not exist.\n", name) + } + } else if err != nil { + panic(err) + } else { + if !e { + t.Errorf("file \"%s\" exists.\n", name) + } + } + } + + +## Using Afero with Http + +Afero provides an http compatible backend which can wrap any of the existing +backends. The Http package requires a slightly specific version of Open which returns an http.File type. @@ -164,8 +187,54 @@ fileserver := http.FileServer(httpFs.Dir(<PATH>))) http.Handle("/", fileserver) +# Available Backends + +## OsFs + +The first is simply a wrapper around the native OS calls. This makes it +very easy to use as all of the calls are the same as the existing OS +calls. It also makes it trivial to have your code use the OS during +operation and a mock filesystem during testing or as needed. + +## MemMapFs + +Afero also provides a fully atomic memory backed filesystem perfect for use in +mocking and to speed up unnecessary disk io when persistence isn’t +necessary. It is fully concurrent and will work within go routines +safely. + +### InMemoryFile + +As part of MemMapFs, Afero also provides an atomic, fully concurrent memory +backed file implementation. This can be used in other memory backed file +systems with ease. Plans are to add a radix tree memory stored file +system using InMemoryFile. + +## Desired/possible backends + +The following is a short list of possible backends we hope someone will +implement: + +* SSH/SCP +* ZIP +* TAR +* S3 +* Mem buffering to disk/network +* BasePath (where all paths are relative to a fixed basepath) + +# About the project + +## The name + +Initially this project was called fs. Unfortunately as I used it, the +name proved confusing, there were too many fs’. In looking for +alternatives I looked up the word 'abstract' in a variety of different +languages. Afero is the Greek word for abstract and it seemed to be a +fitting name for the project. It also means ‘to do’ or ‘thing’ in +Esperanto which is also fitting. ## Release Notes + * **0.9.0** 2015.11.05 * New Walk function similar to filepath.Walk * MemMapFs.OpenFile handles O_CREATE, O_APPEND, O_TRUNC @@ -198,4 +267,5 @@ ## License -Afero is released under the Apache 2.0 license. See [LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt) +Afero is released under the Apache 2.0 license. See +[LICENSE.txt](https://github.com/spf13/afero/blob/master/LICENSE.txt)