|
| 1 | +Status clean-proof sidecar |
| 2 | +========================== |
| 3 | + |
| 4 | +The status clean-proof sidecar is an optional proof for one empty clean |
| 5 | +scan. It can answer the exact empty `git status --porcelain=v2` query, |
| 6 | +or let a literal plain `git status` print its live long-format metadata |
| 7 | +without repeating the scan. It is never a source of repository state or |
| 8 | +cached human-readable output. A missing, stale, malformed, unsupported, |
| 9 | +or raced sidecar makes status read the index and scan the worktree |
| 10 | +normally. |
| 11 | + |
| 12 | +Location and scope |
| 13 | +------------------ |
| 14 | + |
| 15 | +The sidecar for an index at `<index>` is stored at `<index>.csts`. This |
| 16 | +keeps a proof for one index from being applied to an alternate index. |
| 17 | +Sidecars are currently limited to the main worktree, the builtin file |
| 18 | +system monitor, and an index and worktree root on local APFS file |
| 19 | +systems. |
| 20 | + |
| 21 | +Readers pass `O_NONBLOCK` and do not follow symbolic links when opening |
| 22 | +the sidecar, then accept only regular files no larger than 8192 bytes. |
| 23 | +An open or validation failure falls back to ordinary status. Writers use |
| 24 | +the normal lockfile protocol. |
| 25 | + |
| 26 | +Binary format |
| 27 | +------------- |
| 28 | + |
| 29 | +All integers are stored in network byte order. Hashes use the |
| 30 | +repository's object-format hash algorithm. Version 1 consists of: |
| 31 | + |
| 32 | +* Four-byte magic `CSTS`. |
| 33 | +
|
| 34 | +* A 32-bit version number (currently 1). |
| 35 | +
|
| 36 | +* 32-bit flags (currently zero). |
| 37 | +
|
| 38 | +* Fourteen 64-bit fields describing the source index: device, inode, |
| 39 | + mode, link count, uid, gid, size, mtime seconds and nanoseconds, ctime |
| 40 | + seconds and nanoseconds, birth time seconds and nanoseconds, and |
| 41 | + generation. |
| 42 | +
|
| 43 | +* The 32-bit index format version and 32-bit cache-entry count. |
| 44 | +
|
| 45 | +* The index checksum, which is all zero for an `index.skipHash` index, |
| 46 | + and the `HEAD` tree object ID. |
| 47 | +
|
| 48 | +* Hashes of status-relevant configuration and repository identity. The |
| 49 | + repository identity covers the worktree and Git directory paths, the |
| 50 | + worktree root identity, the local APFS identifiers of the held index |
| 51 | + and worktree root, external-attribute contents, and locale inputs. |
| 52 | +
|
| 53 | +* One object ID digesting the unique standard-exclude observations in |
| 54 | + first-observation order. Each observation contains the source path, |
| 55 | + symbolic-link lookup policy, presence, and contents. Transient file |
| 56 | + system identities used to make an observation coherent are not part |
| 57 | + of the digest. |
| 58 | +
|
| 59 | +* A 32-bit provider-token length followed by the token without a |
| 60 | + terminating NUL. Version 1 accepts only builtin-fsmonitor tokens. |
| 61 | +
|
| 62 | +* A hash over all preceding bytes in the sidecar. |
| 63 | +
|
| 64 | +Issuance |
| 65 | +-------- |
| 66 | + |
| 67 | +Only a literal, top-level `status --porcelain=v2` invocation, or a |
| 68 | +literal plain `status` after it restored external history, can issue a |
| 69 | +sidecar. Status first completes the tracked and untracked scan, |
| 70 | +semantic-conversion checks, and provider-token closure. The result must |
| 71 | +be empty and use the bulk scanner's complete standard-exclude result. |
| 72 | +The index must also contain persistent semantic history from an earlier |
| 73 | +scan, so the first scan cannot certify itself. For plain status, |
| 74 | +external checkpoint publication is attempted before the physical-index |
| 75 | +proof is installed. |
| 76 | + |
| 77 | +Status then uses the held attribute snapshot and the scanner-sourced |
| 78 | +standard-exclude digest, pins the named index, and checks its ordinary |
| 79 | +expanded entries, `HEAD`, and the cache tree. External attribute |
| 80 | +sources, effective replacement refs, untracked-cache results, and other |
| 81 | +unsupported repository or index shapes prevent issuance. A null index |
| 82 | +checksum is accepted only when the pinned index is bound by the durable |
| 83 | +local-APFS identity used for raced-input checks. |
| 84 | + |
| 85 | +The sidecar is installed while the index lock remains held and after |
| 86 | +the pinned index is rechecked. Status then rolls back the index lock, so |
| 87 | +issuing a sidecar does not itself rewrite the index. With optional locks |
| 88 | +disabled, status does not issue a sidecar. |
| 89 | + |
| 90 | +Validation and races |
| 91 | +-------------------- |
| 92 | + |
| 93 | +For either eligible literal command, status attempts validation before |
| 94 | +loading the index entries. It checks the bounded sidecar, pins the named |
| 95 | +index, and recreates the configuration, attribute, standard-exclude, |
| 96 | +repository, and `HEAD` inputs. It then queries the builtin file system |
| 97 | +monitor from the recorded token and accepts only an empty delta |
| 98 | +response. |
| 99 | + |
| 100 | +The attribute and exclude snapshots remain held across that query. |
| 101 | +Before returning a clean result, status freshly checks configuration, |
| 102 | +`HEAD`, uncached replacement refs, the attribute contents and namespace, |
| 103 | +the exclude sources, and both the opened and named index identities. |
| 104 | +The sidecar's exclude-source opens pass `O_NONBLOCK` and fail closed |
| 105 | +when the source cannot be opened and validated; standard-exclude |
| 106 | +symbolic links retain their normal lookup behavior. |
| 107 | + |
| 108 | +An exact porcelain hit produces no output. A plain-status hit refreshes |
| 109 | +branch, tracking, and in-progress-operation metadata and passes the |
| 110 | +empty tracked and untracked lists to the normal long-status printer. |
| 111 | +Either hit reads only the 12-byte index header and the 20- or 32-byte |
| 112 | +checksum trailer; for a null trailer, the durable local-APFS identity |
| 113 | +is the physical binding. It does not deserialize cache entries, write |
| 114 | +the index, replace the sidecar, or advance its provider token. Any |
| 115 | +failed check falls through to ordinary status. |
| 116 | + |
| 117 | +Resumable history checkpoints |
| 118 | +----------------------------- |
| 119 | + |
| 120 | +The physical clean-proof sidecar above is deliberately tied to one |
| 121 | +physical index file. A normal, top-level `git status` has a separate |
| 122 | +checkpoint store for resuming clean-status history after another Git |
| 123 | +implementation has rewritten or re-encoded the index. The store is |
| 124 | +consulted only after the ordinary index entries have been read. It |
| 125 | +cannot answer a status command by itself, but a successful restore can |
| 126 | +publish a new physical proof for the next unchanged-index plain status. |
| 127 | +The exact clean porcelain-v2 producer also refreshes this checkpoint |
| 128 | +before publishing its physical proof, so both files name the same |
| 129 | +provider boundary after a later foreign index rewrite. |
| 130 | + |
| 131 | +For an index at `<index>`, a checkpoint is stored as |
| 132 | +`<index>.csh1.<namespace-hash>`. The namespace covers the checkpoint |
| 133 | +schema, status configuration, semantic inputs, attribute namespace, and |
| 134 | +the canonical worktree, Git directory, and common directory paths. It |
| 135 | +does not include a Git executable, build prefix, provider token, or |
| 136 | +physical index generation. At most eight regular version-1 checkpoint |
| 137 | +files are retained next to an index. Each file is limited to 16 MiB; |
| 138 | +readers use `O_NONBLOCK`, do not follow symbolic links, and verify an |
| 139 | +outer checksum before parsing any section. Publication currently |
| 140 | +requires durable index identities on a local APFS file system. |
| 141 | + |
| 142 | +Each checkpoint is self-contained and co-temporal. It contains: |
| 143 | + |
| 144 | +* a canonical digest of the ordered logical index entries; |
| 145 | +
|
| 146 | +* the `FSMN` token and dirty bitmap; |
| 147 | +
|
| 148 | +* the serialized untracked cache and its paired `FSUC` token, when an |
| 149 | + untracked cache exists; and |
| 150 | +
|
| 151 | +* the `FSCF` semantic proof bound to the same file-system-monitor token. |
| 152 | +
|
| 153 | +The logical index digest includes entry count, path, stage, object ID, |
| 154 | +mode, `CE_VALID`, skip-worktree, and intent-to-add state. It excludes |
| 155 | +index format, checksum, file identity, cached stat data, and |
| 156 | +`CE_FSMONITOR_VALID`. Split and collapsed sparse indexes and |
| 157 | +unrecognized transient flags reject matching. A changed logical digest |
| 158 | +misses, while publication additionally rejects logical changes during |
| 159 | +the command and racy entries. This lets an index-format-only rewrite |
| 160 | +find the same logical state without preserving proof across commands |
| 161 | +which can change entry membership or persistent flags. |
| 162 | + |
| 163 | +On a valid hit, status installs all checkpoint sections together in a |
| 164 | +scratch index, rechecks the pinned index, and only then replaces the |
| 165 | +in-memory acceleration state. It queries the builtin file-system |
| 166 | +monitor from the stored token. If the named index already carries a |
| 167 | +different usable builtin token, status first requires the stored token |
| 168 | +to return a delta; otherwise it keeps the named boundary for the |
| 169 | +forward-baseline fallback. A trivial response, provider restart, |
| 170 | +malformed section, token mismatch, namespace mismatch, or index race |
| 171 | +falls back to ordinary validation. |
| 172 | + |
| 173 | +Status publishes a replacement checkpoint only after closing the |
| 174 | +provider token and validating the semantic proof and paired untracked |
| 175 | +cache. Publication uses the normal index lock followed by a per-slot |
| 176 | +lockfile, and atomically replaces one namespace slot. When publication |
| 177 | +succeeds, status rolls back the pending acceleration-only index update. |
| 178 | +After an external restore, status also leaves the main index untouched |
| 179 | +if republication fails, so one proof namespace is not copied over |
| 180 | +another implementation's index extensions. Only literal normal status |
| 181 | +and the exact clean porcelain-v2 producer enable this lane; commands |
| 182 | +capable of logical index changes retain the normal index-writing path. |
| 183 | +Optional-lock-free commands neither publish checkpoints nor use this |
| 184 | +rollback path. |
0 commit comments