Skip to content

Commit ad7be65

Browse files
Merge tb/codex/status-preview-unstable into codex-unstable
Integrate the current tb/codex/status-preview-unstable topic into the internally distributed codex-unstable branch. Codex-Integration: tb/codex/status-preview-unstable@f92dd57ecdaea8626c7ea72bb72e2ca9a7772716
2 parents 00ee4fe + f92dd57 commit ad7be65

165 files changed

Lines changed: 39964 additions & 405 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Documentation/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ TECH_DOCS += technical/send-pack-pipeline
142142
TECH_DOCS += technical/shallow
143143
TECH_DOCS += technical/sparse-checkout
144144
TECH_DOCS += technical/sparse-index
145+
TECH_DOCS += technical/status-clean-proof
145146
TECH_DOCS += technical/trivial-merge
146147
TECH_DOCS += technical/unambiguous-types
147148
TECH_DOCS += technical/unit-tests

Documentation/config/core.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,17 @@ relatively high IO latencies. When enabled, Git will do the
729729
index comparison to the filesystem data in parallel, allowing
730730
overlapping IO's. Defaults to true.
731731

732+
core.preloadIndexBulk::
733+
On supported filesystems, scan working tree directories in bulk before
734+
the parallel index preload.
735+
+
736+
This replaces per-entry filesystem lookups with a physical directory scan,
737+
but may cost more than normal preload depending on filesystem and cache
738+
state. Inconclusive scans are discarded before continuing with the normal
739+
preload. Currently this is supported on APFS, ext-family filesystems, and
740+
XFS, and only has an effect when `core.preloadIndex` is enabled. Defaults
741+
to false.
742+
732743
core.unsetenvvars::
733744
Windows-only: comma-separated list of environment variables'
734745
names that need to be unset before spawning any other process.

Documentation/gitformat-index.adoc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,49 @@ The remaining data of each directory block is grouped by type:
366366
- An ewah bitmap, the n-th bit indicates whether the n-th index entry
367367
is not CE_FSMONITOR_VALID.
368368

369+
== File System Monitor untracked-cache token
370+
371+
The file system monitor untracked-cache token records the provider
372+
token associated with an untracked-cache snapshot. The signature for
373+
this extension is { 'F', 'S', 'U', 'C' }.
374+
375+
The extension consists of:
376+
377+
- 32-bit version number: the current version is 1.
378+
379+
- A NUL-terminated string containing the opaque file system monitor
380+
token associated with the untracked-cache data.
381+
382+
== File System Monitor semantic proof
383+
384+
The file system monitor semantic proof records the configuration and
385+
attribute inputs for a completed worktree-content verification. Its
386+
signature is { 'F', 'S', 'C', 'F' }.
387+
388+
The extension consists of:
389+
390+
- 32-bit version number (currently 1).
391+
392+
- 32-bit magic number identifying version 1 records (`FSC1`).
393+
394+
- 32-bit flags. The low four bits respectively indicate a complete
395+
attribute manifest, a provider-token binding, a stat-data binding, and
396+
coverage of the full index. All other bits must be zero.
397+
398+
- 32-bit length of the provider token.
399+
400+
- 32-bit length of the attribute manifest.
401+
402+
- The provider token, without a terminating NUL.
403+
404+
- Three hashes, using the index hash algorithm, over the relevant Git
405+
configuration, semantic-conversion configuration, and attribute state.
406+
407+
- The attribute manifest described by its length above.
408+
409+
- A hash over all preceding bytes in this extension, using the index hash
410+
algorithm.
411+
369412
== End of Index Entry
370413

371414
The End of Index Entry (EOIE) is used to locate the end of the variable

Documentation/technical/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ articles = [
3131
'shallow.adoc',
3232
'sparse-checkout.adoc',
3333
'sparse-index.adoc',
34+
'status-clean-proof.adoc',
3435
'trivial-merge.adoc',
3536
'unambiguous-types.adoc',
3637
'unit-tests.adoc',
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
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

Comments
 (0)