Documentation
¶
Overview ¶
Package localstore centralizes the one thing every small on-disk store in Kram (credentials, tool settings, onboarding, custom providers, config, permissions) needs and several of them got wrong: writing a file such that a reader — or a crash mid-write — never observes a half-written or truncated file.
Before this, config and permissions wrote atomically (temp file + rename) while credentials, toolsettings, onboarding and customprovider used a raw os.WriteFile that truncates the target in place. So the file whose corruption hurts most — credentials.json, holding API keys and OAuth tokens — was among the least protected. AtomicWrite makes the safe path the only path, by construction rather than by each store remembering to reimplement it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AtomicWrite ¶
AtomicWrite writes data to path so a reader never sees a partial file: it writes a sibling temp file, fsyncs it, then renames it into place (an atomic operation on POSIX). Parent directories are created as needed.
The fsync before rename matters for power loss specifically: a plain write-then-rename protects against a reader (or a process crash) observing a half-written file, but without the fsync the rename can become visible before the data blocks reach disk, so a power cut can leave a file that exists but is empty or truncated. fsync forces the bytes down first, so the rename only ever exposes fully-written data.
On Windows os.Rename fails if the destination already exists, so the existing file is removed first — leaving a brief window where neither the old nor the new file exists. That's still strictly better than a reader observing a half-written file: a missing file is the normal first-run state every store here already handles, whereas a truncated one is a parse error that can brick the store.
Types ¶
This section is empty.