Skip to content

aferobilly

Go has two filesystem abstractions and they don't speak to each other. This bridges them in one direction: give it a go-billy filesystem, get an afero.Fs.

go get gitlab.com/phpboyscout/go/aferobilly
fs := aferobilly.New(worktree.Filesystem)

data, err := afero.ReadFile(fs, "go.mod") // afero code, billy filesystem

The usual reason you need this: go-git exposes a worktree as billy.Filesystem, while most application code, and most test helpers, are written against afero.Fs. Rather than copying the tree out and syncing it back, work against it live.

Why

  • A full afero.Fs, not a subset. That includes the optional symlink interfaces, with real afero.File handles for files and directories. Chown and Chtimes are deliberate no-ops. The awkward corners where billy and afero disagree are resolved deliberately; see billy vs afero semantics.
  • Optional locking that holds after the handle escapes. Every Fs and File operation that reaches the filesystem is serialised through a sync.Locker you supply. Hand it the mutex guarding whatever produced the filesystem and a handle stays safe even after the reference escapes.
  • The lock boundary can't be bypassed. The returned Fs and its files expose no accessor for the underlying billy object, so there is no way to forget to lock.
  • No VCS dependency. go-git is the common source of a billy filesystem, but this module never imports it and works with memfs, osfs, chroot, or your own. A dependency guard keeps it that way.

Where next

Reference

The API is three symbols (New, Option, WithLocker), but the behaviour underneath them is where the questions are.

The generated Go documentation is on pkg.go.dev.

What this does not do

It bridges one direction only, it is not a sandbox, Sync never flushes, and Chown and Chtimes do nothing on any backend. Each limit is deliberate and each has a reason. What this does not do sets them out.

Further reading

The blog carries a curated route through this subject: Building a command-line tool in Go collects everything written about it, ordered so you can start at the beginning rather than newest-first.

Ask phpbotscout

phpbotscout

He answers questions about the projects over on the Discord, citing the docs where they already cover it, and offering to raise an issue where they don't. Bring a bug, an idea, or a questionable engineering decision.

Join the Discord