Documentation
¶
Overview ¶
Package configbilly adapts a billy.Filesystem to the config.FS interface, so code already holding a go-billy filesystem — the storage abstraction underneath go-git and a large family of Git tooling — can hand it to a config Store unchanged.
The config module defines its own six-method filesystem interface rather than depending on go-billy, so that importing it does not oblige a consumer to import a filesystem library chosen for them. This adapter is for consumers who have made that choice already — a tool built on go-billy, holding an on-disk tree (osfs), an in-memory one (memfs), a chrooted subtree, or its own implementation, that needs configuration read through it.
store, err := config.NewStore(ctx, config.WithFiles(configbilly.Wrap(bfs), "config.yaml"))
If all you need is the real filesystem, you do not need this package: config.OS is that, with no dependency. And a test wanting a throwaway directory wants config.Dir over t.TempDir(), which gives real file semantics including watching.
Paths are relative to the wrapped filesystem's root ¶
go-billy names are forward-slash and interpreted relative to the wrapped filesystem's root — an osfs.New("/etc/app") reads "config.yaml", not "/etc/app/config.yaml" — like config.Dir, unlike config.OS. Names pass through Wrap unchanged; the adapter does not normalise or validate them, and the Store composes paths itself. Do not pass an absolute operating-system path expecting config.OS semantics.
What this adapter claims, and what it declines ¶
Six methods map onto go-billy almost directly. The part worth not rediscovering is which optional interfaces the adapter may claim.
It does NOT satisfy config.RealPather. A billy.Filesystem cannot honestly report an operating-system path through its interface: Root() returns a logical root (memfs reports "/"), the concrete type is the same wrapper for a disk-backed and an in-memory filesystem alike, and capabilities describe file-I/O features, not whether a path is real. Claiming a real path it cannot prove would make every wrapped filesystem look watchable, so native notification would be selected and the absence of anything to watch discovered one path at a time. The adapter is therefore polled by config's core watcher, which is cheap for both osfs and memfs.
It DOES satisfy config.LinkReader unconditionally, because Readlink is mandatory on every billy.Filesystem (via the billy.Symlink interface). Where the target is not a link, Readlink returns an honest "not a link" error and the Store falls back to writing through the path as given.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Wrap ¶
func Wrap(bfs billy.Filesystem) config.FS
Wrap adapts a go-billy filesystem to config.FS.
The result reads and writes through the wrapped filesystem and is watched by polling — a billy.Filesystem cannot honestly report an operating-system path (see the package doc), so it does not satisfy config.RealPather. It always satisfies config.LinkReader, because Readlink is mandatory on every billy.Filesystem.
A billy filesystem mounted read-only is honoured: when billy.Capabilities reports no WriteCapability, the write methods return config.ErrReadOnlyFS up front, so a read-only filesystem gives a consumer a consistent errors.Is result. A genuinely writable filesystem that then fails still surfaces the underlying error unchanged.
Types ¶
This section is empty.