Skip to content

Add filesystem monitor support to status - #3153

Draft
Sebastian Thiel (Byron) wants to merge 21 commits into
mainfrom
fsmonitor-support
Draft

Sebastian Thiel (Byron) wants to merge 21 commits into
mainfrom
fsmonitor-support

Conversation

@Byron

@Byron Byron commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Tasks

This section is for Byron only. Models continuing this PR must not add, remove, check, uncheck, rename, or reorder checkboxes here.

  • refackiew

Everything below this line was generated by Codex.

Created by Codex on behalf of Byron. Byron will review before this is ready to merge.

Status honors trusted core.fsmonitor configuration, using hook protocols 1/2 or Git's built-in daemon. It queries the saved checkpoint before skipping tracked files, invalidates reported paths and directory descendants, and writes refreshed tokens and dirty bitmaps through Outcome::write_changes(). Failed or unusable monitor responses fall back to ordinary filesystem checks.

Monitored status also reuses Git's warmed UNTR directory cache after checking worktree identity, ignore rules, walk options, and monitor events. Index writes preserve validated cache data; callers rebuilding an index can explicitly carry forward safe FSMN and UNTR state. Tracing reports query selection, validity counts, daemon startup/connection outcomes, cache hits, directory reads, and fallback reasons without logging opaque monitor tokens.

Byron requested this so applications using gix status, including GitButler clients that rebuild indexes, can benefit from state already maintained by Git and avoid repeated metadata checks and directory reads. The implementation was compared with schacon/gitoxide's gitbutler-fsmonitor branch and Git itself. Monitor activation follows repository configuration, including includeIf, without a repository-size cutoff.

Meaningful steps

  1. Reject incomplete EWAH bitmaps before missing dirty bits can be trusted.
  2. Expose and serialize FSMN checkpoints in gix-index, invalidating saved state on mutable index access.
  3. Add refreshed validity masks and clean-entry tracking to gix-status; raw entry flags alone cannot authorize skipping checks.
  4. Integrate trusted hooks into iterator and direct status calls, with protocol selection, conservative fallback, path invalidation, and selective writeback.
  5. Query Git's daemon over Unix sockets or Windows named pipes, with supported-platform autostart and short temporary aliases for long Unix socket paths.
  6. Trace filesystem-monitor queries, scan fallbacks, and daemon outcomes.
  7. Preserve, serialize, and invalidate Git's untracked cache, including path, subtree, and checkpoint changes.
  8. Accept cached directory listings in gix-dir and pass them through gix-status, retaining disk traversal when options or delegate callbacks require omitted entries.
  9. Carry validated monitor and untracked-cache state into rebuilt indexes, and use this in merge --update-head. Malformed optional cache data is discarded without preventing the merge.
  10. Reuse compatible untracked caches during monitored status and retain cache invalidation together with refreshed tokens during writeback.

Limits

Git populates new untracked-cache listings; gix preserves, validates, and invalidates existing ones. Incompatible walk options, uncertain non-ASCII filename composition, and cached untracked names without reliable file types use directory reads. core.untrackedCache=false disables reuse. As with Git, changing core.ignoreCase requires removing the old cache with git update-index --no-untracked-cache before warming it again.

Alternate Unix daemon socket locations on remote filesystems and daemon responses over 64 MiB fall back to full scanning. Windows execution was not tested locally; CI provides platform validation. As in Git, a connected but stalled Windows daemon can block synchronous pipe reads.

Comment thread gix-notify/src/backend/windows/native.rs Dismissed
@Byron
Sebastian Thiel (Byron) force-pushed the fsmonitor-support branch 2 times, most recently from 2f68568 to 1077036 Compare November 7, 2026 09:30
Arthur Jean (arthjean) added a commit to arthjean/paneflow that referenced this pull request Nov 8, 2026
Copies the gix-notify crate of the draft GitoxideLabs/gitoxide#3153 under vendor/gix-notify, unchanged except for its manifest, and links it from paneflow-git with the gix-error and gix-parallel that gix 0.90 already resolves. The lockfile test pins the copy, its upstream commit and the shared gix runtime, and keeps it out of the size-capped helpers.

Refs #134
Arthur Jean (arthjean) added a commit to arthjean/paneflow that referenced this pull request Nov 9, 2026
Copies the gix-notify crate of the draft GitoxideLabs/gitoxide#3153 under vendor/gix-notify, unchanged except for its manifest, and links it from paneflow-git with the gix-error and gix-parallel that gix 0.90 already resolves. The lockfile test pins the copy, its upstream commit and the shared gix runtime, and keeps it out of the size-capped helpers.

Refs #134
Knowing how the venerable `notify` crate sometimes doesn't work as one would expect,
particularly on Linux, it's probably worth it to give it another shot with assistance,
thinking that todays models can probably do a better job, ultimately.

Walked through the watcher tests (high-level API) and actually tried to understand and
follow. Many changes were done based on my feedback.

<!-- agent -->
Long-running applications such as Tix need bounded event intake, explicit
coverage loss, replaceable subscriptions, and predictable shutdown without
owning platform notification machinery themselves. Provide these facilities in
the Git-independent `gix-notify` crate so repository monitoring and other event
loops can share the same contract.

Bound queued events and diagnostic samples, wake consumers without holding the
queue lock, and invalidate coverage on overflow, disconnection, or root
replacement. Canonicalize registrations, preserve native path representations,
and keep file, nonrecursive-directory, and recursive-directory interests
separate from the native registrations used to implement them.

Own notification delivery on macOS through FSEvents, on Linux through inotify,
and on Windows through `ReadDirectoryChangesW` and a completion-port worker.
macOS and Linux support administrative-marker delivery fences. Windows uses
bounded asynchronous reads, validates native records, and drains cancelled
operations before releasing their buffers; delivery synchronization remains
explicitly unsupported there. Retain an upstream `notify` compatibility backend
for other platforms.

Include the workspace registration, dependencies, documentation, example, queue
tests, and native backend tests with the complete crate. Repository-specific
watch inventories and application integration can build on this independently.

Assisted-by: GPT 6.0 Astra
Tix's repository monitor needs to track configuration dependencies even when
an active include is missing or empty. Parsed sections alone cannot identify
those paths, so observing include resolution lets the monitor notice when a
missing file appears or an empty file gains configuration.

Add `File::resolve_includes_with_observer()` to report each resolved active
include before filesystem checks and reads. Preserve existing include
resolution behavior through the observer-free entry points. Root
configuration paths remain the caller's responsibility.

Keep the integration tests with this API. They cover missing, empty, nested,
and conditional includes, disabled resolution, and unavailable interpolation.

Validation on macOS with the locked dependency graph:

- `cargo test --locked -p gix-config observer_`: both observer tests passed.
- `cargo check --locked --workspace --all-targets`: passed with this API
  independently of the repository monitor integration.
Tix needs to keep history and worktree views current without retaining a
repository while idle. Build `gix::notify::RepositoryMonitor` on `gix-notify`
and use it in Tix so repository-aware invalidation and coverage recovery can be
shared by other long-running Git clients.

Expose `Repository::monitor()` through the opt-in `notify` feature. Event loops
call `service()` to process bounded batches and `next_timeout()` to schedule
maintenance and publication. Outcomes report conservative cache invalidations
and retain errors alongside simultaneous changes; notifications do not promise
atomic Git transactions. This layer consumes native events through `gix-notify`
directly, independently of the Git fsmonitor protocol client.

Keep metadata and ignore-aware worktree subscriptions independent. Confine
subscriptions and missing-directory fallback to the worktree and its private
and shared Git directories. Track local configuration roots, active includes,
and repository-local ignore and attribute dependencies, including missing
permitted files. Reopening the repository reads external configuration without
adding watches outside these roots. Preserve raw Git path bytes and avoid extra
parent watches for replacing an entire repository root.

Observe linked-worktree membership and administrative roots non-recursively,
including incomplete worktrees before their `gitdir` files exist. Keep recursive
coverage for shared refs and the current worktree's refs and operation
directories. Reconcile subscriptions after changes or coverage loss and use the
configurable 60-second safety interval to rediscover coverage after missed
events or failures.

Establish metadata coverage before Tix's initial history snapshot. Publish
worktree invalidations on the next service call, replacing Tix's previous
75 ms worktree debounce. By default, metadata waits for 100 ms of quiet with a
250 ms maximum latency, and failed discovery or registration retries after
five seconds. Keep these scheduling intervals configurable in the library.

Bound worktree invalidation scopes by count and bytes, escalating to a full
worktree refresh when their budget is exhausted. Bound monitor diagnostics
and Tix's response logs to 16 representative paths and 4 KiB of path bytes,
with omitted-path counts, replacing the unbounded set of seen paths.

Use configuration-include observation from `gix-config` to track configuration
and pattern dependencies in `gix`, and replace Tix's direct watcher management
with the repository monitor. Keep the Tix specification and regression tests
with this integration, including nested ignores, cache invalidation, linked
worktrees, excluded external dependencies, and missing-root recovery.

Validation on macOS:

- `cargo test -p gix --no-default-features --features sha1,notify,status --lib`:
  all 36 tests passed.
- `cargo test -p gix-tix --features sha1 --lib watch`: both watcher tests passed.

These checks used the locked dependency graph. Full workspace QA and native
Linux/Windows runtime tests were not run.

Co-authored-by: Byron <sebastian.thiel@icloud.com>
…e servers

Applications and monitored status need reusable Git filesystem monitor clients
and servers without a dependency on `gix` or a command-line parser. Introduce
`gix-fsmonitor` with its complete client API and optional `server` feature, and
keep repository discovery, configuration, and process launching in the separate
`gix-fsmonitor-daemon` package, which provides the `gix-fsmonitor` executable.

Support hook protocols 1 and 2, native Simple IPC over Unix sockets and Windows
named pipes, and Git daemon startup on macOS and Windows. Callers supply paths,
tokens, command context, and retry, timeout, and response-size options. Trace
connection and protocol outcomes without logging opaque tokens or path contents;
leave trusted configuration, checkpoint validation, and scan policy to callers.

The server uses owned repository context and complete native watch coverage,
independent of ignore rules and client indexes. A bounded journal serves multiple
token baselines and conservatively invalidates lost or uncertifiable history.
macOS and Linux synchronize delivery through administrative markers; Windows
currently requests full scans. Preserve Git's endpoint and startup-lock protocol,
resolve roots to native spelling, and support long Unix socket paths through
private aliases without changing the process working directory.

`server::spawn(Context)` returns after binding and initial watch registration.
The returned handle can request shutdown, wait, or stop and join; dropping it
also stops its owned instance. Initial failures release resources, and stopping
an old handle cannot stop a replacement endpoint owner. Each linked worktree
has an independent endpoint and watch lifetime. The CLI supports foreground
operation, automatic startup, stop, status, flush, and raw queries using this
same runtime.

Validation: all 36 client, server, and daemon tests pass on macOS at this
introduction, and the workspace builds with all targets and the locked dependency
graph. Coverage includes Git interoperability, readiness, duplicate endpoints,
shutdown and restart, independent roots, native synchronization, long paths,
Unicode aliases, ignored tracked files, alternate indexes, and root removal.
The combined implementation was also previously checked with strict Clippy,
rustdoc, and Linux/Windows ARM64 compilation. Native Linux and Windows runtime
validation remains outside the locally checked scope.

Co-authored-by: Codex <codex@openai.com>
While adding `core.fsmonitor` support to status, an incomplete bitmap could
make missing dirty bits appear clear and hide worktree changes. Require
iteration to cover every declared bit before reporting success.

The regression declares one bit in an empty encoding and failed before
this change. Validation: `cargo test -p gix-bitmap --features gix-testtools/sha1`
and the complete `gix-index` suite with parallel processing.

Git reference: `6de20f6092` (`v2.56.0-116-g6de20f6092`), whose `FSMN`
extension records dirty entries in an EWAH bitmap.
Status needs Git's saved monitor token and dirty bitmap to avoid checking
files which the monitor knows are unchanged. Expose versioned checkpoints
and conservative bitmap decoding without trusting them during index reads.
Write `FSMN` from current entry flags, excluding removed entries and keeping
conflicts, intent-to-add entries, gitlinks and sparse directories dirty.
Mutable entry/path access drops the checkpoint so an in-memory index cannot
reuse bitmap positions after mutation.

Git reference: `6de20f6092` (`v2.56.0-116-g6de20f6092`), `fsmonitor.c`
index extension encoding and `fill_fsmonitor_bitmap()` behavior.

Validation: failing serialization/bitmap regressions first, then complete
`gix-index` SHA-1 and SHA-256 suites; final parallel suite passed 107 tests.
`cargo clippy -p gix-index --all-targets --features sha1,serde -- -D warnings`
passed. Tests cover token versions, malformed bitmaps, mutation invalidation,
removed and special entries, extension selection and NUL-token rejection.
Add an optional per-entry validity mask to both index/worktree status
contexts. A refreshed monitor can now avoid filesystem calls for unchanged
files and retain the entries actually confirmed clean for index writeback.
An explicit mask overrides old entry flags so failed monitor queries can
force normal checks. Pathspec-excluded and interrupted entries retain their
prior state; conflicts, intent-to-add entries and submodules are checked.

This plumbing enables the requested `core.fsmonitor` support in porcelain
status. Git reference: `6de20f6092`, `fsmonitor.c` and
`t/t7519-status-fsmonitor.sh`. A regression first demonstrated that the old
`FSMONITOR_VALID` shortcut incorrectly hid intent-to-add entries.

Validation: 39 focused SHA-1 tests, all 43 SHA-256 status tests, and clippy
with all targets/features and `-D warnings`. New tests cover scan omission,
clean marking, dirty/excluded/interrupted entries and invalid mask lengths.
Adapt the porcelain caller to initialize the new context field.

Entry `FSMONITOR_VALID` flags alone no longer authorize scan omissions;
callers must supply a mask refreshed against their monitor. This lets
porcelain disable monitoring without scanning every entry to find stale
in-memory flags, preserving narrow pathspec performance when no monitor is
configured. The no-mask regression failed before this correction.
The requested Git-compatible `core.fsmonitor` support needs to query the
configured hook before trusting the index's saved dirty bitmap. Both status
iterators and direct `index_worktree_status()` calls now query trusted hooks
with protocol 2, falling back to protocol 1 when appropriate. Explicit
`core.fsmonitorHookVersion` selects either protocol. Hooks run from the
worktree root with repository command context and shell-command support.

Invalidate reported files and directory descendants before pathspec
filtering. Failed/malformed queries and disabled configuration force ordinary
checks. Keep normal untracked-file traversal. Iterator outcomes retain the
new token and actually validated entries for `write_changes()`, including
clean statuses whose only pending change is the monitor checkpoint.

Git reference: `6de20f6092` (`v2.56.0-116-g6de20f6092`), `fsmonitor.c`
and `t/t7519-status-fsmonitor.sh`. The initial regression showed gix reporting
two deliberately unreported changes that Git skipped after priming FSMN.

Validation: all 45 selected status tests pass with and without parallelism;
clippy passes for `sha1,status,parallel`. Seven fsmonitor tests cover Git
output parity, hook protocols, shell commands, failure fallback, trust,
directory/case handling, initial checkpoints and partial-status writeback.
Git reads the generated FSMN extension and agrees with subsequent gix status.
A minimal-feature rustdoc check hits existing clone API link errors unrelated
to this change; full-feature docs will be checked with final validation.

Post-commit review found two performance issues: "Avoid writing the index
when monitor state is unchanged" and "Invalidate entries from reported paths
rather than scanning all paths". Compare the resulting token/validity against
the saved checkpoint before requesting writeback. Resolve reported files and
directory ranges directly in the sorted index, reusing its case-insensitive
lookup for fallback instead of visiting every path and its ancestors.

A new repeated-query regression failed before the writeback correction.
All eight fsmonitor regressions and focused clippy pass after both changes.

A later review identified an unnecessary scan of all entry flags when no
monitor is configured. The plumbing now requires an explicit refreshed mask,
so ordinary status can immediately bypass monitor preparation unless an FSMN
extension must be removed. All eight hook regressions pass.

The suggestion to require a NUL terminator after the last reported path was
not applied: Git's `fsmonitor.c` explicitly accepts that final path. The
existing directory-event test now compares this framing case directly with
Git to preserve compatibility.

Linux ARM and ARM64 CI exposed a same-second fixture timestamp race in
`repeated_queries_do_not_request_redundant_index_writes`: the reported clean
`dir/b` legitimately requested another stat refresh despite unchanged FSMN.
Forcing a future mtime reproduced that failure locally. Set this test file's
mtime to a fixed old value before the first status call so the assertion
isolates monitor writeback; preserve production racy-clean handling.
All eight hook regressions pass after stabilizing the fixture.

Open the fixture file with write access when setting its timestamp:
Windows `SetFileTime` requires `FILE_WRITE_ATTRIBUTES`, which a read-only
`File::open()` handle does not grant. The fixed timestamp regression and
formatting check pass locally; CI covers Windows execution.

Address review feedback to "Reject empty paths in filesystem monitor
responses". Preserve an empty result and a single optional final NUL, but
invalidate the whole checkpoint for leading, interior, or extra trailing
empty records. The extended fallback regression reproduced omitted changes
before the fix and now passes for both hook protocols. All eight hook tests
pass, including the existing unterminated-final-path compatibility case.

Windows CI exposed failed launches for otherwise successful hooks: relative
scripts were inspected for their shebang before the command entered the
worktree, and `/bin/sh` was not resolved as Git for Windows resolves it.
Use the configured Git shell on Windows, with manual splitting disabled, so
relative hooks and inline assignments resolve in the child worktree. The
existing Windows failures provide the regression; extend protocol coverage
with an inline-assignment hook. All eight hook tests pass locally.
The requested Git-compatible `core.fsmonitor` support needs to query the
worktree daemon before trusting the index checkpoint. Honor
`core.fsmonitor=true` with the new `gix-fsmonitor` client, resolving the
worktree-specific endpoint and supplying command context lazily for startup.

Feed successful responses through the hook invalidation and writeback path.
Failed queries fall back to ordinary checks with Git's `builtin:fake`
checkpoint. The client owns Unix sockets, Windows named pipes, framing,
long-path aliases, and startup on supported platforms (macOS and Windows).

Git reference: `6de20f6092` (`v2.56.0-116-g6de20f6092`),
`fsmonitor-ipc.c`, simple IPC framing, and `t/t7527-builtin-fsmonitor.sh`.
The original regression showed that status never started or queried the daemon.

Validation: all eleven hook/daemon status regressions pass on macOS,
including fragmented replies, native Git startup, checkpoint writeback,
change detection, and long socket paths with the working directory preserved.
Windows execution remains delegated to CI. Alternate remote-filesystem socket
locations retain the full-scan fallback; transport limits live in the client.
Filesystem monitor acceleration is otherwise difficult to distinguish from
an ordinary status scan. Record the selected query mechanism and protocol,
restored and refreshed valid-entry counts, returned path counts, and reasons
for falling back to scanning. Complement the client's existing connection
and startup diagnostics without logging opaque monitor tokens or worktree
path contents.

Validated the existing filesystem monitor integration tests with tracing
enabled, including hook failures and malformed responses.
…ites

Status clients must retain Git's warmed `UNTR` extension to benefit from its
directory listings. Serialize empty and populated caches in Git's format,
and expose cache replacement and conservative path/subtree invalidation.

Mutable entry/path access and a changed monitor checkpoint discard the cache
until a caller explicitly restores validated state. This prevents an updated
`FSMN` token from silently making old directory listings authoritative.

Validated Git read/rewrite parity, nested invalidation, mutation invalidation,
truncated encodings, both object hashes, the full parallel index test suite,
and clippy.
A filesystem monitor can prove that a directory has not changed since Git
cached its contents. Allow callers to supply those listings to the walker,
and pass them through `gix-status`, while retaining streaming filesystem
iteration for cache misses. Report cache hits alongside directory reads.

Partial listings which omit ignored entries are only usable for compatible
walk modes. Track all visible children before deciding whether a directory
can collapse, and validate cached names before joining paths.

Validated complete and partial caches, mixed tracked/untracked collapse,
pathspec and ignored-output fallback, hybrid disk/cache traversal, early
stopping, interruption, and invalid names. Full `gix-dir` suites passed with
both object hashes; `gix-status` tests and clippy passed as well.

CI's `housekeeping@linux-x86_64` check enforces matching shebangs and
executable permissions. Mark the three new Bash cache fixtures executable
so a fresh checkout preserves their intended invocation. The local
`housekeeping` QA stage passes at this commit after correcting their modes.
…indexes

Clients such as GitButler rebuild indexes and should retain monitor checkpoints
and safe untracked listings. Add explicit carry-forward for clients replacing
an index, and use it in the merge command before updating HEAD and its index.
Writing alone does not reread or resurrect deliberately removed extensions.

Validate the source bitmap and hash kind before modifying the destination.
Retain validity only when path, stage, object id, mode, stat and checking
flags match. Invalidate cached membership changes and ignore-rule subtrees.
The merge caller traces rejected optional monitor data and keeps its fresh
index so a malformed cache cannot prevent the requested merge.

Reference Git `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`: `fsmonitor.c`
rebuilds dirty positions after removals; `dir.c` invalidates parent listings
and inherited ignore rules; `builtin/update-index.c` invalidates monitor
validity when assume-valid or skip-worktree flags change.

Validated the full parallel index suite, five carry-forward regressions
with both object hashes, atomic failures, clippy, and a merge regression
that verifies HEAD and the rebuilt index after rejecting malformed FSMN.
Status should benefit from Git's warmed directory cache as well as its
tracked-file monitor bitmap. Validate worktree identity, walk policy, ignore
rules and monitor events before supplying cached listings. Merge tracked
names only when their presence and spelling are reliable.

Retain cache invalidation and refreshed monitor tokens together during
writeback, including restricted status calls. Fall back for uncertain
Unicode composition and untyped untracked files, using directory reads to
obtain their types together. Honor `core.untrackedCache=false` and trace
cache hits, directory reads and validation fallbacks. Existing caches are
preserved; Git still populates new listings.

Git reference: `6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`, `dir.c` cache
identity/policy and ignore validation, and `fsmonitor.c` event invalidation
before checkpoint advancement. Keep Git's query policy without a
repository-size cutoff.

Validated 15 cache regressions and all 64 status tests, including native
daemon operation, plus clippy. Coverage includes case-only renames, sparse
and assumed-valid entries, filename composition, ignore changes, removals,
token advancement, unusable monitors and incompatible walk options.

CI's `housekeeping@linux-x86_64` check failed because
`gix/tests/fixtures/make_status_untracked_cache.sh` had a Bash shebang but
was committed without executable permission. Preserve its executable mode
in fresh checkouts. The `housekeeping` QA stage failed before the correction
and passes on the complete stack with all cache fixtures correctly marked.

Both native Windows CI suites failed
`writeback_preserves_valid_siblings_and_git_can_read_the_result`: an
unreported sibling was invalid after writeback. Git for Windows resolves
the worktree through a file handle, expanding short DOS aliases such as
the runner's temporary directory. Use the same canonical worktree spelling
for cache identity and remove the Windows verbatim namespace prefix,
preserving UNC roots. Extend the cache-reuse regression to open the
worktree through a verbatim path too.

The 64 local status tests pass outside the sandbox, including socket and
native daemon tests. Formatting, local clippy with tracing enabled, and
Windows ARM64 cross-compilation pass. Cross-target clippy encounters
existing pointer-cast lints in `gix-sec`; native Windows runtime validation
is performed by the PR CI suites.
Apply tracked-entry and untracked-cache invalidation while processing each
validated monitor event. This removes the duplicate event loop while
preserving case fallback, ignore-file invalidation and full-scan handling
for malformed replies.

The existing 64 status tests pass before and after the change, including
directory events, malformed hooks, daemon responses and cache writeback.
The filesystem-monitor implementation should follow Git's writeback policy
without reconstructing changes by decoding the original bitmap or recounting
cached directories after each status call.

Track invalid-to-clean entry transitions and untracked-cache invalidations as
they happen. Keep token updates and ordinary dirty-path invalidations in memory
until another change warrants an index write. Like Git, force a checkpoint after
an incremental response reports more than 100 paths, including duplicates and
unmatched paths. Expose that threshold as
`gitoxide.fsmonitor.forceUpdateThreshold`; zero writes after any nonempty
incremental response. Full resets, checkpoint creation/removal, and cache
invalidations retain their required writeback behavior.

The plumbing API changes together with its callers: the `gix-status` contexts
now accept an `FsMonitor` containing validity and a shared change flag, and the
`gix-index` untracked-cache invalidation methods return whether data changed.

Git's reference behavior is in `fsmonitor.c` and `fsmonitor.h` at
`6de20f6092dcf9bdb1c8efe03db4b70c82b423dd`. Regression coverage compares persisted
tokens with Git and checks threshold boundaries, partial status, repeated clean
revalidation, and unchanged or failed monitors.

Validation: status and configuration regressions, the complete `gix-index` and
`gix-status` integration suites, a minimal status-feature build, and Clippy.
Applications using monitored status need to adjust daemon retry, timeout,
and response-size policies without rebuilding `gix`. Pass trusted configuration
to the `gix-fsmonitor` client's existing `Options` API through
`gitoxide.fsmonitor.connectRetries` (100), `connectRetryDelay` (50 ms),
`socketTimeout` (30000 ms), and `maxResponseSize` (64 MiB).

Zero disables retries or socket timeouts, removes retry delay, or rejects
nonempty payloads, respectively. Socket timeouts apply to Unix sockets; Windows
named pipes retain synchronous response reads. Keep trusted/lenient parsing in
`gix`, before query errors can fall back to scanning, so invalid settings remain visible instead of silently
disabling acceleration.

Keep retry, timeout, and payload enforcement in `gix-fsmonitor`. None of these
policies belongs in `gix-index`, whose checkpoint and cache APIs are unchanged.
The status, configuration trust/leniency, and defaults regressions cover the
configuration wiring.
Cold-cache Linux status reports identify rebuilding an index from every
`HEAD^{tree}` object as avoidable work. Git reuses matching valid cache-tree
nodes, while `tree_index_status()` previously loaded the entire tree on every
call, even for an unchanged index.

Add `gix_index::State::from_tree_with_cache()` and use it for status. Reuse
matching root or subtree entries after checking cached counts and entry
eligibility, retaining path validation and a complete synthetic tree index
with empty stat data and flags. This keeps callback indices, pathspecs, and
rename tracking unchanged while avoiding reads of matching tree objects.
Directory validation is reused within each cached directory to avoid adding
CPU overhead when objects are already in memory.

Invalidate `TREE` on mutable entry/path access so in-memory staged changes
cannot be hidden by stale IDs. Add explicit cache restoration and retain it
across status writeback, which only changes stat data and monitor flags.
Missing or unusable caches fall back to normal traversal.

Regression tests first showed two tree reads for both the clean-root and
changed-root fixtures; they now read zero and one respectively. Other tests
cover cached/uncached index equality, invalid counts and paths, sparse and
special entries, in-memory edits, stat writeback, pathspecs, and exact renames.
All 72 selected status tests and 122 `gix-index` tests pass, including focused
SHA-256 and serial checks. Strict Clippy, formatting, workspace/all-targets
checking, and network-enabled documentation pass. Default-feature `gix`
documentation still has existing clone API links requiring networking.

A 10,000-file, 100-directory in-memory benchmark measures approximately
0.39 ms for ordinary construction versus 0.23 ms with a matching cache-tree.
This is not an end-to-end cold-disk measurement: the API still builds and
compares a complete in-memory index, so work remains linear in entry count.
Applications that already own repositories need filesystem monitors whose
lifetimes follow the application and whose endpoints ordinary status calls can
discover. Add `Repository::fsmonitor_server()` behind the `fsmonitor-server`
feature, using the existing `gix-fsmonitor` server runtime.

Resolve the worktree, private Git directory, and common directory to native
absolute paths, and pass filesystem configuration to the server without
retaining the repository. The returned handle is ready for queries and owns
shutdown and joining. Each linked worktree has an independent endpoint and
watch lifetime; bare repositories are rejected.

Leave configuration unchanged and allow applications to select the server for
status through an in-memory `core.fsmonitor=true` override. Cover readiness,
independent linked-worktree lifetimes, checkpoint creation, subsequent tracked
changes, and unchanged repository configuration in the integration test.
Server startup launches no executable; the helper uses the local private Git
directory endpoint supported by the existing status client.
Profiling `gix status` in WebKit's 417,002-entry checkout showed that the
filesystem monitor already skipped all but nine tracked-file checks, but
untracked-cache handling still dominated the command.

Build cached tracked names from borrowed path slices and avoid repeatedly
adding shared ancestors. Reuse partial directory listings containing a
known tracked file even when they also contain subdirectories, while
retaining the fallbacks for case-insensitive, sparse, and uncertain empty
directories.

Precious parsing no longer rejects the cache when the actual ignore
patterns agree with Git. When their meanings differ, skip reuse without
invalidating Git's unchanged cache. Keep the CLI's precious-file default
and add a tracing span for cache preparation.

With `gitoxide.parsePrecious=false`, warm read-only WebKit status fell from
about 656 ms to 304 ms; Git took 239 ms. Actual directory reads fell from
21,461 with the original default command to 2,933 on the optimized path.

Validation: 73 status-related tests and 94 `gix-dir` tests passed, including
regressions for precious ignore sources and partial directory listings.
The four daemon tests passed outside the socket-restricted sandbox.
Release build, formatting, and unchanged WebKit status output verified.
On WebKit, filesystem monitoring skips almost all 417,002 tracked entries,
but status still spent substantial CPU time updating shared counters,
searching the entire index for each directory entry, retaining tracked
paths that would never be emitted, and parsing paths during traversal.
This left a measurable gap after improving untracked-cache reuse.

Batch cheap entry-flag and monitor skips per chunk while preserving
immediate progress for filesystem checks. Bound case-sensitive file
lookups to the current directory's index entries, retaining all conflict
stages and the existing case-insensitive and sparse-directory handling.
Avoid retaining hidden tracked paths while still counting them and
preventing ancestor collapse.

Validate cached names directly on Unix and restore the known parent path
bytes after each entry. Other platforms retain native component handling.
Regression coverage exercises chunked skip counts, interruption, conflict
stages beside adjacent directory prefixes, hidden tracked entries, and
native cached-name validation.

With the filesystem monitor and Git's untracked cache active, 20 warm
WebKit runs measured 221.6 +/- 2.0 ms for `gix` versus 224.5 +/- 1.8 ms for
Git. Both commands disabled index writes, and `gix` used
`-c gitoxide.parsePrecious=false` to match the cached ignore semantics.
Status output is unchanged.

Validation: 95 `gix-dir` tests, 47 `gix-status` tests for each of SHA-1 and
SHA-256, and 73 integrated `gix` status tests pass. Clippy for `gix-dir` and
`gix-status`, formatting, the release build, and a `gix` build with
`--no-default-features --features sha1,status` also pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants