Expand description
Whether a worktree is clean enough to copy from or to remove without asking Git, proven in process.
What:
Whether a worktree is clean enough to be copied from, or removed without asking Git: no operation in progress, an
index equal to the tree of HEAD, every tracked file unchanged by its recorded size, times and inode, and no
untracked file that Git does not ignore.
Why:
A snapshot or a clone carries the bytes of the source’s files, so any change the source has not committed would
reach the new worktree, and a removal by the subvolume ioctl cannot be undone. The tracked-file checks read the
index in process (no Git process) with the same comparison Git’s fast path makes, and refuse every shape they cannot
prove: a split or sparse index, a skip-worktree or assume-valid entry, a submodule, an entry as new as the index
file (Git re-hashes those, so their stat fields prove nothing). The one question the index cannot answer, whether
an untracked file is ignored, goes to one git ls-files run. Every refusal returns its reason in words for the log.
In TS you’d write (pseudocode):
const clean = await checkClean({ root, gitDir, commonDir }); // { headCommit, headTree } or throws a reasonStructs§
- Clean
Refusal - What: Why a worktree could not be proven clean: the kind and the reason in words. Why: The words are for logs and for people; the kind is for code.
- Clean
Source - What:
What a clean worktree’s
HEADnames. Why: The two-tree update that follows a snapshot starts from this tree, so a caller needs not read it again. - Content
Target - What the content decision needs besides the entries: the worktree, its Git directories, the environment and the format.
- Dirty
Source - What:
What
HEADnames for a worktree that is not clean, and why it is not, once it is known that the only trouble is ordinary changes. Why: The snapshot rung copies such a worktree and restores the copy to itsHEAD; the copy’s own index is installed, so the index bytes here are only as read: they name the tracked paths and prove nothing about the files. - Stat
Cursor - What:
A walk below a held directory that keeps the last directory it opened.
Why:
The paths of an index come in order, so most of them share their parent with the one before; one
openat2chain per directory instead of per file is what the walk costs, and each file is still reached through handles that follow no link. - Stat
Entry - What:
One tracked file of an index with the stat fields the index recorded for it.
Why:
parse_indexleaves the stat fields out, and the comparison with the file on disk needs them.
Enums§
- Clean
Refusal Kind - What: Which kind of state kept a worktree from being proven clean. Why: Callers decide by kind, never by the words of the reason: the snapshot rung restores a worktree whose only trouble is an ordinary change, and refuses every state a restore cannot be proven to undo; the sentence for the person is chosen by kind.
- Stat
Verdict - What: What the stat data of an index entry says about a file. Why: A file the data cannot vouch for (a racily clean entry, a stale stat) is not the same as a file that certainly changed: Git settles the first by content, so a caller that can compare content takes the two apart.
Functions§
- check_
clean - Cleanliness controls stay out of the release executable.
What:
Check that the worktree at
root, whose Git directory isgit_dirand whose shared directory iscommon_dir, is clean; return what itsHEADnames, or the reason it cannot be proven clean. Why: The caller turns a refusal into a quiet fall to the next rung (or to Git’s own removal) and logs the reason. - check_
clean_ tracked - What:
The checks of
check_cleanthat read no untracked file: no operation in progress, an index equal to the tree ofHEAD, and every tracked file with the size, times and inode its index entry recorded. Why: A caller that copies the whole worktree, untracked files included (the conversion of a worktree into a subvolume), needs a quiet and unmodified tracked state but has no reason to refuse for an untracked file, and needs no Git process. - check_
clean_ tracked_ by_ content - What:
check_clean_trackedthat settles an entry the stat data cannot vouch for by comparing the file with the committed blob in process, under the configuration and attribute locations ofenvironment. Why: The conversion copies the whole worktree and rewrites the index afterwards, and an entry it could not prove keeps its old stat data, so Git hashes it at the first status; the snapshot and clone rungs install the index they proved and use the stat-only check. - dirty_
source - What:
For a worktree
check_cleanrefused with the ordinary changewhy, whatHEADnames, or the refusal that a restore cannot undo when the index holds one anywhere. Why: The first refusal hides the rest: a staged edit can come before a submodule or a skip-worktree entry, and only a look at every entry tells a change a reset undoes from a state it does not. - head_
commit - What:
The commit
HEADresolves to, read from the plain ref files. Why: An unusual ref storage answers “unknown”, which declines the shortcut rather than guessing. - metadata_
differs_ from_ entry - What:
The reason a file whose metadata is
metadatadiffers from its index entry, or nothing when the two agree. Why: Callers that rely on the stat data alone (the snapshot and clone rungs) treat a file the data cannot vouch for like a file that changed. - metadata_
verdict - What:
What the stat data of the entry says about a file whose metadata is
metadata. Why: The comparison takes the metadata of an inode already in hand, so a caller that holds a descriptor judges the file it holds, not whatever the path names a moment later. Type and executable bit come before the time checks: they differ whatever the content is. - stat_
fields_ beneath - What:
The stat fields of the tracked file
pathbelow the held directoryroot, found through handles, or nothing. Why: The index of a snapshot takes the stat fields of the snapshot’s own files; reading them by a path with several components would follow a link substituted below the root. - stored_
stats - What:
The tracked files of the index paired with their recorded stat fields, or nothing when the layout is not plain.
Why:
The comparison with
lstatneeds the fieldsparse_indexleaves out. - tree_
differs_ from_ index - What:
The first reason a tracked file of
rootdiffers from its index entry, or nothing when every file agrees. Why: After a snapshot the same comparison runs against the snapshot’s own files, so a source that changed while the snapshot was taken is caught on the copy. The files are reached below a held root with no link followed, so a directory replaced by a link is not read through. - tree_
differs_ from_ index_ beneath - What:
The first reason a tracked file below the held directory
rootdiffers from its index entry, or nothing when every file agrees; each file is looked at below handles opened without following a link. Why: A snapshot is checked against the index it will carry; a path walk through a link inside the snapshot would compare a file outside it, so every directory on the way must be a real one on the snapshot’s device. - tree_
fields_ beneath - What:
Judge every tracked file below the held directory
rootagainst its index entry and return the stat fields of each, in entry order, in one walk. Why: The snapshot’s index takes the stat fields of the snapshot’s own files, and the snapshot is proven equal to the source’s index by the same stat data; the samestatxserves both, so the files are looked at once, and the fields are the ones the verdict was given on.