ssh: Handle `~` in ssh filenames (#17939)

Thorsten Ball and Conrad created

This allows users to open `ssh://user@host/~/my-home-dir-folder`.

Release Notes:

- N/A

Co-authored-by: Conrad <conrad@zed.dev>

Change summary

crates/project/src/worktree_store.rs | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)

Detailed changes

crates/project/src/worktree_store.rs 🔗

@@ -182,14 +182,23 @@ impl WorktreeStore {
         visible: bool,
         cx: &mut ModelContext<Self>,
     ) -> Task<Result<Model<Worktree>, Arc<anyhow::Error>>> {
-        let abs_path = abs_path.as_ref();
-        let root_name = abs_path.file_name().unwrap().to_string_lossy().to_string();
-        let path = abs_path.to_string_lossy().to_string();
+        let mut abs_path = abs_path.as_ref().to_string_lossy().to_string();
+        // If we start with `/~` that means the ssh path was something like `ssh://user@host/~/home-dir-folder/`
+        // in which case want to strip the leading the `/` and expand the tilde.
+        // That's what git does too: https://github.com/libgit2/libgit2/issues/3345#issuecomment-127050850
+        if abs_path.starts_with("/~") {
+            abs_path = shellexpand::tilde(&abs_path[1..]).to_string();
+        }
+        let root_name = PathBuf::from(abs_path.clone())
+            .file_name()
+            .unwrap()
+            .to_string_lossy()
+            .to_string();
         cx.spawn(|this, mut cx| async move {
             let response = client
                 .request(proto::AddWorktree {
                     project_id: SSH_PROJECT_ID,
-                    path: path.clone(),
+                    path: abs_path.clone(),
                 })
                 .await?;
             let worktree = cx.update(|cx| {
@@ -200,7 +209,7 @@ impl WorktreeStore {
                         id: response.worktree_id,
                         root_name,
                         visible,
-                        abs_path: path,
+                        abs_path,
                     },
                     client,
                     cx,