windows: Add support for SSH (#29145)

Closes #19892

This PR builds on top of #20587 and improves upon it.

Release Notes:

- N/A

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This commit is contained in:
张小白
2025-07-08 14:34:57 +00:00
committed by GitHub
co-authored by Kirill Bulatov
parent 8bd739d869
commit 0ca0914cca
26 changed files with 1435 additions and 354 deletions
+18 -11
View File
@@ -25,7 +25,10 @@ use smol::{
stream::StreamExt,
};
use text::ReplicaId;
use util::{ResultExt, paths::SanitizedPath};
use util::{
ResultExt,
paths::{PathStyle, RemotePathBuf, SanitizedPath},
};
use worktree::{
Entry, ProjectEntryId, UpdatedEntriesSet, UpdatedGitRepositoriesSet, Worktree, WorktreeId,
WorktreeSettings,
@@ -46,6 +49,7 @@ enum WorktreeStoreState {
Remote {
upstream_client: AnyProtoClient,
upstream_project_id: u64,
path_style: PathStyle,
},
}
@@ -100,6 +104,7 @@ impl WorktreeStore {
retain_worktrees: bool,
upstream_client: AnyProtoClient,
upstream_project_id: u64,
path_style: PathStyle,
) -> Self {
Self {
next_entry_id: Default::default(),
@@ -111,6 +116,7 @@ impl WorktreeStore {
state: WorktreeStoreState::Remote {
upstream_client,
upstream_project_id,
path_style,
},
}
}
@@ -214,17 +220,16 @@ impl WorktreeStore {
if !self.loading_worktrees.contains_key(&abs_path) {
let task = match &self.state {
WorktreeStoreState::Remote {
upstream_client, ..
upstream_client,
path_style,
..
} => {
if upstream_client.is_via_collab() {
Task::ready(Err(Arc::new(anyhow!("cannot create worktrees via collab"))))
} else {
self.create_ssh_worktree(
upstream_client.clone(),
abs_path.clone(),
visible,
cx,
)
let abs_path =
RemotePathBuf::new(abs_path.as_path().to_path_buf(), *path_style);
self.create_ssh_worktree(upstream_client.clone(), abs_path, visible, cx)
}
}
WorktreeStoreState::Local { fs } => {
@@ -250,11 +255,12 @@ impl WorktreeStore {
fn create_ssh_worktree(
&mut self,
client: AnyProtoClient,
abs_path: impl Into<SanitizedPath>,
abs_path: RemotePathBuf,
visible: bool,
cx: &mut Context<Self>,
) -> Task<Result<Entity<Worktree>, Arc<anyhow::Error>>> {
let mut abs_path = Into::<SanitizedPath>::into(abs_path).to_string();
let path_style = abs_path.path_style();
let mut abs_path = abs_path.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 `/`.
// On the host-side, the `~` will get expanded.
@@ -265,10 +271,11 @@ impl WorktreeStore {
if abs_path.is_empty() {
abs_path = "~/".to_string();
}
cx.spawn(async move |this, cx| {
let this = this.upgrade().context("Dropped worktree store")?;
let path = Path::new(abs_path.as_str());
let path = RemotePathBuf::new(abs_path.into(), path_style);
let response = client
.request(proto::AddWorktree {
project_id: SSH_PROJECT_ID,