Cherrypick/fix misc bugs 8
Objective
- Describe the objective or issue this PR addresses.
- If you're fixing a specific issue, use "Fixes #X" for each issue as described in the GitHub docs.
Solution
- Describe the solution used to achieve the objective above.
Testing
- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything specific they need to know?
- If relevant, what platforms did you test these changes on, and are there any important ones you can't test?
Self-Review Checklist:
- 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 and icon guidelines)
- Tests cover the new/changed behavior
- Performance impact has been considered and is acceptable
Showcase
This section is optional. If this PR does not include a visual change or does not add a new user-facing feature, you can delete this section.
- Help others understand the result of this PR by showcasing your awesome work!
- If this PR includes a visual change, consider adding a screenshot, GIF, or video
- A before/after comparison is very useful for changes to existing features!
While a showcase should aim to be brief and digestible, you can use a toggleable section to save space on longer showcases:
Click to view showcase
My super cool demos here
Release Notes:
- N/A or Added/Fixed/Improved ...
[!NOTE]
High Risk
Large fs-watcher concurrency/state-machine changes can miss or duplicate FS events if wrong, and read-only project policy touches save/edit paths across editor, project, and panel.
Overview
This PR bundles reliable file watching, read-only local projects for embedders, and several host/UI hooks.
File watching adds Watcher::add_and_wait and reworks the global watcher so OS watches can be awaited without blocking callers on slow FSEvents work (macOS queues on a dedicated thread; other modes apply inline). Worktree/git/external paths now wait for watches before trusting the tree, batch deferred watches, handle failed registrations with rollback and promotion when a covering ancestor is removed, and expose readiness via oneshot waiters shared across duplicate adds.
Read-only projects introduce Project::set_local_read_only / buffer-store force_read_only: saves and filesystem mutations are refused, dirty buffers stay dirty as Read (not silently “clean”), per-file unlock is blocked when the project is read-only, and the project panel skips create/rename/delete/paste/undo/git restore/drops.
Other embedder-facing changes: project panel set_name_validator with inline errors; commit diff binary before/after cards (images + sizes, capped); buffer search embedded layout and focus_query_editor; workspace set_manages_window_title and public notification_stack.
Reviewed by Cursor Bugbot for commit c5a1d6959899dde3467c60b59b53838ef9391bce. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Cherry-picks a set of fixes: makes FSEvents file watching reliable, prevents missed changes, and adds support for read-only local projects plus several embedder-facing improvements.
File watching
- FSEvents watch and unwatch commands queue on a dedicated watcher thread, so callers never block behind slow
fseventsd. - A new
add_and_waitresolves once a watch is in place; the worktree scanner awaits it for linked worktrees and external paths it depends on, so no change is missed after a scan. - Deferred worktree watches (external symlink targets, git dirs) are all queued before any is awaited, batching them into one FSEvents restart.
- Registration changes publish their commands in order, so an unwatch never overtakes the watch it follows.
- A second
add_and_waitfor a path a queued command or a queued ancestor covers waits for the nearest covering watch; a vanished registration is reported separately so callers register again, a poll task claiming a path that has just appeared gets time to register before the wait, and a path still unclaimed past the deadline times out instead of succeeding. - Failed watch registrations are rolled back: their covering records (and every registration they covered) are unregistered, so owners retry with a watch of their own unless another live watch still covers the path.
- Removing an ancestor watch promotes the covered registrations nothing else covers to their own OS watch, shortest first; promoted watches stay pending until applied and go in before the ancestor is released.
- If the watch a path was waiting on is released before it is applied,
add_and_waitrechecks that path's own registration and waits for it. - External directories are recorded as watched only after their watch succeeds.
- A failed FSEvents backend creation is retried on the next watch instead of caching the failure.
- A partially applied watch batch no longer reads past its failing operation.
Embedders and read-only projects
Project::set_local_read_onlymarks a local project read-only (a UI policy for projects on a read-only filesystem): buffers with unsaved edits become read-only but stay dirty (so closing still asks), saves are rejected (includingsave_buffer,save_buffer_as,restore_entry, code actions, renames, and Discard Changes), autosave stays quiet, per-file toggling back is blocked, and every buffer added afterwards becomes read-only.- The project panel adds a host-supplied name validator (using the project's path style) and disables entry-creating, renaming, copy, paste, delete, undo/redo, and file drops on read-only projects.
- Commit diff preview renders binary files as before/after cards (with image previews and sizes) instead of placeholder text; cards past the cap are counted, not held.
- The search bar gains an embedded mode and
focus_query_editor(the embedded replace row wraps); workspaces can stop managing the window title (re-enabling rewrites it) and expose their toast stack.
Summary by CodeRabbit
- New Features
- Commit previews show binary files as before-and-after cards, with image previews and file sizes when available. Additional binary files are counted when they exceed the preview limit.
- Project panels validate names as they’re entered and show inline errors for rejected names.
- Embedded search bars adapt to available toolbar space and support focusing the query field. Workspaces can leave window-title management to their host and expose their notification stack.
- Improvements
- Read-only projects block saving changes and file actions such as renaming, creating, restoring, or deleting files. Explicit saves report an error when edits are unsaved; autosaves leave them unchanged, and read-only buffers remain read-only.
- File watching waits for registration to complete for project, repository, and external paths.