ssh remoting: Show error message if project path does not exist (#18343)

This now shows an error message if you try open a project over SSH that
doesn't exist. If it's a possible file-path though, it acts like Zed's
`cli` and opens the file so that it can be created.

- Works: `cargo run ssh://127.0.0.1/~/folder-exists/file-does-not-exist`
— this will open `file-does-not-exist`
- Shows error: `cargo run
ssh://127.0.0.1/~/folder-does-not-exist/file-does-not-exist` — this will
show an error

Release Notes:

- N/A

Co-authored-by: Bennet <bennet@zed.dev>
Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
Thorsten Ball 2024-09-25 18:08:34 +02:00 committed by GitHub
parent 9300dbc834
commit 19162c3160
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 53 additions and 10 deletions

View file

@ -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()),
}
})
}

View file

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

View file

@ -189,11 +189,34 @@ impl HeadlessProject {
message: TypedEnvelope<proto::AddWorktree>,
mut cx: AsyncAppContext,
) -> Result<proto::AddWorktreeResponse> {
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(),

View file

@ -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)
}
}
})
})
}