Repository navigation
Add filesystem monitor support to status - #3153
Draft
Sebastian Thiel (Byron) wants to merge 21 commits into
Draft
Sebastian Thiel (Byron) wants to merge 21 commits into
Sebastian Thiel (Byron) wants to merge 21 commits into
Conversation
Sebastian Thiel (Byron)
force-pushed
the
fsmonitor-support
branch
4 times, most recently
from
November 3, 2026 15:45
92517af to
c372dae
Compare
This was referenced Nov 3, 2026
Sebastian Thiel (Byron)
force-pushed
the
fsmonitor-support
branch
7 times, most recently
from
November 6, 2026 08:32
5181ebd to
1a83948
Compare
Sebastian Thiel (Byron)
force-pushed
the
fsmonitor-support
branch
2 times, most recently
from
November 7, 2026 09:30
2f68568 to
1077036
Compare
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
Sebastian Thiel (Byron)
force-pushed
the
fsmonitor-support
branch
from
November 9, 2026 14:22
1077036 to
fa908ee
Compare
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
Sebastian Thiel (Byron)
force-pushed
the
fsmonitor-support
branch
from
November 9, 2026 19:11
fa908ee to
a0ef0d9
Compare
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.
Sebastian Thiel (Byron)
force-pushed
the
fsmonitor-support
branch
from
November 10, 2026 12:53
a0ef0d9 to
0ee7dc4
Compare
Draft
1 of 3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tasks
This section is for Byron only. Models continuing this PR must not add, remove, check, uncheck, rename, or reorder checkboxes here.
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.fsmonitorconfiguration, 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 throughOutcome::write_changes(). Failed or unusable monitor responses fall back to ordinary filesystem checks.Monitored status also reuses Git's warmed
UNTRdirectory 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 safeFSMNandUNTRstate. 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'sgitbutler-fsmonitorbranch and Git itself. Monitor activation follows repository configuration, includingincludeIf, without a repository-size cutoff.Meaningful steps
FSMNcheckpoints ingix-index, invalidating saved state on mutable index access.gix-status; raw entry flags alone cannot authorize skipping checks.gix-dirand pass them throughgix-status, retaining disk traversal when options or delegate callbacks require omitted entries.merge --update-head. Malformed optional cache data is discarded without preventing the merge.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=falsedisables reuse. As with Git, changingcore.ignoreCaserequires removing the old cache withgit update-index --no-untracked-cachebefore 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.