ac94de78ab696fc897b82de467490c1a57e72a6d
391
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
766d7a327a |
worktree: Fix global gitignore matching outside the worktree root (#62130)
# Objective When a worktree has no enclosing git repository, the `global-gitignore` check falls back to matching the raw, unbounded absolute path. This lets an ancestor directory outside the worktree, or the worktree's own root name, incorrectly match a bare global-ignore pattern (e.g. a global entry like `tmp` or `*.com`) and mark the entire worktree as ignored, which silently breaks project search and greys out every file in the project panel. Fixes #62126 Fixes #48887 ## Solution - In `Snapshot::ignore_stack_for_abs_path`, when no containing repository is found, fall back to the worktree's own root as the boundary for `IgnoreStack.repo_root`, instead of leaving it `None`. - This reuses the existing repo-root-relative matching logic in `IgnoreStack::is_abs_path_ignored` (already correct for the git-repository case since #61689) without needing any changes to `ignore.rs` itself: ancestors outside the worktree now correctly fail the prefix check and are treated as not ignored, while the global gitignore still applies to files and directories within the worktree. ## Testing - Added `test_global_gitignore_without_repository` in `crates/worktree/tests/integration/worktree_tests.rs`, covering both variants in one worktree: an ancestor directory outside a non-git worktree matching a global pattern, and the worktree's own root name matching one, while also confirming a file that matches the pattern from within the worktree is still ignored. - Verified the new test fails without the fix (reproducing both #62126 and #48887) and passes with it. - Ran the full `worktree` integration test suite (`cargo test -p worktree --test integration`); all tests pass. - Not tested on Windows or macOS, only Linux. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] Tests cover the changed behavior --- Release Notes: - Fixed global gitignore entries incorrectly matching directories outside the opened project and marking the entire project as ignored --------- Co-authored-by: dino <dinojoaocosta@gmail.com> |
||
|
|
255880598d |
Switch from cargo-machete to cargo-shear (#62643)
This results in ~110 crates being removed, and some orphaned files also. --- Release Notes: - N/A Signed-off-by: Neel <neel@zed.dev> |
||
|
|
b25370b285 |
worktree: Yield during large file decoding (#62831)
# Objective Closing a project while a large local text file is loading can be delayed because file-reading and UTF-8 streaming loops have no await points. Partially addresses #27283. ## Solution Yield between 1 MiB blocks while: - streaming UTF-8 files into a Rope - reading files handled by the fallback decoder, including BOM, UTF-16, and other non-UTF-8 encodings Release Notes: - Improved responsiveness when closing projects that are loading large text files. |
||
|
|
ac9a03c4b9 |
Make opening large files use less peak memory (#62748)
# Objective Opening a file laods it twice. `decode_file_text` builds the whole file as a `String`, and that `String` stays alive alongside the finished rope while `text::Buffer::new` copies it in. The `Vec` behind it grows by doubling, so it also commits up to nearly the file's size again in capacity it never uses. Partially addresses #27283. ## Solution Add `decode_file_text_to_rope`, which streams the file in 1 MB blocks straight into a `Rope`, validating UTF-8 and normalizing line endings as it goes. The file is never fully held as a `String`. `LoadedFile::text` becomes a `Rope` carrying the `LineEnding` detected before normalizing, so `buffer_store` calls `Buffer::new_normalized`. ## Testing On a 729 MB SQL dump, peak memory fell 25% and CPU fell around 28%. tested on 5950x, win11. Release Notes: - Improved memory use when opening large files, reducing peak memory during load by roughly the size of the file itself. |
||
|
|
ef973c67c0 |
Add support for the "..." entry in file_scan_exclusions (#62769)
## Objective `file_scan_exclusions` replaces the defaults instead of adding to them, so excluding one extra directory means restating all eleven default globs and never picking up defaults added in later Zed releases. ## Solution `file_scan_exclusions` now accepts the `"..."` entry, which expands to the value it overrides, so `["**/node_modules", "..."]` adds to the inherited globs instead of replacing them. Entries listed by name keep their position, and leaving `"..."` out still replaces the list outright, so existing settings behave exactly as they do today. ## Testing - Four unit tests in `crates/settings_content/src/project.rs` cover splicing versus replacing, accumulation across successive layers, and edge cases: a repeated `"..."`, an empty list clearing the value, and a bare `["..."]` leaving it unchanged. - To check by hand: set `"file_scan_exclusions": ["**/node_modules", "..."]` in user settings and confirm `node_modules` disappears from the project panel and file finder while `.git` and `.DS_Store` stay excluded. Remove `"..."` and confirm only `node_modules` is excluded. Repeat in a project's `.zed/settings.json` to confirm it splices the resolved user settings rather than the defaults. - Tested on macOS. This is platform-independent settings-merge logic with no OS-specific code paths, so I did not test Linux or Windows. ## Self-Review Checklist: - [x] I’ve reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed’s UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Added support for the `"..."` entry in `file_scan_exclusions`. Custom exclusions can now extend the defaults instead of replacing them. |
||
|
|
75c80abb31 |
git: Decode non-UTF-8 blobs for project diffs (#60821)
## Summary Fixes #56449. Related to #16965. Zed’s Git panel and Project Diff build UI diffs from `language::Buffer` diff bases loaded through the Git backend. Git blob loading previously converted bytes with `String::from_utf8(...).ok()`, so legacy-encoded blobs were treated as missing and the whole worktree file appeared newly added. This follows the same encoding path used for worktree buffers: - move shared byte decoding and encoding into `language` - keep Git blob, revision, and index APIs byte-oriented with `Vec<u8>` - decode diff bases and index contents in `GitStore`, where `language::Buffer`s are created - encode index writes using the open buffer’s encoding and BOM so partial staging does not rewrite the file as UTF-8 - keep worktree loading and saving on the same shared implementation Regression coverage includes Windows-1251 decoding/encoding, UTF-8/UTF-16 BOM preservation, raw Windows-1251 Git blob loading, and a `BufferDiffSnapshot` assertion that a one-line CP1251 edit produces one modified-line hunk instead of a full-file rewrite. This does not run Git `textconv` commands. It fixes the reported legacy-encoding case without executing repository-configured commands or modifying working files on disk. ## Testing - `cargo test -p language file_content::tests --locked` - `cargo test -p git repository::tests::test_load_revisions --locked` - `CARGO_INCREMENTAL=0 cargo test -p project git_store::tests::test_decode_git_text_windows_1251_one_line_change --locked` - `CARGO_INCREMENTAL=0 cargo test -p project --test integration test_restaging_hunk_after_optimistic_unstage --locked` - `CARGO_INCREMENTAL=0 cargo check -p project --tests --locked` - `CARGO_INCREMENTAL=0 cargo check -p git_ui --tests --locked` - `cargo fmt --all --check` - `git diff --check` ## Suggested .rules additions - N/A Release Notes: - Fixed Git panel and Project Diff rendering for legacy-encoded text files whose Git blobs are not valid UTF-8. --------- Co-authored-by: Cole Miller <cole@zed.dev> |
||
|
|
20a95914df |
Remove the problematic data field from the snapshot (#62685)
Follow-up to https://github.com/zed-industries/zed/pull/62658 The problematic field is not needed at all in the snapshot, as can be constructed before starting the scanner — moreover, the field had accumulated more and more paths between rescans, leaking memory. Now, we spend more time traversing the entire tree between rescans, but that happens for rescans only which should be relatively rare? Release Notes: - N/A |
||
|
|
851bf3d499 |
Make file scanner less eager in non-git-tracked directory trees (#62583)
Fixes https://github.com/zed-industries/zed/issues/35780 Collab schema migration PR: https://github.com/zed-industries/cloud/pull/3422 The corresponding database schema migration has been created in the Cloud repo and applied to the production database. Before, Zed scanned each and every entry in the tree down from the directory it was opened in, except gitignored files and scan exclusions. The approach is unchanged, if Zed detects it was open inside a git repository: e.g. the directory open in Zed contains `.git` directory. For the rest of the projects, 2 optimizations are made: * Limit the depth of file scan traversal. Now, `file_scan_depth` (default `5`) restricts Zed from traversing any directory that has same number or more segments in its file path. Such directories behave similar to gitignored directories: their contents is not available in file finder, project search and project panel, but can be lazily traversed when the directory is expanded (e.g. project panel expands it or a nested file is open by path via terminal, etc.) To indicate that to the users, a status entry is shown firs time the limitation is hit in the project: <img width="858" height="133" alt="image" src="https://github.com/user-attachments/assets/7da6cfbb-98b4-4cc3-bf2a-8902a9597a15" /> * During the scan, any git repositories that are not direct children of the directory open in Zed (depth >= 2), are traversed and indexed normally, but their git metadata is never fetched eagerly. Only when Zed opens a buffer from that repo the git metadata is fetched and applied. All that combined now uses a way more moderate amount of CPU and RAM when opening `~`: <img width="1717" height="368" alt="Screenshot 2026-08-13 at 17 43 53" src="https://github.com/user-attachments/assets/ec83e2a9-f7cc-452b-8eb7-af158284ca4e" /> File scan inclusions and exclusions are considered still for such projects. Set `file_scan_depth` to `0` to enable old behavior. The setting is supported in the project settings, so custom values can be set based on the project's structure. --- Release Notes: - Fixed Zed using a lot of memory and CPU in large, non-git-tracked, directory trees |
||
|
|
fc58ad2226 |
Unify non-Unicode file detection code (#62581)
Closes https://github.com/zed-industries/zed/issues/62464 Closes https://github.com/zed-industries/zed/issues/62212 As a bonus, fixes the project search not working in BOM'd UTF-16 files. Release Notes: - Fixed project search not working in some non-Unicode files |
||
|
|
fa19fe3c5c |
project: Don't let a canceled caller leak a loading worktree forever (#61009)
# Objective `WorktreeStore::find_or_create_worktree` inserts the shared worktree-creation task into `loading_worktrees` and relies on the task it returns to each caller to remove that entry once creation resolves. But the creation task keeps running through the clone the map itself holds, while the map cleanup lives only in the callers' returned tasks. If every caller is cancelled before creation resolves, the resolved task stays in `loading_worktrees` forever, retaining the `Entity<Worktree>` captured in its result (a `Shared` task memoizes its output). Such a worktree can never be released: `remove_worktree` only unlists it, so its background scan keeps running and its snapshot keeps growing for the lifetime of the window. The stale entry also keeps `initial_scan_complete` permanently `false` (that flag is `loading_worktrees.is_empty() && …`). Callers are cancelled routinely — worktree creation is async and can take seconds on a large tree, while the tasks awaiting it are owned by UI that the user can close at any time (a tab or pane, a debugger panel resolving a path, an agent session, or the whole window). See the existing note in `crates/zed/src/zed.rs` that external-file worktrees are "released on file close". Observed in the wild: a home-directory worktree removed from the project kept scanning for hours and grew Zed past 45 GB; neither removing the folder nor ending the agent session freed it — only quitting Zed. (The scan-amplification half of that incident is #60988.) ## Solution Spawn the map cleanup as its own detached task, next to the map insertion, so a loading entry always leaves `loading_worktrees` when loading resolves regardless of what happens to the callers. The returned per-caller task is unchanged apart from no longer owning that cleanup. ## Testing - Added `test_worktree_released_when_creation_caller_is_cancelled`: it requests a worktree, drops the returned task immediately (as a cancelled caller would), lets creation complete, removes the worktree, and asserts the entity is released. It fails on `main` and passes with this change. - Full worktree-related project integration suite is green (45/45). ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed a memory leak where a worktree whose creation was requested by a since-cancelled task (e.g. a folder opened as its owning tab/panel/window closed) could never be released, leaving its background scan running and its snapshot growing for the lifetime of the window. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
bfcac04822 |
worktree: Anchor ignore rules at the repository they belong to (#62325)
Since #60772, a worktree's ignore rules are also applied to the directories above its root. Because of this, an `info/exclude` pattern naming one of those parent directories marks it as ignored, and with it the whole worktree below. Stop the walk at the repository containing the worktree root. Also skip exclude rules for paths outside the work directory they are anchored at, as `.gitignore` and global gitignore rules already do. Release Notes: - Fixed a worktree being reported as entirely ignored when its repository's `info/exclude` named one of the worktree's parent directories |
||
|
|
3692029a80 |
Bump rustc to 1.97 (#62395)
Release Notes: - N/A |
||
|
|
59920bc9b5 |
language: Avoid UTF-16 false positive with embedded ASCII (#61250)
# Objective - Zed can hang (and eventually get force-killed) when opening certain binary files, because `analyze_byte_content`'s UTF-16 heuristic misclassifies them as UTF-16LE/BE text. - Reproduced with a real-world case: a ~92 MB OTBM game map file (the binary map format used by OpenTibia/Tibia servers), which interleaves short ASCII strings with small u16 length/type fields. Its byte pattern (mostly-zero high bytes, very few control characters) passed the existing check, so Zed read the entire file, decoded it as UTF-16, and opened it as an editable buffer with tens of millions of characters and effectively no line breaks — a pathological case for the text layout/renderer that hangs or crashes the app (most noticeably on Windows). ## Solution `is_plausible_utf16_text` in `crates/language/src/file_content.rs` previously only rejected the UTF-16 hypothesis when too many code units were control characters (> 2%). That's not sufficient on its own: binary formats that interleave short ASCII fragments with small numeric fields can have a very low control-character ratio while still not being real text — most of their "characters" land on stray symbol/high-byte values rather than letters, digits, or spaces. This PR adds a second, independent requirement: at least 30% of the analyzed code units must be letters, digits, or spaces (the bulk of any real UTF-16 text sample). Both conditions now have to hold for a byte sequence to be classified as UTF-16 text — otherwise it falls through to `ByteContent::Binary`, and file loading is rejected early, as intended for binary files, instead of decoding the whole file as garbled text. ## Testing - Added `test_length_prefixed_binary_not_misdetected_as_utf16le` in `crates/worktree/src/worktree.rs`, using a synthetic byte pattern that reproduces the same statistical shape as the real file (null high bytes, low control-character ratio, no word-like low bytes) — asserts it is now classified `Binary`. - Verified against the real 92 MB `.otbm` file that triggered the bug (not committed, since it's user data): before the fix it was classified `Utf16Le`, after the fix it's classified `Binary`. - Ran the full existing `analyze_byte_content` / `is_plausible_utf16_text` test suite (`cargo test -p worktree --lib tests::`) — all 7 tests pass, including the pre-existing positive UTF-16LE/UTF-16BE detection tests, so legitimate UTF-16 files are unaffected. - Built a full `--release` binary on Windows and confirmed opening the real file now shows "Binary files are not supported" immediately instead of hanging. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments — N/A, no unsafe code - [x] The content adheres to Zed's UI standards — N/A, no UI change - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable — only affects classification of the first 1 KB of a file, negligible cost --- Release Notes: - Fixed: Zed no longer hangs when opening certain binary files (e.g. game asset/map formats) that were previously misdetected as UTF-16 text. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
0ef4dd61eb |
worktree: Fix global gitignore on ancestors (#61689)
# Objective Fixes #61687 Prior to #60772, an `abs_path` outside the `repo_root` would cause a panic. That PR changed it to return the `abs_path` itself, preventing the panic, but allowing all parents of `repo_root` to be subject to the global ignore. This is not what git itself does. ## Solution - This change returns `false` when the `abs_path` is outside the `root_repo`, preventing the panic but also not returning the `abs_path` ## Testing - One in-memory test - Manual test by building Zed and confirming the project pane changes (pictured below) ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase ### Before, with the bug <img width="1430" height="814" alt="Screenshot 2026-07-26 at 11 44 11 AM" src="https://github.com/user-attachments/assets/66e3bb95-4f45-4fd9-a1e4-e7f253f092eb" /> ### After the fix <img width="1568" height="1042" alt="Screenshot 2026-07-26 at 12 34 58 PM" src="https://github.com/user-attachments/assets/588eb01d-830a-4c22-93c0-667742de90b6" /> Release Notes: - Fixed the project panel's global gitignore incorrectly matching parent directories of a repository --------- Co-authored-by: dino <dinojoaocosta@gmail.com> |
||
|
|
fb813f70d6 |
worktree: Suppress bare .git events explained by filtered sibling events (#61636)
Fixes an infinite git-rescan loop on Windows introduced by #59876. On Windows, creating or deleting a file directly inside .git updates the directory's last-write time, so ReadDirectoryChangesW reports a bare .git Changed event alongside the file's own event. Since #59876, bare .git events schedule a git rescan (to cope with coalesced FSEvents on macOS), so every filtered-out lock-file event still triggered a rescan through its paired bare event. Because a rescan's own `git diff --numstat HEAD` can take .git/index.lock (even under --no-optional-locks, e.g. in jj-colocated repos whose index never refreshes clean), each rescan re-triggered the next one, spawning ~9 git processes per cycle, ~4 cycles/sec, indefinitely. Bare .git events are now deferred while processing an event batch and only trigger a rescan when the batch contains no filtered event for the same git dir that explains the directory change. A standalone bare .git event (the macOS coalescing case #59876 addressed) still triggers a rescan, as does any batch containing a meaningful .git change. Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
413b457870 |
worktree: Reload git state when a watcher rescan covers a repository (#61541)
# Objective When the OS file watcher loses sync (e.g. its event queue overflows under heavy fs churn), it drops pending events and reports a single `Rescan` event for the watched root. Git changes hidden behind such a rescan were silently lost, leaving the git panel and branch indicator stale until something else touched `.git`. Contributes to #13176. May fix #60102, though that report predates #60660 and may already be addressed by it on nightly (see Related PRs below). Two bugs caused this, and they masked each other: 1. **A rescan never triggered a git reload.** The `Rescan` event's path is the worktree root, not something inside `.git`, so it never populated `dot_git_abs_paths` in `process_events` — and since `.git` is excluded from entry scanning, the rescan produced no `.git` events either. The dropped git changes were simply never picked up. 2. **Re-scanning reset `git_dir_scan_id` to 0.** The snapshot diff detects git changes by comparing scan ids, so re-inserting the repository with a fresh id could wipe out a bump made earlier in the same scan cycle, swallowing the corresponding `UpdatedGitRepositories` signal. The masking is why these fixes land together rather than as two PRs: the root-rescan case in `test_dot_git_dir_event_does_not_suppress_children` only passed on `main` because the buggy scan-id reset made the snapshot diff fire spuriously. Fixing either bug alone turns that (currently green) test red. ## Solution - `process_events`: a `Rescan` event now schedules a git state reload for every repository whose git directory (`dot_git`, `common_dir`, or `repository_dir`) lies under the rescanned path, covering linked worktrees and gitfile repositories, including git dirs watched outside the worktree root. - `insert_git_repository_for_path`: carry the existing `git_dir_scan_id` forward when re-inserting a repository instead of resetting it to 0. Deliberately *not* bumped either: re-insertion is snapshot bookkeeping, not evidence of a git change — bumping would trigger spurious full reloads on non-lossy paths (explicit refreshes, path-prefix scans). Only `update_git_repositories` claims that git state changed. - `changed_repos`: a `debug_assert` enforcing that `git_dir_scan_id` never regresses, so future violations of this invariant fail loudly in tests instead of manifesting as a stale git panel. ## Testing New fault-injection infrastructure and tests: - `FakeFs::simulate_watcher_overflow` models the kernel's watch queue overflowing: buffered (undelivered) events are discarded and replaced by a single `Rescan` for the given root, mirroring FSEvents `kFSEventStreamEventFlagMustScanSubDirs`, inotify `IN_Q_OVERFLOW`, and Windows `ERROR_NOTIFY_ENUM_DIR`. - `test_watcher_overflow_rescan_reloads_git_state`: a git change whose events are lost to an overflow must still be picked up via the rescan (reproduces bug 1; fails on `main`). - `test_git_update_in_same_batch_as_rescan_is_not_lost`: a git event processed in the same batch as a rescan must not lose its scan-id bump to the repository re-insertion (reproduces bug 2; fails on `main`). - `test_random_git_updates_with_watcher_overflows`: randomized property test (100 iterations) asserting that every git state change is eventually signaled via `UpdatedGitRepositories` under random event batching, delays, and overflows. Fails on `main` within the first few seeds. - `test_random_worktree_changes` now also injects watcher overflows, extending its existing convergence property to rescan reconciliation of worktree entries (this already passed; the injection guards it going forward). Full `worktree` and `fs` suites pass. Verified the directed tests exercise the intended code paths via trace logging (the same-batch test hits `update_git_repositories` stamping followed by re-insertion, distinct from the overflow test where no `.git` event arrives at all). ## Related PRs The recent stale-git-state reports trace back to three distinct mechanisms that share one symptom. This PR addresses the third: - **Events never generated** — #60660 (merged, in this PR's base): Linux's non-recursive watcher missed nested `refs/` directories, so external commits/fetches produced no events at all. That PR (together with #60590, which explicitly rescans after Zed-initiated reset/fetch and touches only `git_store.rs`) fixed #60348. No overlap with this PR; a merge against current `main` is clean, and the refs-watching tests are disjoint from the overflow/rescan tests added here. - **Events coalesced** — #59876 (open, complementary): FSEvents can merge `.git` child events into a bare `.git` `Changed` event; the signal arrives, in a shape Zed ignores. @RemcoSmitsDev's review comment there describes this PR's failure mode and calls the two fixes complementary; this is effectively the follow-up promised in that comment. Both PRs touch the same region of `process_events`, so whichever lands second needs a trivial rebase, and #59876 flips the bare-`.git` expectation in `test_dot_git_dir_event_does_not_suppress_children` Case 2, which this PR preserves. - **Events dropped** — this PR: the watcher generated events but lost them to a queue overflow, and the resulting `Rescan` did not reach the git reload path. #59976 and #60098 (merged) reduced how often this happens; this PR makes git state recover correctly when it does. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed the git panel and branch indicator showing stale state after heavy file-system activity caused the file watcher to lose events |
||
|
|
281f6a5e02 |
Refresh git state on bare .git events (#59876)
# Objective Fix stale Git state in Zed when repository metadata changes are reported only as a bare `.git` directory event. On macOS, file watcher events can be coalesced such that Git operations only surface as a `Changed` event for the `.git` directory itself, rather than individual events for files like `.git/index` or `.git/HEAD`. Zed previously ignored bare `.git` directory events before scheduling a Git metadata refresh, which could leave the Git panel showing stale changes or an outdated history even though `git status` / `git log` reflected the latest state. ## Solution Treat meaningful bare `.git` directory events as Git repository updates before skipping them from normal worktree scanning. This preserves the existing behavior of not scanning `.git` as regular project content, while still notifying the Git repository tracking path that repository metadata may have changed. As a result, Git state such as `HEAD` and file statuses are refreshed when `.git` itself is the only watcher event. Updated the existing worktree test expectations so bare `.git` events now trigger `UpdatedGitRepositories`, while skipped files like `.git/index.lock` still do not. Added a test covering the full project/Git path: - repo initially has old `HEAD` and a modified file status - fake Git state is updated to represent a commit - only a bare `.git Changed` event is emitted - Zed refreshes the repository snapshot, observes the new `HEAD`, and clears the stale file status ## Testing The new tests cover the full project/Git path scenario described above. It fails without the fix and passes with the fix. Unfortunately, i was unable to reproduce the issue deterministically enough to test it end to end. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Fixed stale Git panel state after repository metadata changes. Co-authored-by: Eric Holk <eric@zed.dev> |
||
|
|
63a2ae3eee |
worktree: Apply outer repository excludes within nested repositories (#61492)
Closes TRA-162 When an entry's ignore stack is rebuilt from scratch (opening a file, file system events, a search that includes ignored files), `ignore_stack_for_abs_path` only consulted the `.git/info/exclude` rules of the nearest ancestor containing `.git`. For a path inside a nested repository, that nearest ancestor is the nested repository itself, so the outer repository's exclude rules were silently dropped: entries that were correctly ignored after the initial scan would flip to unignored the moment they were loaded or changed on disk, and from then on project search would surface them. This is the same class of bug that #60772 fixed for ancestor `.gitignore` files — this change extends the fix to `info/exclude` by collecting the exclude rules of every containing repository (outermost first, mirroring how ancestor gitignores are stacked) instead of just the innermost one. Added a regression test that models the affected layout: a bare clone and a linked worktree of it kept inside the repository, hidden via anchored patterns in the outer repository's `.git/info/exclude`. Release Notes: - Fixed project search returning results from inside nested repositories that are excluded by the containing repository's `.git/info/exclude` file. |
||
|
|
4ee16d3650 |
Fix the macOS tests that hang locally (#61407)
See also https://github.com/zed-industries/notify/pull/9 <img width="2088" height="266" alt="image" src="https://github.com/user-attachments/assets/f4bc0b5c-76a9-424a-9abc-abde6e56b9db" /> Release Notes: - N/A |
||
|
|
78652e2f50 |
Fix several small performance inefficiencies in hot paths (#61275)
# Objective Land five small, independent performance fixes found during an audit of hot paths (anchor resolution, line shaping, worktree scanning, and sorting in multibuffers). ## Solution Each fix is its own commit, so **this PR is best reviewed commit-by-commit** — every commit message contains the full reasoning for that change: - `text`: Avoid redundant rope traversal in `Anchor → usize` conversion — call `offset_for_anchor` directly instead of `summary_for_anchor`, which recomputed the same byte offset with ~4 extra O(log n) tree walks. This is the hottest anchor-resolution path. - `editor`: Avoid double allocation per shaped line — `line.as_str().into()` instead of `line.clone().into()`, which allocated twice per visible line, every frame. - `text`: Use `sort_unstable_by_key` in operation queue insertion — Lamport timestamps are unique keys and duplicates are deduped right after, so stability buys nothing. - `multi_buffer`: Sort with an explicit comparator instead of `sort_unstable_by_key`, which cloned a `PathKey` (`Arc` refcount bump) on every comparison. - `worktree`: Replace O(n²) `Vec::remove` in the deferred-directory pass with an O(1) `None` assignment — the vec is already `Vec<Option<ScanJob>>` and is consumed with `.flatten()`. ## Testing - No behavior changes intended; all changes are mechanical and tests affected crates pass: `text`, `editor`, `multi_buffer`, `worktree`. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable --- Release Notes: - Improved editor performance through several micro-optimizations in anchor resolution, line shaping, and worktree scanning. |
||
|
|
23ee3ba37d |
project_panel: Add remote support for undo/redo system (#59709)
# Objective Add remote (SSH) and collaboration support for trashing and restoring files in the project panel, which in turn enables undo/redo of trash operations against remote and collab projects. Relates to #5039. ## Solution - Updated the project panel undo system to carry `TrashId` instead of `TrashedEntry`. - Using `TrashedEntry` could get hairy, as it includes paths, which wouldn't play too nicely when using, for exapmle, macOS as the client and Windows as the host. Using a simple identifier is much easier in this regard and simplifies implementation. - Enabled the Trash action and context-menu entry on remote projects, and removed the command palette filter in `ProjectPanel::new` that was still hiding the action on remote. - As far as I can tell, there isn't a reliable way to detect whether a given remote actually supports the OS trash, so we expose the action everywhere rather than guessing. On a remote without trash support the action will fail when invoked but this is a conscious tradeoff until we find a better way to handle this. - `fs` now tracks trashed files in a `SlotMap<TrashId, TrashedEntry>` on each `Fs` implementation. Trashed files are referenced by an opaque `TrashId` instead of passing a `TrashedEntry` around, which avoids serializing filesystem paths in remote messages. - Split the old `delete_entry(trash: bool)` API into distinct `trash_entry`/`trash_file` (returning a `TrashId`) and `delete_entry`/`delete_file` across `Project`, `Worktree`, `LocalWorktree` and `RemoteWorktree`. - This lets us drop the optional trash result (`Option<TrashedEntry>`) from the delete path and require a `TrashId` from the trash path. - Added new proto messages (`TrashProjectEntry`, `TrashProjectEntryResponse`, `RestoreProjectEntry`, `RestoreProjectEntryResponse`) to let clients request the host to trash or restore entries. - This deprecates `DeleteProjectEntry::use_trash`, but the host still honors it. An older collab peer may request trashing via that flag instead of the newer `TrashProjectEntry`. If the host ignored it, a newer host would permanently delete a file the user meant to send to the trash. The field will be removed in a later PR once all supported peers use `TrashProjectEntry`. ## Testing The following tests were introduced to ensure the new behavior is correctly tested: * `remote_server::remote_editing_tests::test_remote_trash_restore` – Tests trashing a project entry in remote * `remote_server::remote_editing_tests::test_remote_delete_project_entry_with_trash` – Test to ensure we continue respecting `DeleteProjectEntry::use_trash` until it is fully removed * `project_panel::tests::undo::trash_directory_undo_redo` – Not related to these changes but a nice to have as we were missing a test ensuring that trashing and then undoing and redoing it for a directory works as expected Besides these, the following scenarios were manually tested against a remote session on the same machine (macOS): - Trashing → Undo (Restore) → Redo (Trashing) - Batch Trashing → Undo (Batch Restore) → Redo (Batch Trashing) - Rename → Undo (Rename) → Redo (Rename) - Move → Undo (Move) → Redo (Move) - Batch Move → Undo (Batch Move) → Redo (Batch Move) ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [ ] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Release Notes: - N/A --------- Co-authored-by: Yara <git@yara.blue> |
||
|
|
6b6393fb0b |
Split out RelPath into a separate crate (#61029)
This is necessary to remove some `util` dependencies from crates, as well as better sharing for our projects. This also includes the WIP AbsPath abstraction as well as some bug fixes from internal tooling. Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
b4018f4c7e |
Open gitignored subdirectories as their own workspace (#60918)
# Objective Let's git ignored directories be opened as their own project ## Solution - Add an "ignored dir" carve out when checking project collision ## Testing - Added tests ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [-] Unsafe blocks (if any) have justifying comments - [-] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [-] Performance impact has been considered and is acceptable --- Release Notes: - |
||
|
|
bfc278bee0 |
search: Fix ignored file search in nested Git directories (#60772)
# Objective - Fix ignored file search in nested Git directories (even just empty `.git` directories, not real git repositories) - Fixes #52328 ## Solution Keep parent ignore rules when rebuilding a nested repository's ignore stack. This hides root-ignored files again after excluded-file search is turned off, without breaking global ignore handling. For example: ```ascii project/ ├── .git/ ├── .gitignore # log/ ├── app/ │ └── a.txt # hello └── log/ ├── .git/ # nested repository marker └── b.txt # hello ``` Both `a.txt` and `b.txt` have string `hello`. Initially, searching for `hello` returns only `a.txt`. Enabling `Also search files ignored by configuration` rescans `log/` and returns both files. Before this change, disabling the option still returned both files because the rescan dropped the parent `.gitignore` and marked `b.txt` as included. ## Testing - Did you test these changes? If so, how? To test changes in this pull request create a simple project with the following dir structure: ``` .git .gitignore a/a.txt b/b.txt b/.git # this is an empty directory ``` Add `b` folder as an ignore entry to the `.gitignore` file: `b/` - Are there any parts that need more testing? No - How can other people (reviewers) test your changes? Is there anything specific they need to know? Use the test scenario above - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? macOS ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase By using the structure above here is how it works before changes here: https://github.com/user-attachments/assets/2028123e-388e-4390-b131-ddf4642ab5f3 Notice that `hello` string from file `b.txt` is listed in search results regardless of the option `Include excluded files` And here is after: https://github.com/user-attachments/assets/99c627a2-e16a-4fdd-979b-2e0bacbd827d Notice that `hello` string from file `b.txt` is **not** listed in search results when the option `Include excluded files` is disabled. Release Notes: - Fixed ignored file search in nested Git directories |
||
|
|
4e5b6c6b70 |
worktree: Watch .git/refs subdirectories for external ref updates (#60660)
On Linux and FreeBSD the native file watcher is non-recursive, so a watch on the .git directory itself does not report changes to files nested below it. Loose refs live in nested directories under refs, so external git commit, fetch, branch, and update-ref operations that don't also touch a direct child of .git (like the index) went entirely unnoticed. Watch every directory in the refs tree when a repository is inserted, and watch directories subsequently created under refs (new remotes, slash-named branches) as their creation events arrive. On platforms with recursive watchers these registrations dedupe against the existing recursive watch, making them free. --- Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
fb4885a55e |
Open non-writeable files in Capability::Read mode (#57202)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #57174 Release Notes: - Open non-writeable files in Capability::Read mode Co-authored-by: Lukas Wirth <lukas@zed.dev> |
||
|
|
be9f38a892 |
worktree: Refresh all repositories sharing a changed git directory (#60664)
update_git_repositories mapped a changed .git path to a repository with find_map, so when several repositories share a git directory - a main checkout plus one of its linked worktrees in the same project worktree - a ref update under the shared common dir only bumped git_dir_scan_id on whichever repository iterated first, leaving the others stale until an unrelated event happened to refresh them. Collect every matching repository and bump each one. --- Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
7e786c264c |
Fix worktree entry IDs for symlinked files (#57846)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #55792 Release Notes: - Fixed files in pnpm workspaces moving to symlinked `node_modules` paths after saving. --------- Co-authored-by: Kirill Bulatov <kirill@zed.dev> |
||
|
|
f023a7e4a3 |
Fix worktree grouping for bare checkouts (#59968)
Summary - Track whether a worktree root is itself a linked Git worktree. - Use that metadata when computing project group keys so bare checkout worktrees group under the repository identity path. - Propagate the metadata through remote worktree protocols and add local/remote regression coverage. Background Bare checkout layouts can place linked worktrees under the repository identity directory, e.g. `/monty/.bare` with worktrees like `/monty/feature-a`. We were treating those linked worktree paths as separate project identities, which caused the sidebar to move agent threads under the active worktree instead of the shared repository group. We also exclude adding this to collab intentionally, we can open a different PR for that if we need to. Closes #59910 Closes AI-431 Test Plan - `cargo fmt --package project --package worktree --package remote_server --package workspace --package collab --package proto` - `git --no-pager diff --check` - `cargo test -p project test_project_group_key -- --nocapture` - `cargo test -p remote_server test_remote_root_repo_common_dir -- --nocapture` - `cargo test -p worktree remote_worktree -- --nocapture` - `cargo test -p workspace test_remote_project_root_dir_changes_update_groups -- --nocapture` - `cargo check -p collab` Self-Review Checklist: I've reviewed my own diff for quality, security, and reliability Unsafe blocks (if any) have justifying comments The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Tests cover the new/changed behavior Performance impact has been considered and is acceptable Release Notes: - Fixed agent thread/sidebar grouping for Git worktrees backed by bare checkouts. --------- Co-authored-by: Anthony Eid <anthony@zed.dev> |
||
|
|
32a5d2b217 |
worktree: Avoid dropping git repositories during watcher rescans (#59976)
Related to #59610. # Objective When the filesystem watcher loses sync (common on macOS under heavy churn, e.g. a dev build constantly rewriting `target/` and `.git/`), it forces a recursive rescan of the worktree root. That rescan removes the whole subtree from the snapshot before re-scanning it, and `remove_path_from_snapshot` was unconditionally pruning the worktree's git repositories along with it. Because the scanner publishes intermediate snapshots while it works, a snapshot could be published in the window after the repository was pruned but before `.git` was re-scanned. The `GitStore` would see the repository as removed, tear it down, and then re-create it with a fresh `RepositoryId` once it reappeared — churning the id on every watcher overflow and spamming `RepositoryUpdated` events to all consumers (git panel, git graph, blame, etc.). Here some debug logs, **See** that the **repoId** inside the git graph event is different and is **8** now, even though I only have one repository and didn't do any git related updates. ``` 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for Native; scheduling rescans for 11 registrations 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 WARN [fs::fs_watcher] filesystem watcher lost sync for many files, not logging more 2026-06-26T18:38:44+02:00 INFO [git::repository] opening git repository at "/Users/remcosmits/Documents/code/zed/.git" using git binary "/opt/homebrew/bin/git" 2026-06-26T18:38:44+02:00 ERROR [crates/git_ui/src/git_panel.rs:3892] oneshot canceled 2026-06-26T18:38:44+02:00 ERROR [crates/git_ui/src/git_panel.rs:3892] oneshot canceled 2026-06-26T18:38:44+02:00 ERROR [crates/git_ui/src/git_panel.rs:3892] oneshot canceled 2026-06-26T18:38:44+02:00 ERROR [crates/git_ui/src/git_panel.rs:3892] oneshot canceled 2026-06-26T18:38:44+02:00 ERROR [crates/zed/src/main.rs:1991] Is a directory (os error 21) 2026-06-26T18:38:44+02:00 INFO [project::prettier_store] Prettier config file ".prettierrc" changed, reloading prettier instances for worktree 1 2026-06-26T18:38:45+02:00 INFO [project::prettier_store] Prettier config file ".prettierrc" changed, reloading prettier instances for worktree 1 2026-06-26T18:38:45+02:00 INFO [git::repository] opening git repository at "/Users/remcosmits/Documents/code/zed/.git" using git binary "/opt/homebrew/bin/git" 2026-06-26T18:38:45+02:00 ERROR [crates/git_ui/src/git_panel.rs:3892] oneshot canceled 2026-06-26T18:38:45+02:00 ERROR [crates/git_ui/src/git_panel.rs:3892] oneshot canceled [crates/git_ui/src/git_graph.rs:1468:21] &this.repo_id = RepositoryId( 1, ) [crates/git_ui/src/git_graph.rs:1468:21] "other repo id" = "other repo id" [crates/git_ui/src/git_graph.rs:1468:21] &updated_repo_id = RepositoryId( 8, ) [crates/git_ui/src/git_graph.rs:1468:21] &this.repo_id = RepositoryId( 1, ) [crates/git_ui/src/git_graph.rs:1468:21] "other repo id" = "other repo id" [crates/git_ui/src/git_graph.rs:1468:21] &updated_repo_id = RepositoryId( 8, ) [crates/git_ui/src/git_graph.rs:1468:21] &this.repo_id = RepositoryId( 1, ) [crates/git_ui/src/git_graph.rs:1468:21] "other repo id" = "other repo id" [crates/git_ui/src/git_graph.rs:1468:21] &updated_repo_id = RepositoryId( 8, ) [crates/git_ui/src/git_graph.rs:1468:21] &this.repo_id = RepositoryId( 1, ) ``` ## Solution This change makes `remove_path_from_snapshot` prune git repositories only when the path was genuinely removed (`metadata == Ok(None)`), not during a recursive refresh where the subtree is about to be re-scanned. Stale repositories are still reaped authoritatively against the filesystem in `update_git_repositories`. ## Testing It seems to be that I'm the only that can reproduce this issue @Anthony-Eid tried reproducing this but couldn't. **Note**: that I dindn't write a regression test since this is a async timing issue that I couldn't figure out to write a test for. Steps how I can reproduce this: 1. Run `cargo run` 2. Open `Zed` as only project 3. Open the git graph 4. Open a rust file e.g. `git_graph.rs` 5. CTRL-C inside the terminal to kill Zed 6. Run `cargo run` see that you have git graph open and a rust file, note that cargo check is doing it's thing. 7. See within a few seconds that Zed's UI flickers (especially the project panel & nav bar with the selected repo & branch) ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase **Note**: This PR only fixes that we don't send as many git store events, so this results in not having to update the nav bar where the selected repo & branch on every event (that is duplicated in a way). Result of that we now also fixed a rare case that the git graph commit entries where gone, this was because we incremented the **repoId** and the graph couldn't find the repo anymore with the id that it has stored on the gitGraph struct itself. **Before** See that the nav bar with selected repo & branch flickers and the git graph commits are empty. https://github.com/user-attachments/assets/0957be7f-e732-4fd0-a950-29c496b6407d See that the git panel entries flicker and we have an temporary empty panel. https://github.com/user-attachments/assets/3b70e45c-c720-4009-aefa-696986d731b4 **After** See that the nav bar with selected repo & branch does not flicker anymore and that the git graph keeps showing the commits. https://github.com/user-attachments/assets/6e8a74f6-4a8e-4b28-ad30-574c2f33c6d9 See that the git panel does not show an empy state and does not flicker anymore. https://github.com/user-attachments/assets/1df7aacf-b337-4b81-b195-e67d8554d9da --- cc @Anthony-Eid Since we where debugging this yesterday. Release Notes: - Fixed git repositories being repeatedly torn down and re-created when the filesystem watcher forced a rescan, which caused redundant git status refreshes and UI churn. |
||
|
|
45e3602c78 |
Allow file watchers to handle case insensitive file systems (#59579)
## Goal This PR fixes a bug in our file system watcher. Because it matched paths case sensitively, it didn't account for file systems that are case insensitive by default (macOS, Windows, etc.). As a result, when multiple subscribers watched the same path using different casing, Zed could fail to emit file system events to some of them. ### Reproduction I reproduced this with the `tsgo` LSP, which lowercases the file path of the visible worktree root it runs in. Zed subscribes to worktree roots to receive FS updates — e.g. external edits to a buffer, or git state changes — but it doesn't normalize the path when subscribing, so the two casings never matched. ### Fix Fixing this took longer than expected, because I spent a while deciding on an approach. I considered three: - **Follow VS Code's lead:** always treat macOS/Windows as case insensitive and Linux as case sensitive. Simple, but it would leave a couple of bugs. - **Real case the path at registration:** walk each component and use syscalls to rewrite it to match what the file system shows the user (e.g. Finder shows `/Project/some`, so a request to watch `/project/some` becomes `/Project/some`). This had rough edge cases with symlinks that I didn't want to deal with. - **Detect via syscalls whether a path is on a case-insensitive (normalizing) file system and match accordingly** — what I went with. The one wrinkle is that Windows can mark individual directories case-sensitive… because Windows. I also added integration tests to prevent future regressions. Note: Windows currently defaults to case insensitive; implementing the actual case sensitivity check for it is left to a follow up PR. Helps #38109 #35861 #52376 and maybe #41195 ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed missed file system events on case-insensitive filesystems that could cause stale git state and other sync issues --------- Co-authored-by: Cole Miller <cole@zed.dev> |
||
|
|
5bdcb12042 |
Fix project grouping for Git repo subdirectories (#57998)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - No unsafe blocks added. - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - No new UI components; behavior better matches user intent for opened folders. - [x] Tests cover the new/changed behavior - Added sibling-subdirectory project group regression coverage. - Extended subfolder Git-status test to ensure Git still uses the parent repo while project identity stays at the opened folder. - [x] Performance impact has been considered and is acceptable - Change adds one small enum/optional field check when computing worktree paths; no meaningful performance impact expected. Closes #57997 Release Notes: - Fixed project grouping for opened subdirectories that share the same parent Git repository. ## Screenshots ### Before <img width="334" height="224" alt="Screenshot 2026-05-28 at 5 29 55 PM" src="https://github.com/user-attachments/assets/ad5b13c5-11a7-4fa4-a074-a519521641da" /> <img width="485" height="201" alt="Screenshot 2026-05-28 at 5 28 36 PM" src="https://github.com/user-attachments/assets/9cd2c138-92f5-4ff2-bf8f-21cdbeff0b79" /> ### After <img width="343" height="253" alt="Screenshot 2026-05-28 at 5 29 40 PM" src="https://github.com/user-attachments/assets/56a4dca7-f0a1-4530-8c89-3c4773b90486" /> <img width="420" height="206" alt="Screenshot 2026-05-28 at 5 29 22 PM" src="https://github.com/user-attachments/assets/d118340a-955e-4483-9888-4b566f59b931" /> --------- Co-authored-by: Anthony Eid <anthony@zed.dev> Co-authored-by: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com> |
||
|
|
09415bf9e5 |
Include changed paths in remote UpdatedEntries events (#58157)
Include the changed paths in `UpdatedEntries` events emitted by remote worktrees. Previously a remote worktree emitted `Event::UpdatedEntries` with an empty changeset (`Arc::default()`), discarding the changed paths. The changeset now carries the real added/updated/removed paths, resolving removed entries against the previous snapshot. Release Notes: - Fixed file change events not reporting changed paths in remote projects |
||
|
|
cdf9f6ff18 |
git: Avoid unnecessary git repo rescans when unrelated git files change (#59318)
# Objective
Zed triggers many git rescans whenever an outside git command modifies
files inside `.git` dir. This becomes especially problematic when
working on large repos or doing remote development on machines with slow
filesystems.
## Solution
Events for object writes, hook files, lock files, and the reflogs of
HEAD/branches/remote-tracking branches carry no git changes that Zed
cares about beyond what the ref or events already cover. So changes to
these files shouldn't trigger a full git rescan.
## Testing
I extended the existing unittests to add the additionally ignored
directories and lock files.
I also manually verified the changes by viewing the zed git debug logs
that get generated when running `git gc` on a freshly gc'ed repo.
Previously Zed triggered **7 worktree updates**, with these changes it
was reduced to **a single worktree update** which is due to
`.git/packed-refs` which we can't ignore.
**main:**
```
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:52+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:52+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:53+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:53+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:54+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:55+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-13T13:56:55+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] fetched remotes
2026-06-13T13:56:56+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] load merge details
2026-06-13T13:56:56+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }
```
**This PR:**
```
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] received worktree update for repositories: [UpdatedGitRepository { work_directory_id: ProjectEntryId(0), old_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), new_work_directory_abs_path: Some("/Users/lgeiger/code/zed"), dot_git_abs_path: Some("/Users/lgeiger/code/zed/.git"), repository_dir_abs_path: Some("/Users/lgeiger/code/zed/.git"), common_dir_abs_path: Some("/Users/lgeiger/code/zed/.git") }]
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] local worktree repos changed
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] run scheduled git status scan
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] starting compute snapshot
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] fetched branches, head commit, worktrees
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] fetched remotes
2026-06-15T01:19:51+01:00 DEBUG [git::repository] Checking for git status in [""]
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] fetched statuses, diff stats, stash entries
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] load merge details
2026-06-15T01:19:51+01:00 DEBUG [project::git_store] new merge details: MergeDetails { merge_heads_by_conflicted_path: {}, message: None }```
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Reduced number of git operations when repository state changes outside of zed
|
||
|
|
cb06458cf8 |
git: Fix .git directory being removed from watcher when excluded via file_scan_exclusions (#57895)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #57888 Commit `c3f05a7060d75eae1b168434d299389f5fcdbdf2` introduced the bug on #50412 . This change modified the `remove_path` function to also remove the path from the watcher: https://github.com/zed-industries/zed/blob/356c8cae072a0288da786b5ac010ce3f0d532ea1/crates/worktree/src/worktree.rs#L3218-L3220 And when a user modified the global setting and doesn't include `.git` in it, like: ```jsonc // ~/.config/zed/settings.json { "file_scan_exclusions": ["foo"] } ``` But then includes it on their local project settings: ```jsonc // ~/my/local/project/.zed/settings.json { "file_scan_exclusions": ["**/.git"] } ``` It causes zed to stop watching for changes on `.git` Release Notes: - Fixed bug where zed stopped watching change on `.git` directory if it was added to the project local `file_scan_exclusions` |
||
|
|
423d5b64b5 |
multi_buffer: Don't eagerly clone BufferSnapshot in range_to_buffer_ranges (#59190)
Both cloning and dropping of these has quite a bit of overhead (despite them being snapshots), so avoid where possible, especially in display map syncing Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
23237ac456 |
Improve didChangeWatchedFiles handler performance (#59078)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A --------- Co-authored-by: John Tur <john-tur@outlook.com> Co-authored-by: Ben Kunkle <ben@zed.dev> |
||
|
|
5fa0f1787b |
Fix stale Git UI on reftable repositories on Linux (#58719)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable The non-recursive Linux watcher causes subdirectories inside `.git/` to need explicit watching. For repos using the reftable backend, all ref data lives in `.git/reftable/`. Operations in the UI like uncommitting and creating new branches only modify refs inside `.git/reftable` without changing `.git/HEAD`'s contents, so no inotify event fires on `.git/` itself and the git UI never refreshes. Essentially all this change does is check if `.git/reftable/` exists and if it does, add it to the watcher. On the recursive macOS/Windows watchers, `FsWatcher::add` returns early safely so this *should* not be a performance loss apart from the brief lookup. Release Notes: - Fixed Git UI not refreshing on Linux for repositories using the reftable backend. |
||
|
|
d124bd296b |
worktree: Don't eagerly remove watchers (#58692)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #ISSUE Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
439d0bf281 |
Fix symlinked root rename event handling (#58624)
Fixes #58619. When a worktree is opened through a symlinked root, filesystem events can arrive rooted at either the opened symlink path or the canonical target path. The worktree event processing path already handled canonical target paths, but dropped events reported under the opened symlink root because it only derived relative paths from the canonical root. This PR adds a regression test that opens `/link -> /target`, renames `/link/subdir-a` to `/link/subdir-aa`, and verifies `subdir-aa/config.ini` remains visible in the worktree. The production fix accepts event paths under the opened worktree root as a fallback when deriving relative paths. Testing: - Verified the new regression test fails with only the test commit applied. - `cargo test -p worktree --test integration test_renaming_subdir_under_symlinked_root_keeps_children` - `cargo test -p worktree --test integration test_symlinks_pointing_outside` |
||
|
|
f00bcae75e |
Symlink scan option (#53646)
Adds option to always search/scan symlinks for more thorough coverage of #41887 issue This is a significant rewrite and more thoroughly reviewed and tested version of the old PR here: https://github.com/zed-industries/zed/pull/46344 The "never" option was removed from the old PR, since "expanded" is now the default. Perhaps "never" can be added as an option later if there's demand for it. Adding that option may resolve #48890 for instance. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable (significant impact with "always" option, but "expanded" is default) Release Notes: - Add option choose between including expanded symlinks or include all symlinks in project search (#41887) --------- Co-authored-by: Eric Holk <eric@zed.dev> |
||
|
|
c0c2df9c97 |
worktree: Fix linked worktree git dir event handling (#57782)
When a linked worktree receives fs events for its .git directory, the event path resolves to the per-worktree git dir (e.g. main_repo/.git/worktrees/<name>), not the .git directory itself or the common dir. The existing match only checked common_dir_abs_path and repository_dir_abs_path, causing the repository entry to be missed and then removed as stale. Add dot_git_abs_path to the match, and fix the staleness metadata check to use dot_git_abs_path (the actual .git entry) rather than common_dir_abs_path (which may be outside the worktree root). Extracted from https://github.com/zed-industries/zed/pull/53453 Release Notes: - N/A or Added/Fixed/Improved ... --------- Co-authored-by: Kieran Freitag <kfreitag@kieran.ca> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
3c347c9dc4 |
Honor anchored patterns in .git/info/exclude (#57779)
Patterns in `.git/info/exclude` that contain a slash (e.g. `.claude/worktrees`) are anchored: Git matches them relative to the project root. Zed was instead matching them relative to the `.git/info/` directory that the file lives in, so they matched nothing and had no effect. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Support anchored patterns in .git/info/exclude --------- Co-authored-by: Cole Miller <cole@zed.dev> Co-authored-by: zed-zippy[bot] <234243425+zed-zippy[bot]@users.noreply.github.com> |
||
|
|
f43794ddc0 |
Fix the filtering of index.lock + COMMIT_MESSAGE FS events to work in linked worktrees (#57763)
Zed reloads a lot of data about a git repository any time any file changes inside of the `.git` directory, with the exception of a few known paths that we know do not warrant a reload, such as `index.lock` and `COMMIT_MESSAGE`. Previously, we ignored FS events for those files, but we used a specific path that only worked for the main worktree. This caused a lot of unnecessary reloads when using linked worktrees. Now we ignore those files in a general way, by their filename, so that the optimization applies to linked worktrees as well. @cole-miller Noticed this bug. Release Notes: - Fixed unnecessary reloading of Git state that could occur when editing in linked worktrees. |
||
|
|
16ede263e4 |
git: Degrade gracefully when refreshing git state (#57292)
This PR changes the git store's `compute_snapshot`, which runs to update state that depends on the contents of `.git`, to degrade gracefully when fetching individual pieces of state fails. For example, when fetching the list of branches fails, instead of returning early from the function (leaving the previous git state snapshot in place with stale state), we continue with an empty list of branches. This prevents failures of individual git commands from making the entire git UI get stuck indefinitely. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #ISSUE Release Notes: - Fixed an issue where failing to fetch branches using the git CLI would prevent other git-related state from being updated. |
||
|
|
23f5b1cd75 |
Add some more logging to diagnose lost FS events and stale git state (#57173)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A --------- Co-authored-by: Ben Kunkle <ben@zed.dev> |
||
|
|
edf9271686 |
fs: Defer initializing poll watcher until after initial worktree scan (#56207)
Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Closes #56021 Closes #56100 Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
f0bdd3c4af |
Skip Git tracking for invisible worktrees (#55760)
Release Notes: - N/A or Added/Fixed/Improved ... |
||
|
|
1deb935c77 |
Fix handling of git repositories with an external git directory (#55402)
Closes https://github.com/zed-industries/zed/issues/54824 Previously, we always assumed that `gitdir` was an absolute path. Also, we did not correctly handle custom gitignore files that were configured via separate git directories. Release Notes: - Fixed failure to recognize git repositories where `gitdir` was expressed as a relative path. - Fixed handling of gitignores in git repositories that use a separate git dir. |
||
|
|
e4774ea2dc |
Respect .git/info/exclude in secondary worktrees (#51536)
Closes #50880 When a git worktree linked via a `.git` file (e.g. `gitdir: /repo/.git/worktrees/my-worktree`) was opened in Zed, entries in `.git/info/exclude` were not respected. This is now fixed. Before you mark this PR as ready for review, make sure that you have: - [x] Added a solid test coverage and/or screenshots from doing manual testing - [x] Done a self-review taking into account security and performance aspects - [x] Aligned any UI changes with the [UI checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) Release Notes: - Fixed `.git/info/exclude` not being respected when opening a secondary git worktree https://github.com/user-attachments/assets/f38df5dc-96eb-40a8-a77c-0932a2c8575b --------- Co-authored-by: Lukas Wirth <lukas@zed.dev> Co-authored-by: Lukas Wirth <me@lukaswirth.dev> |