Similar to afero, but built around the extension interface pattern described in the io/fs draft design.
Also an anagram for "fish".
This was not intentional.
import (
"os"
"io/fs"
"strings"
"github.com/unstoppablemango/ihfs"
"github.com/unstoppablemango/ihfs/osfs"
"github.com/unstoppablemango/ihfs/try"
)
// Built around [io/fs]
var fs fs.FS = osfs.New()
// Regular type checks
if mkdir, ok := fs.(ihfs.MkdirFS); ok {
_ = mkdir.Mkdir("foo", os.ModeDir)
}
// The [try] package
_, err := try.WriteFile(fs, "foo/bar.txt", []byte("❤️"), os.ModePerm)
// Walking with [iter.Seq]
seq, err := ihfs.Catch(ihfs.Iter(fs, "."))
for path, dirEntry := range seq {
// .
// ./foo
// ./foo/bar.txt
}
// Filtering
filtered := ihfs.Where(fs, func(o ihfs.Operation) bool {
return strings.Contains(o.Subject(), "bar.txt")
})
for path, err := range ihfs.IterPaths(filtered, ".") {
// ./foo/bar.txt
}Wraps the OS filesystem. The Default variable provides a package-level instance.
import "github.com/unstoppablemango/ihfs/osfs"
fs := osfs.New()
f, err := fs.Open("path/to/file")A full-featured in-memory filesystem with read/write support. Useful for testing or ephemeral scratch space.
import "github.com/unstoppablemango/ihfs/memfs"
fs := memfs.New()
f, _ := fs.Create("hello.txt")
f.Write([]byte("hello"))
f.Close()A read-only filesystem backed by a tar archive. Entries are lazily buffered as files are accessed.
import "github.com/unstoppablemango/ihfs/tarfs"
tfs, err := tarfs.Open("archive.tar")
defer tfs.Close()
f, err := tfs.Open("dir/file.txt")You can also construct one from any io.Reader:
tfs := tarfs.FromReader("archive.tar", r)A copy-on-write filesystem layered over a base. All writes go to the layer; reads prefer the layer and fall back to the base. Modifying a file that exists only in the base copies it to the layer first.
import (
"github.com/unstoppablemango/ihfs/cowfs"
"github.com/unstoppablemango/ihfs/memfs"
"github.com/unstoppablemango/ihfs/osfs"
)
base := osfs.New()
layer := memfs.New()
fs := cowfs.New(base, layer)A cache-on-read filesystem. The first read of a file copies it from the base into the layer; subsequent reads come from the layer. A cache duration of 0 (the default) caches indefinitely.
import (
"time"
"github.com/unstoppablemango/ihfs/corfs"
"github.com/unstoppablemango/ihfs/memfs"
"github.com/unstoppablemango/ihfs/osfs"
)
base := osfs.New()
cache := memfs.New()
fs := corfs.New(base, cache)
// With a 5-minute expiry:
fs = corfs.New(base, cache, corfs.WithCacheTime(5*time.Minute))Hand-written test doubles with function-field overrides. Useful for simple unit tests that need a configurable fake filesystem without a full mock framework.
import (
"github.com/unstoppablemango/ihfs"
"github.com/unstoppablemango/ihfs/testfs"
)
fs := testfs.New(
testfs.WithOpen(func(name string) (ihfs.File, error) {
return testfs.NewFile(name), nil
}),
)Generated gomock mocks for all ihfs interfaces.
A read/write filesystem adapter for OCI container images and layers.
Package ghfs contains an implementation of io/fs for the GitHub API.
Much of the implementation is adapted from afero, specifically the corfs, cowfs, and union packages.