# Allow file watchers to handle case insensitive file systems \(\#59579\) · gitcafe/zed

[View on GitCafe](https://git.cafe/gitcafe/zed/commit/6febe1c45a6d4b5460678a69b4eea497aa1f89ad)

Repository: [gitcafe/zed](https://git.cafe/gitcafe/zed)

Visibility: public

Requested revision: 6febe1c45a6d4b5460678a69b4eea497aa1f89ad

Requested commit: 6febe1c45a6d4b5460678a69b4eea497aa1f89ad

Commit: 6febe1c45a6d4b5460678a69b4eea497aa1f89ad

Tree: 104bcf95568af5e0f6d6b65c08734aed72552883

Author: Anthony Eid

Committer: GitHub

## Message

```
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>
```

## Parents

- [195760c6173e6a133192e497cff02c052890f8b1](https://git.cafe/gitcafe/zed/commit/195760c6173e6a133192e497cff02c052890f8b1?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zed/tree/6febe1c45a6d4b5460678a69b4eea497aa1f89ad?format=markdown)
