Fix path handling regressions on Windows (#48905)

John Tur created

https://github.com/zed-industries/zed/pull/48891 changed `find_worktree`
to use `PathStyle::strip_prefix`, which exposed this bug.

- [ ] Tests or screenshots needed?
- [X] Code Reviewed
- [X] Manual QA

Release Notes:

- N/A

Change summary

crates/util/src/paths.rs          | 12 +++++++++++-
crates/workspace/src/workspace.rs |  3 ++-
2 files changed, 13 insertions(+), 2 deletions(-)

Detailed changes

crates/util/src/paths.rs 🔗

@@ -428,7 +428,17 @@ impl PathStyle {
             .find_map(|sep| parent.strip_suffix(sep))
             .unwrap_or(parent);
         let child = child.to_str()?;
-        let stripped = child.strip_prefix(parent)?;
+
+        // Match behavior of std::path::Path, which is case-insensitive for drive letters (e.g., "C:" == "c:")
+        let stripped = if self.is_windows()
+            && child.as_bytes().get(1) == Some(&b':')
+            && parent.as_bytes().get(1) == Some(&b':')
+            && child.as_bytes()[0].eq_ignore_ascii_case(&parent.as_bytes()[0])
+        {
+            child[2..].strip_prefix(&parent[2..])?
+        } else {
+            child.strip_prefix(parent)?
+        };
         if let Some(relative) = self
             .separators()
             .iter()

crates/workspace/src/workspace.rs 🔗

@@ -8354,11 +8354,12 @@ pub async fn find_existing_workspace(
                             let project = workspace.project.read(cx);
                             let path_style = workspace.path_style(cx);
                             !abs_paths.iter().any(|path| {
+                                let path = util::paths::SanitizedPath::new(path);
                                 project.worktrees(cx).any(|worktree| {
                                     let worktree = worktree.read(cx);
                                     let abs_path = worktree.abs_path();
                                     path_style
-                                        .strip_prefix(path, abs_path.as_ref())
+                                        .strip_prefix(path.as_ref(), abs_path.as_ref())
                                         .and_then(|rel| worktree.entry_for_path(&rel))
                                         .is_some_and(|e| e.is_dir())
                                 })