And implement `fs.ReadDirFile` for `BasePathFile`.
There are other `File` implementations that could also benefit from the above, but
this is a start.
The primary motivation behind this is to allow `fs.WalkDir` use the native
implementation whenever possible, as that new function was added in Go 1.16 with
speed as its main selling point.
This commit also adds a benchmark for `fs.WalkDir` that, when compared to the main branch:
```bash
name old time/op new time/op delta
WalkDir-10 369µs ± 1% 196µs ± 3% -46.89% (p=0.029 n=4+4)
name old alloc/op new alloc/op delta
WalkDir-10 85.3kB ± 0% 40.2kB ± 0% -52.87% (p=0.029 n=4+4)
name old allocs/op new allocs/op delta
WalkDir-10 826 ± 0% 584 ± 0% -29.30% (p=0.029 n=4+4)
```
Fixes#365
The interface has one method returning the `FileInfo` and a flag telling if `Lstat` was called or not.
```go
type Lstater interface {
LstatIfPossible(name string) (os.FileInfo, bool, error)
}
```
`Lstat` is currently only supported by the `OsFs`, but since that `Fs` can be used in others, they will also support it by proxy.
But not always, so hence this optional interface.
The interface is in this commit implemented for:
* BasePathFs
* OsFs
* CopyOnWriteFs
* ReadOnlyFs
Fixes#75
A common mistake in using the BasePathFs is to give it a real
OS absolute file path instead of a virtual one relative to the virtual base.
This commit adds some tests and returns an error on Windows in this case.
On Unix we have to train the users to do a better job.
See https://github.com/spf13/hugo/issues/1800
* add a BasePathFs implemented as FilterFs:
The BasePathFs restricts all operations to a given path within an Fs.
The given file name to the operations on this Fs will be prepended
with the base path before calling the base Fs.
Any file name (after filepath.Clean()) outside this base path will be
treated as non existing file.
* fix meaning of "facere" - "facio" means "I do", "facere" is the base
form