init commit
This commit is contained in:
208
vendor/github.com/karrick/godirwalk/README.md
generated
vendored
Normal file
208
vendor/github.com/karrick/godirwalk/README.md
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
# godirwalk
|
||||
|
||||
`godirwalk` is a library for traversing a directory tree on a file
|
||||
system.
|
||||
|
||||
In short, why do I use this library?
|
||||
|
||||
1. It's faster than `filepath.Walk`.
|
||||
1. It's more correct on Windows than `filepath.Walk`.
|
||||
1. It's more easy to use than `filepath.Walk`.
|
||||
1. It's more flexible than `filepath.Walk`.
|
||||
|
||||
## Usage Example
|
||||
|
||||
Additional examples are provided in the `examples/` subdirectory.
|
||||
|
||||
This library will normalize the provided top level directory name
|
||||
based on the os-specific path separator by calling `filepath.Clean` on
|
||||
its first argument. However it always provides the pathname created by
|
||||
using the correct os-specific path separator when invoking the
|
||||
provided callback function.
|
||||
|
||||
```Go
|
||||
dirname := "some/directory/root"
|
||||
err := godirwalk.Walk(dirname, &godirwalk.Options{
|
||||
Callback: func(osPathname string, de *godirwalk.Dirent) error {
|
||||
fmt.Printf("%s %s\n", de.ModeType(), osPathname)
|
||||
return nil
|
||||
},
|
||||
Unsorted: true, // (optional) set true for faster yet non-deterministic enumeration (see godoc)
|
||||
})
|
||||
```
|
||||
|
||||
This library not only provides functions for traversing a file system
|
||||
directory tree, but also for obtaining a list of immediate descendants
|
||||
of a particular directory, typically much more quickly than using
|
||||
`os.ReadDir` or `os.ReadDirnames`.
|
||||
|
||||
Documentation is available via
|
||||
[](https://godoc.org/github.com/karrick/godirwalk).
|
||||
|
||||
## Description
|
||||
|
||||
Here's why I use `godirwalk` in preference to `filepath.Walk`,
|
||||
`os.ReadDir`, and `os.ReadDirnames`.
|
||||
|
||||
### It's faster than `filepath.Walk`
|
||||
|
||||
When compared against `filepath.Walk` in benchmarks, it has been
|
||||
observed to run between five and ten times the speed on darwin, at
|
||||
speeds comparable to the that of the unix `find` utility; about twice
|
||||
the speed on linux; and about four times the speed on Windows.
|
||||
|
||||
How does it obtain this performance boost? It does less work to give
|
||||
you nearly the same output. This library calls the same `syscall`
|
||||
functions to do the work, but it makes fewer calls, does not throw
|
||||
away information that it might need, and creates less memory churn
|
||||
along the way by reusing the same scratch buffer rather than
|
||||
reallocating a new buffer every time it reads data from the operating
|
||||
system.
|
||||
|
||||
While traversing a file system directory tree, `filepath.Walk` obtains
|
||||
the list of immediate descendants of a directory, and throws away the
|
||||
file system node type information provided by the operating system
|
||||
that comes with the node's name. Then, immediately prior to invoking
|
||||
the callback function, `filepath.Walk` invokes `os.Stat` for each
|
||||
node, and passes the returned `os.FileInfo` information to the
|
||||
callback.
|
||||
|
||||
While the `os.FileInfo` information provided by `os.Stat` is extremely
|
||||
helpful--and even includes the `os.FileMode` data--providing it
|
||||
requires an additional system call for each node.
|
||||
|
||||
Because most callbacks only care about what the node type is, this
|
||||
library does not throw the type information away, but rather provides
|
||||
that information to the callback function in the form of a
|
||||
`os.FileMode` value. Note that the provided `os.FileMode` value that
|
||||
this library provides only has the node type information, and does not
|
||||
have the permission bits, sticky bits, or other information from the
|
||||
file's mode. If the callback does care about a particular node's
|
||||
entire `os.FileInfo` data structure, the callback can easiy invoke
|
||||
`os.Stat` when needed, and only when needed.
|
||||
|
||||
#### Benchmarks
|
||||
|
||||
##### macOS
|
||||
|
||||
```Bash
|
||||
go test -bench=.
|
||||
goos: darwin
|
||||
goarch: amd64
|
||||
pkg: github.com/karrick/godirwalk
|
||||
BenchmarkFilepathWalk-8 1 3001274570 ns/op
|
||||
BenchmarkGoDirWalk-8 3 465573172 ns/op
|
||||
BenchmarkFlameGraphFilepathWalk-8 1 6957916936 ns/op
|
||||
BenchmarkFlameGraphGoDirWalk-8 1 4210582571 ns/op
|
||||
PASS
|
||||
ok github.com/karrick/godirwalk 16.822s
|
||||
```
|
||||
|
||||
##### Linux
|
||||
|
||||
```Bash
|
||||
go test -bench=.
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
pkg: github.com/karrick/godirwalk
|
||||
BenchmarkFilepathWalk-12 1 1609189170 ns/op
|
||||
BenchmarkGoDirWalk-12 5 211336628 ns/op
|
||||
BenchmarkFlameGraphFilepathWalk-12 1 3968119932 ns/op
|
||||
BenchmarkFlameGraphGoDirWalk-12 1 2139598998 ns/op
|
||||
PASS
|
||||
ok github.com/karrick/godirwalk 9.007s
|
||||
```
|
||||
|
||||
### It's more correct on Windows than `filepath.Walk`
|
||||
|
||||
I did not previously care about this either, but humor me. We all love
|
||||
how we can write once and run everywhere. It is essential for the
|
||||
language's adoption, growth, and success, that the software we create
|
||||
can run unmodified on all architectures and operating systems
|
||||
supported by Go.
|
||||
|
||||
When the traversed file system has a logical loop caused by symbolic
|
||||
links to directories, on unix `filepath.Walk` ignores symbolic links
|
||||
and traverses the entire directory tree without error. On Windows
|
||||
however, `filepath.Walk` will continue following directory symbolic
|
||||
links, even though it is not supposed to, eventually causing
|
||||
`filepath.Walk` to terminate early and return an error when the
|
||||
pathname gets too long from concatenating endless loops of symbolic
|
||||
links onto the pathname. This error comes from Windows, passes through
|
||||
`filepath.Walk`, and to the upstream client running `filepath.Walk`.
|
||||
|
||||
The takeaway is that behavior is different based on which platform
|
||||
`filepath.Walk` is running. While this is clearly not intentional,
|
||||
until it is fixed in the standard library, it presents a compatibility
|
||||
problem.
|
||||
|
||||
This library correctly identifies symbolic links that point to
|
||||
directories and will only follow them when `FollowSymbolicLinks` is
|
||||
set to true. Behavior on Windows and other operating systems is
|
||||
identical.
|
||||
|
||||
### It's more easy to use than `filepath.Walk`
|
||||
|
||||
Since this library does not invoke `os.Stat` on every file system node
|
||||
it encounters, there is no possible error event for the callback
|
||||
function to filter on. The third argument in the `filepath.WalkFunc`
|
||||
function signature to pass the error from `os.Stat` to the callback
|
||||
function is no longer necessary, and thus eliminated from signature of
|
||||
the callback function from this library.
|
||||
|
||||
Also, `filepath.Walk` invokes the callback function with a solidus
|
||||
delimited pathname regardless of the os-specific path separator. This
|
||||
library invokes the callback function with the os-specific pathname
|
||||
separator, obviating a call to `filepath.Clean` in the callback
|
||||
function for each node prior to actually using the provided pathname.
|
||||
|
||||
In other words, even on Windows, `filepath.Walk` will invoke the
|
||||
callback with `some/path/to/foo.txt`, requiring well written clients
|
||||
to perform pathname normalization for every file prior to working with
|
||||
the specified file. In truth, many clients developed on unix and not
|
||||
tested on Windows neglect this subtlety, and will result in software
|
||||
bugs when running on Windows. This library would invoke the callback
|
||||
function with `some\path\to\foo.txt` for the same file when running on
|
||||
Windows, eliminating the need to normalize the pathname by the client,
|
||||
and lessen the likelyhood that a client will work on unix but not on
|
||||
Windows.
|
||||
|
||||
### It's more flexible than `filepath.Walk`
|
||||
|
||||
#### Configurable Handling of Symbolic Links
|
||||
|
||||
The default behavior of this library is to ignore symbolic links to
|
||||
directories when walking a directory tree, just like `filepath.Walk`
|
||||
does. However, it does invoke the callback function with each node it
|
||||
finds, including symbolic links. If a particular use case exists to
|
||||
follow symbolic links when traversing a directory tree, this library
|
||||
can be invoked in manner to do so, by setting the
|
||||
`FollowSymbolicLinks` parameter to true.
|
||||
|
||||
#### Configurable Sorting of Directory Children
|
||||
|
||||
The default behavior of this library is to always sort the immediate
|
||||
descendants of a directory prior to visiting each node, just like
|
||||
`filepath.Walk` does. This is usually the desired behavior. However,
|
||||
this does come at a performance penalty to sort the names when a
|
||||
directory node has many entries. If a particular use case exists that
|
||||
does not require sorting the directory's immediate descendants prior
|
||||
to visiting its nodes, this library will skip the sorting step when
|
||||
the `Unsorted` parameter is set to true.
|
||||
|
||||
#### Configurable Post Children Callback
|
||||
|
||||
This library provides upstream code with the ability to specify a
|
||||
callback to be invoked for each directory after its children are
|
||||
processed. This has been used to recursively delete empty directories
|
||||
after traversing the file system in a more efficient manner. See the
|
||||
`examples/clean-empties` directory for an example of this usage.
|
||||
|
||||
#### Configurable Error Callback
|
||||
|
||||
This library provides upstream code with the ability to specify a
|
||||
callback to be invoked for errors that the operating system returns,
|
||||
allowing the upstream code to determine the next course of action to
|
||||
take, whether to halt walking the hierarchy, as it would do were no
|
||||
error callback provided, or skip the node that caused the error. See
|
||||
the `examples/walk-fast` directory for an example of this usage.
|
||||
Reference in New Issue
Block a user