Packages
A package is a directory with a talor.mod in it. talor install resolves the manifest's require lines, copies or fetches what the cache does not hold, verifies each tree's digest, and writes talor.lock.
talor install [<dir>]talor build performs the same resolution when it has to: it writes the lock of a tree that has none, and copies into the cache a package the lock names that the cache lacks. So the everyday path is talor build alone, and install is the resolution without a build. A require the lock does not name is refused by build, naming install, and a lock is never changed by a build. No command reaches the network yet.
What a require names
A require writes the dependency's name, the source it comes from, and what that source takes:
require util path libs/util
require greet file:// ../greet
require crypto git https://example.com/crypto.git v1.0.2
require parser registry 1.2.3| Source | What it takes | What install does with it |
|---|---|---|
path | a directory inside the package | nothing: the tree is read where it is, and it is in neither the lock nor the cache |
file:// | a path anywhere | copies the tree into the cache, which is a copy and not a fetch |
git | a repository, and optionally a revision | named in the manifest; the fetch is not written yet |
registry | a version | named in the manifest; the fetch is not written yet |
workspace | nothing | nothing: the root build's own require of the same name says where it comes from |
The two sources that need no network are the two that work today, and a git or registry line is refused where it stands, naming the source:
'crypto' comes from 'https://example.com/crypto.git', which needs the network; 'path' and 'file://' are the sources that need nothingA package is cached under the name and version its own talor.mod declares, so a tree whose manifest names another name than the require that reached it is refused rather than cached under either:
'../greet' declares the name 'greet', and 'sib' is the name it is required underA name is also how a use reaches it: require greet file:// ../greet is what makes use greet; resolve under that package's own tree.
The lock
talor.lock is what pins a build. It is written whole and in name order, so a run that changed nothing writes the same bytes:
lock 1
package greet 1.0.0 file://../greet sha256:528b5bba55b595517079e58ef1cf431fb9c7fba60013166a11f58145cd46ce29The first line is the format version and nothing else; a lock whose first line names a version this toolchain does not write is refused rather than read halfway, because the part of a newer format that happens to look like this one would build the wrong tree. Each line after it carries the digest of the tree as install left it, and build recomputes it: a cache that moved is a refusal and not a warning.
An entry already in the lock, already in the cache and whose digest still matches is not copied again, so a second talor install does no work.
What it refuses
- No manifest: a package is a directory with a
talor.mod, andbuildrefuses it the same way. - A
file://tree that is not there, naming the path. - A tree whose manifest names another name, naming both.
- A tree whose manifest names no version: the version a package is cached under is its own.
- A
requirewhose source needs the network, naming the source and saying thatpathandfile://are the sources that need nothing. - A
requirewritten twice, refused by the manifest reader asbuildrefuses it.
Vendoring
talor vendor [<dir>]vendor copies every package talor.lock names out of the cache into <dir>/vendor/<name>/<version>/, checking each copy against the lock's digest. A tree with a vendor/ directory builds on a machine with no cache.