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:
parent
9300dbc834
commit
19162c3160
4 changed files with 53 additions and 10 deletions
|
@ -18,7 +18,7 @@ use gpui::{
|
||||||
use postage::oneshot;
|
use postage::oneshot;
|
||||||
use rpc::{
|
use rpc::{
|
||||||
proto::{self, SSH_PROJECT_ID},
|
proto::{self, SSH_PROJECT_ID},
|
||||||
AnyProtoClient, TypedEnvelope,
|
AnyProtoClient, ErrorExt, TypedEnvelope,
|
||||||
};
|
};
|
||||||
use smol::{
|
use smol::{
|
||||||
channel::{Receiver, Sender},
|
channel::{Receiver, Sender},
|
||||||
|
@ -207,7 +207,7 @@ impl WorktreeStore {
|
||||||
cx.background_executor().spawn(async move {
|
cx.background_executor().spawn(async move {
|
||||||
match task.await {
|
match task.await {
|
||||||
Ok(worktree) => Ok(worktree),
|
Ok(worktree) => Ok(worktree),
|
||||||
Err(err) => Err(anyhow!("{}", err)),
|
Err(err) => Err((*err).cloned()),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ test-support = ["fs/test-support"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
client.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
|
|
@ -189,11 +189,34 @@ impl HeadlessProject {
|
||||||
message: TypedEnvelope<proto::AddWorktree>,
|
message: TypedEnvelope<proto::AddWorktree>,
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<proto::AddWorktreeResponse> {
|
) -> Result<proto::AddWorktreeResponse> {
|
||||||
|
use client::ErrorCodeExt;
|
||||||
let path = shellexpand::tilde(&message.payload.path).to_string();
|
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
|
let worktree = this
|
||||||
.update(&mut cx.clone(), |this, _| {
|
.update(&mut cx.clone(), |this, _| {
|
||||||
Worktree::local(
|
Worktree::local(
|
||||||
Path::new(&path),
|
Arc::from(canonicalized),
|
||||||
true,
|
true,
|
||||||
this.fs.clone(),
|
this.fs.clone(),
|
||||||
this.next_entry_id.clone(),
|
this.next_entry_id.clone(),
|
||||||
|
|
|
@ -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 {
|
for path in paths {
|
||||||
project
|
let result = cx
|
||||||
.update(&mut cx, |project, cx| {
|
.update(|cx| Workspace::project_path_for_path(project.clone(), &path, true, cx))?
|
||||||
project.find_or_create_worktree(&path, true, cx)
|
.await;
|
||||||
})?
|
match result {
|
||||||
.await?;
|
Ok((_, project_path)) => {
|
||||||
|
project_paths_to_open.push((path.clone(), Some(project_path)));
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
project_path_errors.push(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let serialized_workspace =
|
let serialized_workspace =
|
||||||
|
@ -5576,11 +5585,21 @@ pub fn open_ssh_project(
|
||||||
.update(&mut cx, |_, cx| {
|
.update(&mut cx, |_, cx| {
|
||||||
cx.activate_window();
|
cx.activate_window();
|
||||||
|
|
||||||
open_items(serialized_workspace, vec![], app_state, cx)
|
open_items(serialized_workspace, project_paths_to_open, app_state, cx)
|
||||||
})?
|
})?
|
||||||
.await?;
|
.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue