Concurrency
How DubStack protects local state when commands overlap.
DubStack stores repository state under .git/dubstack/. State writes are
protected by .git/dubstack/state.lock so two overlapping dub commands do
not write tracking metadata at the same time.
Write Locks
When a command may mutate stack state, DubStack creates
.git/dubstack/state.lock with the current process ID, command name, and start
timestamp. The lock is created atomically, then removed after the command
finishes its state-mutating work. This can cover work before and after the
final state.json write, so a waiting command may pause for the full duration
of the active mutation.
If another live process already owns the lock, DubStack prints a waiting message and retries every 500ms for up to 30 seconds. If the lock owner exits before that timeout, the waiting command continues.
Stale Locks
If the lockfile points at a process that is no longer running, DubStack treats
the lock as stale, removes it, and continues. If the owner is still running and
the wait times out, DubStack exits with a recovery hint to run dub doctor and
remove .git/dubstack/state.lock manually only after confirming no dub
process is still writing state.
Read-Only Commands
Read-only commands do not acquire the write lock. Commands such as dub log,
dub status --json, and dub doctor --no-fetch can keep reading
state.json while another command is writing because state.json itself is
written with an atomic temp-file rename.