diff --git a/crates/project/src/worktree_store.rs b/crates/project/src/worktree_store.rs index 4b1764c3a87fa1a2b20c1404ddaacb1265ce7935..e445eab2dd6392c953522e4fda368489c5dcc021 100644 --- a/crates/project/src/worktree_store.rs +++ b/crates/project/src/worktree_store.rs @@ -18,7 +18,7 @@ use gpui::{ use postage::oneshot; use rpc::{ proto::{self, SSH_PROJECT_ID}, - AnyProtoClient, TypedEnvelope, + AnyProtoClient, ErrorExt, TypedEnvelope, }; use smol::{ channel::{Receiver, Sender}, @@ -207,7 +207,7 @@ impl WorktreeStore { cx.background_executor().spawn(async move { match task.await { Ok(worktree) => Ok(worktree), - Err(err) => Err(anyhow!("{}", err)), + Err(err) => Err((*err).cloned()), } }) } diff --git a/crates/remote_server/Cargo.toml b/crates/remote_server/Cargo.toml index ed12b41167cc230ff625435dc1b14f515945f724..64db2616e9b2f8078f61f5da6853f0173ea9c8e2 100644 --- a/crates/remote_server/Cargo.toml +++ b/crates/remote_server/Cargo.toml @@ -22,6 +22,7 @@ test-support = ["fs/test-support"] [dependencies] anyhow.workspace = true +client.workspace = true env_logger.workspace = true fs.workspace = true futures.workspace = true diff --git a/crates/remote_server/src/headless_project.rs b/crates/remote_server/src/headless_project.rs index 0af0d6bb1570dda0a39278eb57bf4c043c9c7ddd..84fb22b282d37d3fe1e212ee488983563f6be7e2 100644 --- a/crates/remote_server/src/headless_project.rs +++ b/crates/remote_server/src/headless_project.rs @@ -189,11 +189,34 @@ impl HeadlessProject { message: TypedEnvelope, mut cx: AsyncAppContext, ) -> Result { + use client::ErrorCodeExt; let path = shellexpand::tilde(&message.payload.path).to_string(); + + let fs = this.read_with(&mut cx, |this, _| this.fs.clone())?; + let path = PathBuf::from(path); + + let canonicalized = match fs.canonicalize(&path).await { + Ok(path) => path, + Err(e) => { + let mut parent = path + .parent() + .ok_or(e) + .map_err(|_| anyhow!("{:?} does not exist", path))?; + if parent == Path::new("") { + parent = util::paths::home_dir(); + } + let parent = fs.canonicalize(parent).await.map_err(|_| { + anyhow!(proto::ErrorCode::DevServerProjectPathDoesNotExist + .with_tag("path", &path.to_string_lossy().as_ref())) + })?; + parent.join(path.file_name().unwrap()) + } + }; + let worktree = this .update(&mut cx.clone(), |this, _| { Worktree::local( - Path::new(&path), + Arc::from(canonicalized), true, this.fs.clone(), this.next_entry_id.clone(), diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 4d656294703d424bae54e74b275af7175f9dffcc..cec913851f04df1fcafa99a9bf8631b284f3c9bd 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -5544,12 +5544,21 @@ pub fn open_ssh_project( ) })?; + let mut project_paths_to_open = vec![]; + let mut project_path_errors = vec![]; + for path in paths { - project - .update(&mut cx, |project, cx| { - project.find_or_create_worktree(&path, true, cx) - })? - .await?; + let result = cx + .update(|cx| Workspace::project_path_for_path(project.clone(), &path, true, cx))? + .await; + match result { + Ok((_, project_path)) => { + project_paths_to_open.push((path.clone(), Some(project_path))); + } + Err(error) => { + project_path_errors.push(error); + } + }; } let serialized_workspace = @@ -5576,11 +5585,21 @@ pub fn open_ssh_project( .update(&mut cx, |_, cx| { cx.activate_window(); - open_items(serialized_workspace, vec![], app_state, cx) + open_items(serialized_workspace, project_paths_to_open, app_state, cx) })? .await?; - Ok(()) + window.update(&mut cx, |workspace, cx| { + for error in project_path_errors { + if error.error_code() == proto::ErrorCode::DevServerProjectPathDoesNotExist { + if let Some(path) = error.error_tag("path") { + workspace.show_error(&anyhow!("'{path}' does not exist"), cx) + } + } else { + workspace.show_error(&error, cx) + } + } + }) }) }