mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 05:51:14 +00:00
Fix deserialization for remote projects
This commit is contained in:
parent
0a9ab49ffb
commit
7c2993de75
6 changed files with 139 additions and 121 deletions
|
|
@ -859,15 +859,11 @@ impl Item for Editor {
|
|||
item_id: ItemId,
|
||||
cx: &mut AppContext,
|
||||
) {
|
||||
if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
|
||||
let path = file.abs_path(cx);
|
||||
if let Some(file) = buffer.read(cx).file() {
|
||||
let path = file.abs_path(cx).to_path_buf();
|
||||
|
||||
cx.background_executor()
|
||||
.spawn(async move {
|
||||
DB.save_path(item_id, workspace_id, path.clone())
|
||||
.await
|
||||
.log_err()
|
||||
})
|
||||
.spawn(async move { DB.save_path(item_id, workspace_id, path).await.log_err() })
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
|
@ -943,7 +939,7 @@ impl Item for Editor {
|
|||
.context("No path stored for this editor")?;
|
||||
|
||||
let (worktree, path) = project
|
||||
.find_local_worktree(&path, cx)
|
||||
.find_worktree(&path, cx)
|
||||
.with_context(|| format!("No worktree for path: {path:?}"))?;
|
||||
let project_path = ProjectPath {
|
||||
worktree_id: worktree.read(cx).id(),
|
||||
|
|
|
|||
|
|
@ -343,6 +343,9 @@ pub trait File: Send + Sync {
|
|||
/// Returns the path of this file relative to the worktree's root directory.
|
||||
fn path(&self) -> &Arc<Path>;
|
||||
|
||||
/// Returns the path of this file relative to the worktree's root directory.
|
||||
fn abs_path(&self, cx: &AppContext) -> PathBuf;
|
||||
|
||||
/// Returns the path of this file relative to the worktree's parent directory (this means it
|
||||
/// includes the name of the worktree's root folder).
|
||||
fn full_path(&self, cx: &AppContext) -> PathBuf;
|
||||
|
|
@ -376,9 +379,6 @@ pub trait File: Send + Sync {
|
|||
|
||||
/// The file associated with a buffer, in the case where the file is on the local disk.
|
||||
pub trait LocalFile: File {
|
||||
/// Returns the absolute path of this file.
|
||||
fn abs_path(&self, cx: &AppContext) -> PathBuf;
|
||||
|
||||
/// Loads the file's contents from disk.
|
||||
fn load(&self, cx: &AppContext) -> Task<Result<String>>;
|
||||
|
||||
|
|
@ -3906,6 +3906,10 @@ impl File for TestFile {
|
|||
&self.path
|
||||
}
|
||||
|
||||
fn abs_path(&self, cx: &AppContext) -> PathBuf {
|
||||
panic!("unimplemented")
|
||||
}
|
||||
|
||||
fn full_path(&self, _: &gpui::AppContext) -> PathBuf {
|
||||
PathBuf::from(&self.root_name).join(self.path.as_ref())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use futures::{
|
|||
use gpui::{AsyncAppContext, Model, ModelContext, Task, WeakModel};
|
||||
use language::{
|
||||
language_settings::{Formatter, LanguageSettings},
|
||||
Buffer, LanguageServerName, LocalFile,
|
||||
Buffer, File as _, LanguageServerName,
|
||||
};
|
||||
use lsp::{LanguageServer, LanguageServerId};
|
||||
use node_runtime::NodeRuntime;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ use language::{
|
|||
},
|
||||
range_from_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, Capability, CodeLabel,
|
||||
ContextProvider, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Documentation,
|
||||
Event as BufferEvent, File as _, Language, LanguageRegistry, LanguageServerName, LocalFile,
|
||||
Event as BufferEvent, File as _, Language, LanguageRegistry, LanguageServerName,
|
||||
LspAdapterDelegate, Operation, Patch, PendingLanguageServer, PointUtf16, TextBufferSnapshot,
|
||||
ToOffset, ToPointUtf16, Transaction, Unclipped,
|
||||
};
|
||||
|
|
@ -7425,6 +7425,21 @@ impl Project {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_worktree(
|
||||
&self,
|
||||
abs_path: &Path,
|
||||
cx: &AppContext,
|
||||
) -> Option<(Model<Worktree>, PathBuf)> {
|
||||
for tree in &self.worktrees {
|
||||
if let Some(tree) = tree.upgrade() {
|
||||
if let Some(relative_path) = abs_path.strip_prefix(&tree.read(cx).abs_path()).ok() {
|
||||
return Some((tree.clone(), relative_path.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn find_local_worktree(
|
||||
&self,
|
||||
abs_path: &Path,
|
||||
|
|
|
|||
|
|
@ -950,81 +950,101 @@ impl Workspace {
|
|||
}
|
||||
}
|
||||
|
||||
let workspace_id = if let Some(serialized_workspace) = serialized_workspace.as_ref() {
|
||||
serialized_workspace.id
|
||||
} else {
|
||||
DB.next_id().await.unwrap_or_else(|_| Default::default())
|
||||
};
|
||||
|
||||
let window = if let Some(window) = requesting_window {
|
||||
cx.update_window(window.into(), |_, cx| {
|
||||
cx.replace_root_view(|cx| {
|
||||
Workspace::new(
|
||||
Some(workspace_id),
|
||||
project_handle.clone(),
|
||||
app_state.clone(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
})?;
|
||||
window
|
||||
} else {
|
||||
let window_bounds_override = window_bounds_env_override();
|
||||
|
||||
let (window_bounds, display) = if let Some(bounds) = window_bounds_override {
|
||||
(Some(WindowBounds::Windowed(bounds)), None)
|
||||
} else {
|
||||
let restorable_bounds = serialized_workspace
|
||||
.as_ref()
|
||||
.and_then(|workspace| Some((workspace.display?, workspace.window_bounds?)))
|
||||
.or_else(|| {
|
||||
let (display, window_bounds) = DB.last_window().log_err()?;
|
||||
Some((display?, window_bounds?))
|
||||
});
|
||||
|
||||
if let Some((serialized_display, serialized_status)) = restorable_bounds {
|
||||
(Some(serialized_status.0), Some(serialized_display))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
};
|
||||
|
||||
// Use the serialized workspace to construct the new window
|
||||
let mut options = cx.update(|cx| (app_state.build_window_options)(display, cx))?;
|
||||
options.window_bounds = window_bounds;
|
||||
let centered_layout = serialized_workspace
|
||||
.as_ref()
|
||||
.map(|w| w.centered_layout)
|
||||
.unwrap_or(false);
|
||||
cx.open_window(options, {
|
||||
let app_state = app_state.clone();
|
||||
let project_handle = project_handle.clone();
|
||||
move |cx| {
|
||||
cx.new_view(|cx| {
|
||||
let mut workspace =
|
||||
Workspace::new(Some(workspace_id), project_handle, app_state, cx);
|
||||
workspace.centered_layout = centered_layout;
|
||||
workspace
|
||||
})
|
||||
}
|
||||
})?
|
||||
};
|
||||
|
||||
notify_if_database_failed(window, &mut cx);
|
||||
let opened_items = window
|
||||
.update(&mut cx, |_workspace, cx| {
|
||||
open_items(serialized_workspace, project_paths, app_state, cx)
|
||||
})?
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
window
|
||||
.update(&mut cx, |_, cx| cx.activate_window())
|
||||
.log_err();
|
||||
Ok((window, opened_items))
|
||||
Workspace::reopen_serialized(
|
||||
project_handle,
|
||||
serialized_workspace,
|
||||
project_paths,
|
||||
app_state,
|
||||
requesting_window,
|
||||
&mut cx,
|
||||
)
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
async fn reopen_serialized(
|
||||
project_handle: Model<Project>,
|
||||
serialized_workspace: Option<SerializedWorkspace>,
|
||||
project_paths: Vec<(PathBuf, Option<ProjectPath>)>,
|
||||
app_state: Arc<AppState>,
|
||||
requesting_window: Option<WindowHandle<Workspace>>,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> anyhow::Result<(
|
||||
WindowHandle<Workspace>,
|
||||
Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
|
||||
)> {
|
||||
let workspace_id = if let Some(serialized_workspace) = serialized_workspace.as_ref() {
|
||||
serialized_workspace.id
|
||||
} else {
|
||||
DB.next_id().await.unwrap_or_else(|_| Default::default())
|
||||
};
|
||||
|
||||
let window = if let Some(window) = requesting_window {
|
||||
cx.update_window(window.into(), |_, cx| {
|
||||
cx.replace_root_view(|cx| {
|
||||
Workspace::new(
|
||||
Some(workspace_id),
|
||||
project_handle.clone(),
|
||||
app_state.clone(),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
})?;
|
||||
window
|
||||
} else {
|
||||
let window_bounds_override = window_bounds_env_override();
|
||||
|
||||
let (window_bounds, display) = if let Some(bounds) = window_bounds_override {
|
||||
(Some(WindowBounds::Windowed(bounds)), None)
|
||||
} else {
|
||||
let restorable_bounds = serialized_workspace
|
||||
.as_ref()
|
||||
.and_then(|workspace| Some((workspace.display?, workspace.window_bounds?)))
|
||||
.or_else(|| {
|
||||
let (display, window_bounds) = DB.last_window().log_err()?;
|
||||
Some((display?, window_bounds?))
|
||||
});
|
||||
|
||||
if let Some((serialized_display, serialized_status)) = restorable_bounds {
|
||||
(Some(serialized_status.0), Some(serialized_display))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
};
|
||||
|
||||
// Use the serialized workspace to construct the new window
|
||||
let mut options = cx.update(|cx| (app_state.build_window_options)(display, cx))?;
|
||||
options.window_bounds = window_bounds;
|
||||
let centered_layout = serialized_workspace
|
||||
.as_ref()
|
||||
.map(|w| w.centered_layout)
|
||||
.unwrap_or(false);
|
||||
cx.open_window(options, {
|
||||
let app_state = app_state.clone();
|
||||
let project_handle = project_handle.clone();
|
||||
move |cx| {
|
||||
cx.new_view(|cx| {
|
||||
let mut workspace =
|
||||
Workspace::new(Some(workspace_id), project_handle, app_state, cx);
|
||||
workspace.centered_layout = centered_layout;
|
||||
workspace
|
||||
})
|
||||
}
|
||||
})?
|
||||
};
|
||||
|
||||
notify_if_database_failed(window, cx);
|
||||
let opened_items = window
|
||||
.update(cx, |_workspace, cx| {
|
||||
open_items(serialized_workspace, project_paths, app_state, cx)
|
||||
})?
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
window.update(cx, |_, cx| cx.activate_window()).log_err();
|
||||
Ok((window, opened_items))
|
||||
}
|
||||
|
||||
pub fn weak_handle(&self) -> WeakView<Self> {
|
||||
self.weak_self.clone()
|
||||
}
|
||||
|
|
@ -4984,36 +5004,19 @@ pub fn join_dev_server_project(
|
|||
cx.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let serialized_workspace: Option<SerializedWorkspace> =
|
||||
persistence::DB.workspace_for_dev_server_project(dev_server_project_id);
|
||||
|
||||
let workspace_id = if let Some(serialized_workspace) = serialized_workspace {
|
||||
serialized_workspace.id
|
||||
} else {
|
||||
persistence::DB.next_id().await?
|
||||
};
|
||||
|
||||
if let Some(window_to_replace) = window_to_replace {
|
||||
cx.update_window(window_to_replace.into(), |_, cx| {
|
||||
cx.replace_root_view(|cx| {
|
||||
Workspace::new(Some(workspace_id), project, app_state.clone(), cx)
|
||||
});
|
||||
})?;
|
||||
window_to_replace
|
||||
} else {
|
||||
let window_bounds_override = window_bounds_env_override();
|
||||
cx.update(|cx| {
|
||||
let mut options = (app_state.build_window_options)(None, cx);
|
||||
options.window_bounds =
|
||||
window_bounds_override.map(|bounds| WindowBounds::Windowed(bounds));
|
||||
cx.open_window(options, |cx| {
|
||||
cx.new_view(|cx| {
|
||||
Workspace::new(Some(workspace_id), project, app_state.clone(), cx)
|
||||
})
|
||||
})
|
||||
})?
|
||||
}
|
||||
Workspace::reopen_serialized(
|
||||
project,
|
||||
serialized_workspace,
|
||||
vec![],
|
||||
app_state,
|
||||
window_to_replace,
|
||||
&mut cx,
|
||||
)
|
||||
.await?
|
||||
.0
|
||||
};
|
||||
|
||||
workspace.update(&mut cx, |_, cx| {
|
||||
|
|
|
|||
|
|
@ -2947,6 +2947,15 @@ impl language::File for File {
|
|||
&self.path
|
||||
}
|
||||
|
||||
fn abs_path(&self, cx: &AppContext) -> PathBuf {
|
||||
let worktree_path = &self.worktree.read(cx).abs_path;
|
||||
if self.path.as_ref() == Path::new("") {
|
||||
worktree_path.to_path_buf()
|
||||
} else {
|
||||
worktree_path.join(&self.path)
|
||||
}
|
||||
}
|
||||
|
||||
fn full_path(&self, cx: &AppContext) -> PathBuf {
|
||||
let mut full_path = PathBuf::new();
|
||||
let worktree = self.worktree.read(cx);
|
||||
|
|
@ -3007,15 +3016,6 @@ impl language::File for File {
|
|||
}
|
||||
|
||||
impl language::LocalFile for File {
|
||||
fn abs_path(&self, cx: &AppContext) -> PathBuf {
|
||||
let worktree_path = &self.worktree.read(cx).as_local().unwrap().abs_path;
|
||||
if self.path.as_ref() == Path::new("") {
|
||||
worktree_path.to_path_buf()
|
||||
} else {
|
||||
worktree_path.join(&self.path)
|
||||
}
|
||||
}
|
||||
|
||||
fn load(&self, cx: &AppContext) -> Task<Result<String>> {
|
||||
let worktree = self.worktree.read(cx).as_local().unwrap();
|
||||
let abs_path = worktree.absolutize(&self.path);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue