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

Manifest and lockfile reference

A scadman project is a directory holding scadman.toml, which you write, and scadman.lock, which scadman writes. Commit both. Run scadman from that directory; it does not search parent directories.

scadman.toml

[project]
name = "enclosure"
openscad = ">=2021.01"        # optional

[dependencies]
BOSL2 = { git = "https://github.com/BelfrySCAD/BOSL2", branch = "master" }
Round-Anything = { git = "https://github.com/Irev-Dev/Round-Anything", rev = "061fef7c429628808e847696bb345a9b0ec6e279" }
dotSCAD = { git = "https://github.com/JustinSDK/dotSCAD", rev = "bb33edfd75cba0edbb7971606a077b9c69d0b7d2", root = "src", on_path = true }
mylib = { path = "../mylib" }

[project]

KeyRequiredMeaning
nameyesThe project’s name, shown by graph.
openscadnoMinimum OpenSCAD version, as "2021.01" or ">=2021.01". doctor and run warn when the installed version is older; nothing is blocked.

[dependencies]

Each key is the name the library is exposed under: BOSL2 makes include <BOSL2/…> resolve. Use the name the library’s own files use for themselves, since many libraries import their own files as <Name/…>. A name is a single path component: no / or \, and not . or ...

A git dependency:

KeyRequiredMeaning
gityesThe repository URL.
revone of these threeAn exact commit, as the full 40-character hash; an abbreviated one is refused. Never moves.
tagA tag. Locked to the commit it points at; scadman update re-reads it.
branchA branch. Locked to its tip at lock time; scadman update advances it.
rootnoSubdirectory to expose instead of the repository root. See library-roots.md.
on_pathnoAlso put the exposed directory on OPENSCADPATH. See library-roots.md.

Give exactly one of rev, tag and branch; an entry with none, or with more than one, is refused at lock time.

A path dependency takes path (a directory, relative to the project or absolute) and the same optional root and on_path. See path-dependencies.md.

An unknown table or key anywhere in your scadman.toml is an error, so a misspelled [dependencies] header or key cannot be silently ignored. A bare version string (BOSL2 = "^2.0") is reserved for a future registry and is refused at lock time.

One version per library

OpenSCAD has one flat namespace, so each library appears once in a project. lock stops with an error, and writes no lockfile, when:

  • one source is requested at two different commits;
  • two different sources are given the same name;
  • one source is given two names.

There is no override syntax yet; the fix is to make the declarations agree.

Two URLs are the same source when they match after a trailing / and a .git suffix are removed. Other spellings of one repository, such as different letter case or ssh against https, count as different sources (#98), so write a library’s URL the same way everywhere.

Dependencies of dependencies

If a git dependency ships its own scadman.toml, its dependencies are resolved too, under the same one-version rule. It may not declare path dependencies. Unknown keys in a dependency’s manifest are ignored, apart from those inside its dependency tables, so a library written for a newer scadman stays readable.

Almost no OpenSCAD library ships a manifest today. When a library imports another without declaring it, sync names the missing library and you add it to your own manifest.

scadman.lock

Generated by lock and update; do not edit it. One entry per resolved library:

version = 1

[[package]]
name = "BOSL2"
source = "https://github.com/BelfrySCAD/BOSL2"
rev = "afe82db884ee4409aa76ecfcfbbf54d446964af1"
hash = "…"
FieldMeaning
nameThe name the library is exposed under.
sourceThe git URL, or path: followed by the absolute directory of a path dependency.
revThe exact commit. For a path dependency, its content hash.
hashSHA-256 of the library’s files: the key of its copy in the store.
dependenciesNames of the libraries this one declares, if any.
root, on_pathCopied from the manifest when set.

version is the lockfile format. Every command refuses a lockfile whose version it does not know, and lock and update will not overwrite one: upgrade scadman, or delete the file to write a fresh one.

On a machine that does not have a library’s content yet, sync fetches rev from source and refuses to continue if the content does not hash to hash.

sync, run and env use the lockfile as it is. They create it if it is missing, and rewrite it when a path dependency’s content has changed. They stop and ask for scadman lock when the manifest and the lockfile disagree:

  • the manifest declares a library the lockfile lacks;
  • the lockfile holds a library the manifest no longer leads to, as after scadman remove;
  • a library’s source, rev, root or on_path no longer matches.

One edit is not detected: a changed tag or branch name on an unchanged URL. Running scadman lock after every manifest edit covers it.

Where scadman keeps things

PathWhatCommit it?
scadman.tomlThe manifest.yes
scadman.lockThe lockfile.yes
.scadman/env/The project environment: one symlink per library, rebuilt on every sync.no (init ignores it)
$XDG_DATA_HOME/scadman/store/, or ~/.local/share/scadman/store/The store: one immutable directory per content hash, shared by all projects.not in the project

A library’s stored copy is its working tree without .git. Symbolic links inside a library are not copied. File modes do not affect the hash.

Nothing removes store entries yet (#96). Deleting the store is safe: the next sync restores what the lockfile needs.