Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sspur.lock

sspur.lock pins every package in the dependency graph, direct or not. sspur add and sspur deps update write it; you don’t edit it by hand, and you commit it.

$ cat sspur.lock
# sspur.lock: generated by sspur. Each dependency is pinned by the hash of its exports.

[[dep]]
name = "money"
version = "0.1.0"
source = "path+../money"
hash = "hfxpwwzddzoxhcf5jsfnbtwgrgeolp7j4b6ifpfkdtsfiygbx4aq"
deps = []
FieldMeaning
name, versionThe package’s name and version: the full name of a scoped package (acme/money), and acme/text:strings for the module strings of the published package acme/text
sourceWhere it was resolved from: path+DIR, git+URL, registry, or module for a module of a published package, which comes with that package
refThe rev the manifest asked for, or for a registry package its version requirement
revFor git and registry sources, the commit
hashThe hash of the package’s exports
git, snapshot, sha256Registry packages: the repository, the snapshot URL and the snapshot’s SHA-256, so a locked version can be downloaded again without the index. The snapshot is used first; the repository at rev only when the snapshot is missing, and it must give the same bytes
depsThe names of its own dependencies, which have their own [[dep]] entries

Pinned by what it exports

The hash is the Merkle root over the hashes of the package’s pub definitions, and each of those includes everything it calls. So the lock pins behavior, not a version string: a new release that doesn’t change any export locks to the same hash, and any change to an exported function’s body, signature, effects or contracts changes it.

A build reads only the lock and the package cache, ~/.cache/sspur/pkgs/<hash> (or $SSPUR_CACHE/pkgs). A missing package is fetched and its hash verified before use. The errors that come from the lock:

CodeWhenFix
E_DEP_HASHA cached package doesn’t hash to what the lock says, or a registry snapshot doesn’t have its SHA-256Delete that cache entry and run sspur deps fetch; for a snapshot, report it to the registry
E_DEP_STALEsspur.toml asks for a different source or rev than the lock pinssspur deps update NAME, which shows the diff first
E_DEP_CONFLICTTwo versions of one package in the graphsspur deps update NAME where the older one is pinned

Path dependencies inside the package’s own directory, such as models = { path = "models" }, are parts of the package rather than upstream code: a build reads their source, and when one of them changed it builds them again and rewrites the lock, so an edit to a module takes effect at the next sspur run. A dependency outside the directory (../lib, a git URL) stays pinned until sspur deps update.

sspur deps update prints a line per changed export, such as ~ lib.f effects: + log, ~ lib.g contracts: + pre n > 0, + lib.new or - lib.old, typechecks your package against the new version, and refuses to write the lock if it no longer checks, unless you pass --force.

When codebases sync (sspur sync push and pull), the lock and each locked package’s source travel with the commits, and the receiver checks them by hash.