8 API Reference
dxtr edited this page 2026-10-16 22:45:31 +02:00

API Reference

Every symbol the stift package exports, and stift/cli's. Struct readers are listed with their struct.

Conditions

stift-error

The base of every error stift signals. Its message says what went wrong and what to do about it.

Readers: stift-error-message.

stift-warning

The base of every warning stift signals, when it does something otherwise than it was asked to, as building an executable uncompressed on a Lisp that cannot compress one. Its message says what and why.

Readers: stift-warning-message.

manifest-error

A stiftfile that cannot be read, or that breaks the rules of what a stiftfile holds. The report starts with FILE:LINE:COLUMN, as a compiler's does, so that editors can jump to it.

Readers: manifest-error-column, manifest-error-file, manifest-error-line.

url-error

A URL stift does not fetch from: one it cannot read, or one whose scheme would let the network change what it names.

Readers: url-error-url.

git-error

A git command that failed.

Readers: git-error-command, git-error-output, git-error-status.

ref-error

A branch, tag or commit that names nothing in a repository, or names more than one thing.

Readers: ref-error-ref, ref-error-url.

missing-commit

A commit stift cannot get: no branch or tag of its repository reaches it, or it is not in the cache and stift may not use the network.

Readers: missing-commit-commit, missing-commit-url.

no-manifest

No stiftfile in a directory or any directory above it.

Readers: no-manifest-directory.

diverged-requirements

Requirements on one project of which no commit required contains all the others, as when they lie on either side of a fork or of a rewritten branch. The main project settles it by requiring a commit that contains them all, such as a merge, or with a replacement (URL :commit ID).

Readers: diverged-requirements-edges, diverged-requirements-identity.

inconsistent-manifest

A main project's stiftfile that does not hold the build list its requirements make: a project of the build list requires a commit that the stiftfile's commit for that project does not contain, or a project the stiftfile does not list. It happens after an edit by hand, or a merge of two versions of the file. stift tidy brings the file up to date.

Readers: inconsistent-manifest-edges, inconsistent-manifest-file.

system-collision

Two projects of a build list that provide one system, of which ASDF would load one without a word. A :replace settles it when they are copies of one library, and an :exclude when one carries a copy of the other.

Readers: system-collision-identities, system-collision-system.

name-mismatch

A project whose stiftfile gives it another name than the host and path of the URL it was required by: a fork or a mirror. An entry in the :replace of the main project's stiftfile puts it in the place of the original.

Readers: name-mismatch-commit, name-mismatch-named, name-mismatch-url.

moved-tag

A tag that points to another commit than the one recorded beside it: someone moved it. stift get URL@TAG accepts the new commit.

Readers: moved-tag-now, moved-tag-recorded, moved-tag-tag, moved-tag-url.

rewritten-branch

A branch whose newest commit no longer contains the commit recorded beside it: a force-push rewrote it. stift get URL@BRANCH accepts the new commit.

Readers: rewritten-branch-branch, rewritten-branch-now, rewritten-branch-recorded, rewritten-branch-url.

workspace-error

A workspace stift cannot work in: a stiftwork that cannot be read, or breaks the rules of what it holds; a member that is no project, or two that are one; a project that is not a member; or members that stift work sync cannot pin. The report starts with the stiftwork, and the line and column the error is about, if any.

Readers: workspace-error-column, workspace-error-file, workspace-error-line.

vendor-mismatch

A project's vendor/projects that does not match its stiftfile, whose requirements or replacements changed since stift vendor wrote it, or names a copy that is missing, or cannot be read. stift vendor copies the build list again; when the record cannot be read, once vendor/ is deleted. The report starts with the record, and the line and column the error is about, if any.

Readers: vendor-mismatch-column, vendor-mismatch-file, vendor-mismatch-line.

Settings

settings

How stift works on this machine: CACHE-DIRECTORY, where it keeps repositories, checkouts, setup files and fasls; OFFLINE-P, whether it must not use the network; GIT, the git program it runs; VERBOSE-P, whether it prints each git command on ERROR-OUTPUT before running it; and WORKSPACE, which workspace it works in, a WORKSPACE-CHOICE. MAKE-SETTINGS makes one, taking what it is not given from the environment. Settings never change, and may be shared between threads.

Readers: settings-cache-directory, settings-git, settings-offline-p, settings-verbose-p, settings-workspace.

make-settings

(make-settings &key cache-directory (offline nil offline-p) git verbose workspace)

Return settings for stift. What is not given comes from the environment: CACHE-DIRECTORY from STIFT_CACHE, or else stift/ in the directory UIOP:XDG-CACHE-HOME names; OFFLINE from whether STIFT_OFFLINE is set to anything but 0; GIT from STIFT_GIT, or else "git"; WORKSPACE, :SEARCH to look for a stiftwork from the directory a command runs in upwards, :OFF for no workspace, or a stiftwork's pathname, from STIFT_WORKSPACE, which is off, the file, or unset for :SEARCH. VERBOSE, false unless given, makes stift print each git command before running it.

workspace-choice

Which workspace stift works in: :SEARCH for the stiftwork in the directory a command runs in or the nearest one above it, :OFF for none, or the pathname of a stiftwork.

Names

url-identity

(url-identity url)

Return the name stift knows the project at URL by: its host and path, such as fakehacker.cc/dxtr/cl-ffi, the same for every URL of one repository however it is fetched, or the path of a file:// URL. Signal URL-ERROR for a URL stift does not fetch from.

url-name

(url-name url)

Return the last part of the path of the project at URL, such as cl-ffi: the name stift gives its checkouts. Signal URL-ERROR for a URL stift does not fetch from.

split-url-and-ref

(split-url-and-ref string)

Return the URL and the ref in STRING, URL@REF as stift get takes it, or STRING and NIL when it names no ref. The ref follows the first @ after the URL's path begins, so that the @ of USER@HOST is part of the URL.

Manifests

manifest

A project's stiftfile, as read: FILE, where it was read from, a pathname, a string that says where, or NIL; PROJECT, the project's name, its repository's host and path, such as fakehacker.cc/dxtr/cl-ffi; REQUIREMENTS, the projects it requires, and REPLACEMENTS, both in the order the file gives them; and TEXT and FORM, the file's text and its property list as read, by which stift edits it. Manifests never change, and may be shared between threads.

Readers: manifest-file, manifest-project, manifest-replacements, manifest-requirements.

read-manifest

(read-manifest file)

Read the stiftfile FILE and return its manifest. Signal NO-MANIFEST if there is no such file, and MANIFEST-ERROR if it breaks the rules of what a stiftfile holds.

find-manifest

(find-manifest directory)

Return the pathname of the stiftfile of the project DIRECTORY is in: the one in DIRECTORY, or else in the nearest directory above it; or NIL when there is none.

requirement

A project that another requires: URL, where to fetch it; COMMIT, the full ID of the commit required, which that commit or any commit containing it satisfies; BRANCH or TAG, the ref COMMIT was read from, if any; TEST-P, true when only the requiring project's own tests need it; INDIRECT-P, true for the entries stift tidy writes, which the project needs only because a project it requires does; and EXCLUDE, directories of the project, relative to its root, whose .asd files stift ignores. Requirements never change, and may be shared between threads.

Readers: requirement-branch, requirement-commit, requirement-exclude, requirement-indirect-p, requirement-tag, requirement-test-p, requirement-url.

replacement

A main project's choice for a project of its build list, in place of what requirements choose. URL names the project replaced. WITH, another repository's URL, with COMMIT, fetches it from there, as from a fork or a mirror; COMMIT alone takes that commit of URL, whatever is required; LOCAL, a directory relative to the main project's, takes the project's files from there. BRANCH or TAG, beside COMMIT, is the ref COMMIT came from. Replacements count only in main projects. They never change, and may be shared between threads.

Readers: replacement-branch, replacement-commit, replacement-local, replacement-tag, replacement-url, replacement-with.

Projects

initialize-project

(initialize-project &key name (directory (uiop:getcwd)) (settings (make-settings)))

Write a stiftfile in DIRECTORY for the project NAME, which requires nothing yet, and return its pathname. NAME is the host and path of the project's repository, such as fakehacker.cc/dxtr/cl-ffi, or a URL of it, whose host and path stift takes; it is by default that of the git remote origin of the repository DIRECTORY is in. Signal STIFT-ERROR when DIRECTORY has a stiftfile already, and URL-ERROR for neither a name nor a URL stift fetches from.

add-requirement

(add-requirement url &key ref (test nil test-p) (directory (uiop:getcwd)) (settings (make-settings)))

Require the project at URL, at the commit REF names, in the stiftfile of the project DIRECTORY is in, then tidy the stiftfile as TIDY-MANIFEST does. Return the requirement the stiftfile holds, and the changes made, a list of CHANGE objects. REF is a branch or tag name, refs/heads/NAME or refs/tags/NAME, or a full or abbreviated commit ID; NIL, the default, names the repository's default branch. The stiftfile records the commit, and the branch or tag REF names, if it names one. When a project of the build list requires a later commit, tidying moves the requirement there. TEST true marks a requirement only the project's own tests need; when not given, a requirement the stiftfile has keeps its mark. A requirement of the same project takes the place of the old one, and stops being :indirect; the rest of the stiftfile stays as it was, but for what tidying changes. Nothing is written when an error is signalled.

remove-requirement

(remove-requirement url &key (directory (uiop:getcwd)) (settings (make-settings)))

Remove the requirement of the project at URL from the stiftfile of the project DIRECTORY is in, then tidy the stiftfile as TIDY-MANIFEST does. Return the requirement removed, and the changes made, a list of CHANGE objects. When the build list still needs the project, tidying adds it back as an :indirect entry, at the commit chosen for it. Signal STIFT-ERROR when the stiftfile does not require that project. Nothing is written when an error is signalled.

tidy-manifest

(tidy-manifest &key (directory (uiop:getcwd)) (settings (make-settings)))

Bring the stiftfile of the project DIRECTORY is in up to date with what its requirements require, and return the changes made, a list of CHANGE objects. stift reads the stiftfile of each project required, at each commit required of it, and chooses for each project the commit required of it that contains all the others, fetching the commits its cache lacks. Each requirement moves to the commit chosen for its project; each project of the build list that the stiftfile does not list gets an :indirect entry; and the :indirect entries of projects nothing needs any more go. Entries without :indirect are never added or removed. Signal DIVERGED-REQUIREMENTS when no commit required of a project contains all the others, and NAME-MISMATCH when a project's stiftfile names another project.

update-requirements

(update-requirements &key urls (directory (uiop:getcwd)) (settings (make-settings)))

Move the requirements and replacements of the stiftfile of the project DIRECTORY is in along their refs, or only those of the projects the URLS name, then tidy it as TIDY-MANIFEST does, and return the changes made, a list of CHANGE objects. One recorded beside a branch goes to the branch's newest commit. One recorded beside a tag goes to the highest tag of the same major version, among the tags that read as versions, such as v1.2.3 and 1.2.3, whose commit contains the commit recorded. One without a ref stays where it is: it was pinned on purpose. Signal MOVED-TAG when a tag points to another commit than the one recorded beside it, REWRITTEN-BRANCH when a branch no longer contains the commit recorded beside it, and STIFT-ERROR when a URL names a project the stiftfile neither requires nor replaces.

change

A change to a stiftfile: the requirement, or the replacement, of the project IDENTITY was OLD and is NEW. OLD is NIL for one added, and NEW NIL for one removed. Changes never change, and may be shared between threads.

Readers: change-identity, change-new, change-old.

Workspaces

workspace

A workspace's stiftwork, as read: FILE, where it was read from; MEMBERS, the directories of its members as it writes them, relative to its own directory or absolute; REPLACEMENTS, the replacements it holds, which win over its members'; and TEXT and FORM, its text and its property list as read, by which stift edits it. Workspaces never change, and may be shared between threads.

Readers: workspace-file, workspace-members, workspace-replacements.

read-workspace

(read-workspace file)

Read the stiftwork FILE and return its workspace. Signal WORKSPACE-ERROR if there is no such file, or it breaks the rules of what a stiftwork holds.

find-workspace

(find-workspace directory)

Return the pathname of the stiftwork in DIRECTORY, or else in the nearest directory above it; or NIL when there is none.

initialize-workspace

(initialize-workspace &key members (directory (uiop:getcwd)))

Write a stiftwork in DIRECTORY whose members are the projects in the directories MEMBERS, relative to DIRECTORY, and return its pathname. Signal STIFT-ERROR when DIRECTORY has a stiftwork already, or a member's directory does not exist, and WORKSPACE-ERROR when a member's directory holds no stiftfile, or two members are one project.

add-workspace-members

(add-workspace-members directories &key (directory (uiop:getcwd)) (settings (make-settings)))

Make the projects in DIRECTORIES, relative to DIRECTORY, members of the workspace a command run in DIRECTORY works in, and return the pathname of its stiftwork. A project that is a member already stays as it is. Signal STIFT-ERROR when a directory does not exist, and WORKSPACE-ERROR when there is no workspace, a directory holds no stiftfile, or two members would be one project.

remove-workspace-members

(remove-workspace-members directories &key (directory (uiop:getcwd)) (settings (make-settings)))

Remove the projects in DIRECTORIES, relative to DIRECTORY, from the members of the workspace a command run in DIRECTORY works in, and return the pathname of its stiftwork. A directory need not exist any more. Signal WORKSPACE-ERROR when there is no workspace, or a directory is not a member's.

sync-workspace

(sync-workspace &key (directory (uiop:getcwd)) (settings (make-settings)))

Move the requirements of the members of the workspace a command run in DIRECTORY works in on each other to the commits the members' checkouts have checked out, and tidy each stiftfile changed, from pins alone, as TIDY-MANIFEST does. Return the changes made, a list of (IDENTITY . CHANGES) pairs, one for each member whose stiftfile changed, those that others require first: IDENTITY names the member, and CHANGES lists CHANGE objects; and the identities of the members others require whose stiftfiles have changes that are not committed, which the pins on them cannot follow yet, in the same order. Committing and pushing are left to the user: commit and push those stiftfiles in that order, then sync again, until nothing is left. Signal WORKSPACE-ERROR, and change nothing, when a member a requirement would move to has its commit on no branch or tag of its remote, or a commit that does not contain the commit required now.

Build lists

entry

One project of a build list. IDENTITY is the name stift knows it by, such as fakehacker.cc/dxtr/cl-ffi; URL is where its files are fetched from, or NIL for a main project, whose files are in DIRECTORY; and NAME the last part of that URL's path, or of IDENTITY. COMMIT is the commit built, and BRANCH or TAG the ref it came from, if any; COMMIT is NIL for a project whose files are in a directory. TEST-P is true when only the main projects' tests need the project. SOURCE is :MAIN for the project being built, :WORKSPACE for a member of the workspace being built, :CACHE for a project checked out in stift's cache, :VENDOR for one copied into the main project's vendor/ by stift vendor, and :LOCAL for one that a replacement (URL :local DIR) takes from a directory; DIRECTORY holds its files. REPLACED-P is true when a :replace chose it. EXCLUDE lists the directories of the project, relative to its root, whose systems stift leaves out. Entries never change, and may be shared between threads.

Readers: entry-branch, entry-commit, entry-directory, entry-exclude, entry-identity, entry-name, entry-replaced-p, entry-source, entry-tag, entry-test-p, entry-url.

build-list

(build-list &key (directory (uiop:getcwd)) (settings (make-settings)))

Return the build list of the project DIRECTORY is in, or of the workspace it is in: an ENTRY for each main project, then one for each project their requirements reach, at the commit chosen for it. stift fetches the commits its cache lacks and checks them out, so that each entry's directory holds its files. Outside a workspace, the main project's stiftfile holds the build list, in the order it gives, and stift first checks that it is consistent: that the stiftfile of each commit it lists requires no project it does not list, and no commit that the commit it lists for that project does not contain. When stift vendor has copied the build list into the main project's vendor/, the entries are the copies, and stift needs neither the network nor its cache's repositories; it checks only that the copies were made for the stiftfile's requirements and replacements as they are. In a workspace, every member is a main project, whose checkout stands in for it, and the commits are chosen from all their requirements, as TIDY-MANIFEST chooses them. SETTINGS say which workspace, if any. Signal NO-MANIFEST when DIRECTORY is in neither a project nor a workspace, INCONSISTENT-MANIFEST when a stiftfile is not consistent, DIVERGED-REQUIREMENTS when the members' requirements diverge, SYSTEM-COLLISION when two projects of the build list provide one system, VENDOR-MISMATCH when the copies in vendor/ do not match the stiftfile, and WORKSPACE-ERROR when the workspace is not one stift can work in.

download

(download &key (directory (uiop:getcwd)) (settings (make-settings)))

Fetch into stift's cache, and check out, every commit of the build list of the project DIRECTORY is in, or of its workspace, that the cache lacks, as for working offline later or for a CI cache. Return the build list, as BUILD-LIST does. A project that builds from the copies in its vendor/ needs nothing fetched.

setup-file

(setup-file &key (directory (uiop:getcwd)) (settings (make-settings)))

Return the file that sets ASDF up for the build list of the project DIRECTORY is in, writing it first, and fetching what the build list lacks. Loading it into a Lisp, before anything else, makes ASDF find the build list's systems and no others, and put their fasls in a directory of the build list's own; it signals an error when another search, such as Quicklisp's, would find systems too, or when a system is loaded already from elsewhere. STIFT:EXEC-PROGRAM starts a Lisp with it.

The graph of requirements

edge

A requirement of the graph of requirements: the project REQUIRER, an identity, at the commit REQUIRER-COMMIT, requires what REQUIREMENT, a REQUIREMENT, says. REQUIRER-COMMIT is NIL when the requirer's files are in a directory, as the main project's are. Edges never change, and may be shared between threads.

Readers: edge-requirement, edge-requirer, edge-requirer-commit.

requirement-chains

(requirement-chains name &key (directory (uiop:getcwd)) (settings (make-settings)))

Return the chains of requirements that bring the project or the system NAME into the build list of the project DIRECTORY is in, or of its workspace; the identity of the project; the system, or NIL when NAME names a project; and whether the project is a main project, the project itself or a member of its workspace. NAME names a project by its identity, its URL or the last part of its path, or else a system that a project of the build list provides. Each chain is a list of EDGE objects, from a requirement of a main project's own, not :indirect, to one that requires the project, through the commits chosen and the main projects: the shortest for each such requirement that leads to it. There are none for a main project that no other requires, nor for a project that only an :indirect entry brings in, which stift tidy removes.

requirement-graph

(requirement-graph &key (directory (uiop:getcwd)) (settings (make-settings)))

Return every requirement of the graph of requirements of the project DIRECTORY is in, or of its workspace, as EDGE objects, in the order stift meets them: the main projects' own first, then those of each project required, at each commit required of it, as TIDY-MANIFEST reads them. A replaced project is read from its replacement.

Running programs and tests, and building

exec-program

(exec-program program arguments &key (directory (uiop:getcwd)) (settings (make-settings)))

Run PROGRAM with ARGUMENTS, a list of strings, and the build list of the project DIRECTORY is in, fetching what the build list lacks, and return the exit status PROGRAM ends with. PROGRAM shares this process's terminal. When PROGRAM starts SBCL or CCL, it starts without its init files, with the build list's setup file loaded before anything else (see SETUP-FILE). Any other program, such as make, gets the build list in the environment variables that ASDF reads, CL_SOURCE_REGISTRY and ASDF_OUTPUT_TRANSLATIONS, and the setup file's path in STIFT_SETUP. An interrupt from the terminal (Ctrl-C) goes to PROGRAM, and does not end the wait.

run-tests

(run-tests &key systems (lisps '("sbcl")) (directory (uiop:getcwd)) (settings (make-settings)) (stream *standard-output*))

Run the test suites of SYSTEMS, the names of ASDF systems, with the build list of the project DIRECTORY is in, or of its workspace, each in a new Lisp for each of LISPS, programs that start SBCL or CCL. SYSTEMS are by default the project's primary systems, those its .asd files are named after; at a workspace's root, outside its members, those of every member. Each suite runs as ASDF:TEST-SYSTEM runs it, and fails when an error escapes, as when its TEST-OP signals that its tests failed, or when the system does not load. At the end, print a line on STREAM for each suite, unless STREAM is NIL, and return their TEST-RESULT objects. An interrupt from the terminal (Ctrl-C) stops the suite running, and the rest are not run.

test-result

How one test suite went: SYSTEM, the system tested; LISP, the program that ran it; PASSED-P; SECONDS, how long the Lisp ran; and MESSAGE, what the error that failed the suite said, or NIL when it passed. Test results never change, and may be shared between threads.

Readers: test-result-lisp, test-result-message, test-result-passed-p, test-result-seconds, test-result-system.

build-system

(build-system &key system (lisp "sbcl") (directory (uiop:getcwd)) compress (settings (make-settings)))

Build SYSTEM, the name of an ASDF system, as ASDF:MAKE builds it, with the build list of the project DIRECTORY is in, or of its workspace, in a new Lisp that LISP starts, a program that starts SBCL or CCL. The build performs the system's build operation, which its defsystem names with :BUILD-OPERATION: PROGRAM-OP, for one, writes an executable to the file :BUILD-PATHNAME names, which starts in the function :ENTRY-POINT names. SYSTEM is by default the one system of the project's .asd files that names a build operation; at a workspace's root, outside its members, of the members' .asd files. The Lisp's output goes to this process's terminal. Return the files the build wrote, as pathnames, the name of the system built, and true if the image the build dumped is compressed. When COMPRESS is true, the image PROGRAM-OP or IMAGE-OP dumps is compressed on an SBCL built with core compression; otherwise the build writes it uncompressed, and signals a STIFT-WARNING that says why. Signal STIFT-ERROR when there is no such system, when it names no build operation, when not exactly one system names one and SYSTEM is not given, and when the build fails. An interrupt from the terminal (Ctrl-C) stops the build.

Checking what systems need

check-systems

(check-systems &key (lisp "sbcl") (directory (uiop:getcwd)) (settings (make-settings)))

Find what the stiftfiles of the project DIRECTORY is in, or of its workspace, cannot say: which systems its systems need. Start LISP, a program that starts SBCL or CCL, with the build list set up; load every .asd file of the main projects; and follow ASDF's depends-on and defsystem-depends-on from each system they define, test systems included, and from each system those need. Dependencies under (:feature ...) are followed whatever the platform, as ASDF keeps them as written, while #+ in an .asd file is settled as it is read, on this platform. Package-inferred systems are followed as ASDF infers them. Return a list of FINDING objects: systems no project provides; systems of a main project that use a project its stiftfile does not require, or requires only indirectly; requirements of a main project that none of its systems needs, on this platform; and .asd files or systems that could not be loaded. stift fetches the commits its cache lacks, as for a build, and changes nothing.

finding

Something stift check found, of a KIND: :MISSING, a SYSTEM no project of the build list provides, which the SYSTEMS depend on; FEATURES lists the feature expressions, as text, under which they do, when every one of them is conditional, and PROJECT names the project that provides SYSTEM's primary system, if one does; :UNREQUIRED, a SYSTEM of the main project MAIN that depends on SYSTEMS of PROJECT, which MAIN's stiftfile does not require; :INDIRECT, a SYSTEM of the main project MAIN that depends on SYSTEMS of PROJECT, which MAIN's stiftfile requires only as an :indirect entry, which stift tidy may drop; :UNREACHED, a requirement of the main project MAIN on PROJECT, none of whose systems any of MAIN's systems needs on this platform; :UNLOADABLE, a SYSTEM, or an .asd file, that could not be loaded, and the MESSAGE of the error. Findings never change, and may be shared between threads.

Readers: finding-features, finding-kind, finding-main, finding-message, finding-project, finding-system, finding-systems.

Vendoring

vendor-projects

(vendor-projects &key (directory (uiop:getcwd)) (settings (make-settings)))

Copy the build list of the project DIRECTORY is in into its vendor/: each project of stift's cache into vendor/HOST/PATH/, the files of its commit as git checks them out; the record of the copies into vendor/projects; and a .gitattributes and a .gitignore that keep the copies whole in a commit of the project, whatever core.autocrlf and the project's own .gitignore say. Copies of projects that left the build list go. A project a replacement (URL :local DIR) takes from a directory stays where it is. Return the build list, as BUILD-LIST returns it from the copies. The build list is the stiftfile's, from its pins alone, whatever workspace the project is in, as TIDY-MANIFEST works. stift fetches what its cache lacks. From then on, outside a workspace, stift builds from the copies, as BUILD-LIST says, until the stiftfile changes, after which this makes them again. Signal what BUILD-LIST signals for a stiftfile it cannot build from, VENDOR-MISMATCH when the record already in vendor/ cannot be read, and STIFT-ERROR when one copy would lie inside another, as those of example.org/a and example.org/a/b would. The copies belong to stift: VERIFY-PROJECTS finds any change to them.

verify-projects

(verify-projects &key remote (directory (uiop:getcwd)) (settings (make-settings)))

Check that the files of each project of the build list of the project DIRECTORY is in, or of its workspace, that come from a commit are that commit's files: the copies in vendor/ that stift vendor made, or else the checkouts in stift's cache. A copy is compared with the tree recorded for it, which stift finds in its cache, in the main project's own repository when the copies are committed as they were made, or over the network. With REMOTE true, also check over the network that each branch and tag recorded beside a commit still holds it. Return a DISCREPANCY for each project found wrong, or NIL when all are right. Signal what BUILD-LIST signals, and STIFT-ERROR when REMOTE is true and SETTINGS are offline.

discrepancy

What stift verify found about one project of the build list. KIND is :EDITED when the files of DIRECTORY, a copy in vendor/ or a checkout in stift's cache, are not the files of the commit they were made from, as FILES says: a list of (CHANGE PATH), CHANGE :ADDED, :DELETED or :MODIFIED and PATH the file's, relative to DIRECTORY with / between its parts; :UNCHECKED when stift could not find the commit's files to compare with; and :REF when a branch or tag recorded beside the commit no longer holds it. PROJECT is the project's identity, and MESSAGE says what is wrong and what to do, as a paragraph. Discrepancies never change, and may be shared between threads.

Readers: discrepancy-directory, discrepancy-files, discrepancy-kind, discrepancy-message, discrepancy-project.

The cache

repository-directory

(repository-directory url &key (settings (make-settings)))

Return the directory of the bare repository in stift's cache that holds the commits of the project at URL, as for git log. It may not exist yet.

clean-cache

(clean-cache &key fasls-only (settings (make-settings)))

Empty stift's cache: delete its repositories, checkouts, setup files and fasls, or with FASLS-ONLY true its fasls only. stift fetches and compiles again what it needs next. Return NIL.

The command line

run

(run arguments)

Run stift's command line ARGUMENTS, a list of strings, as the stift executable does, and return its exit status: 0 on success, the program's status for stift exec, 1 after an error, whose message goes to ERROR-OUTPUT, and 2 when ARGUMENTS make no sense to stift.

main

(main)

The entry point of the stift executable: run its command line, and exit with the status RUN returns. An interrupt from the terminal (Ctrl-C) ends stift with status 130, as a shell expects.