vfs
nimony/src/lib/vfs.nim
Virtual filesystem abstraction for nimony, hexer, nifc, and nifmake.
Built on the relay pattern from https://nim-lang.org/blog/relays.rst — every file operation is a module-level proc variable initialized to a default that calls straight through to the OS. Drivers reassign at startup; adapters capture the previous relay and wrap it (logging, sandboxing, in-memory cache, build cache, …).
Day-zero behavior is identical to direct syncio/memfiles/os calls. The point is the swappable seam, not yet the swapping.
template dumpVfsProfile(label: string)type FileWriteMode = enum AlwaysWrite = (0, "AlwaysWrite") OnlyIfChanged = (1, "OnlyIfChanged")
func dollar`.FileWriteMode(e: FileWriteMode): stringproc atomicTempPath(target: string): stringA sibling temp path for an atomic replacement of
targetproc vfsMoveInto(src: string; dst: string): boolMove
srcontodstas a single filesystem operation, replacing whatever was there. The point is thatdstis never opened for writing: a reader that mmap'd it, or a process currently EXECUTING it, keeps the old inode and is undisturbed, while everyone who opens the path afterwards sees the complete new file. There is no window in whichdstis half-written.This is what makes a build artefact safe to publish from several processes at once. Writing one in place is not: a concurrent
execveof a partially written executable fails with ETXTBSY ("Text file busy"), and so does writing one that somebody else is executing.proc vfsRemoveTree(dir: string)Remove
dirand everything below it. Best effort: it exists to clean up a scratch directory this process created for itself, and failing to do so must never fail a build.type VfsBlob = object data: pointer size: int64 mf: MemFile cookie: pointer cleanup: proc (b: var VfsBlob) {.nimcall.}
proc initBlob(data: pointer; size: int64; cookie: pointer; cleanup: proc (b: var VfsBlob) {.nimcall.}): VfsBlobConstructor for non-MemFile backends.
proc closeBlob(b: var VfsBlob)Release the backend resource (mmap unmap, LMDB read txn close, …). Safe to call multiple times — the second call is a no-op.
proc fromMemFile(mf: sink MemFile): VfsBlobWrap an already-opened MemFile in a blob whose cleanup closes it.
var openMmapRelay: proc (path: string): VfsBlob {.nimcall.}var readBytesRelay: proc (path: string): string {.nimcall.}var writeBytesRelay: proc (path: string, content: string) {.nimcall.}var existsRelay: proc (path: string): bool {.nimcall.}var mtimeRelay: proc (path: string): int64 {.nimcall.}var nowRelay: proc (): int64 {.nimcall.}var removeRelay: proc (path: string) {.nimcall.}proc vfsOpenMmap(path: string): VfsBlobproc vfsRead(path: string): stringproc vfsWrite(path: string; content: string)proc vfsExists(path: string): boolproc vfsMtime(path: string): int64proc vfsNow(): int64proc vfsRemove(path: string)