From d40177c2ae414226e70330550b7c315f40c469f1 Mon Sep 17 00:00:00 2001 From: "Andrew Borg (Kashin)" <1192958+aborg-dev@users.noreply.github.com> Date: Tue, 21 Jan 2025 11:48:40 +0000 Subject: [PATCH] Fix project entry rename in Remote Development (#23382) Closes #22883 To fix the problem, we move `handle_rename_project_entry` from `Worktree` to `LspStore` and register it there. This way it becomes available both in local and headless projects and this avoids the duplication. Release Notes: - Fixed renaming project entries in Remote Development --- crates/project/src/lsp_store.rs | 47 ++++++++++++++++ crates/project/src/project.rs | 2 - crates/project/src/worktree_store.rs | 55 +------------------ .../remote_server/src/remote_editing_tests.rs | 40 ++++++++++++++ 4 files changed, 88 insertions(+), 56 deletions(-) diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 76dfe323a053402cad93830f92ec3e55ddc43628..bdef131f8853696981f7758a61e894ab397fd269 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -2872,6 +2872,7 @@ impl LspStore { client.add_model_request_handler(Self::handle_on_type_formatting); client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion); client.add_model_request_handler(Self::handle_register_buffer_with_language_servers); + client.add_model_request_handler(Self::handle_rename_project_entry); client.add_model_request_handler(Self::handle_lsp_command::); client.add_model_request_handler(Self::handle_lsp_command::); client.add_model_request_handler(Self::handle_lsp_command::); @@ -5928,6 +5929,52 @@ impl LspStore { Ok(proto::Ack {}) } + async fn handle_rename_project_entry( + this: Model, + envelope: TypedEnvelope, + mut cx: AsyncAppContext, + ) -> Result { + let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id); + let (worktree_id, worktree, old_path, is_dir) = this + .update(&mut cx, |this, cx| { + this.worktree_store + .read(cx) + .worktree_and_entry_for_id(entry_id, cx) + .map(|(worktree, entry)| { + ( + worktree.read(cx).id(), + worktree, + entry.path.clone(), + entry.is_dir(), + ) + }) + })? + .ok_or_else(|| anyhow!("worktree not found"))?; + let (old_abs_path, new_abs_path) = { + let root_path = worktree.update(&mut cx, |this, _| this.abs_path())?; + ( + root_path.join(&old_path), + root_path.join(&envelope.payload.new_path), + ) + }; + + Self::will_rename_entry( + this.downgrade(), + worktree_id, + &old_abs_path, + &new_abs_path, + is_dir, + cx.clone(), + ) + .await; + let response = Worktree::handle_rename_entry(worktree, envelope.payload, cx.clone()).await; + this.update(&mut cx, |this, _| { + this.did_rename_entry(worktree_id, &old_abs_path, &new_abs_path, is_dir); + }) + .ok(); + response + } + async fn handle_update_diagnostic_summary( this: Model, envelope: TypedEnvelope, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 3ffb861171ad8ae664abb6d0207ec8d73290841a..9c4b485ec25dbd9ad03272747d7caee078009667 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -602,8 +602,6 @@ impl Project { client.add_model_request_handler(Self::handle_open_new_buffer); client.add_model_message_handler(Self::handle_create_buffer_for_peer); - client.add_model_request_handler(WorktreeStore::handle_rename_project_entry); - WorktreeStore::init(&client); BufferStore::init(&client); LspStore::init(&client); diff --git a/crates/project/src/worktree_store.rs b/crates/project/src/worktree_store.rs index c648b75e85a0bcd9a156a1dfd8a8a9b76fa59e7c..e7b1510e2d91507a9296be9df74d5edab976fecb 100644 --- a/crates/project/src/worktree_store.rs +++ b/crates/project/src/worktree_store.rs @@ -27,7 +27,7 @@ use text::ReplicaId; use util::{paths::SanitizedPath, ResultExt}; use worktree::{Entry, ProjectEntryId, Worktree, WorktreeId, WorktreeSettings}; -use crate::{search::SearchQuery, LspStore, ProjectPath}; +use crate::{search::SearchQuery, ProjectPath}; struct MatchingEntry { worktree_path: Arc, @@ -1018,59 +1018,6 @@ impl WorktreeStore { Worktree::handle_create_entry(worktree, envelope.payload, cx).await } - pub async fn handle_rename_project_entry( - this: Model, - envelope: TypedEnvelope, - mut cx: AsyncAppContext, - ) -> Result { - let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id); - let (worktree_id, worktree, old_path, is_dir) = this - .update(&mut cx, |this, cx| { - this.worktree_store - .read(cx) - .worktree_and_entry_for_id(entry_id, cx) - .map(|(worktree, entry)| { - ( - worktree.read(cx).id(), - worktree, - entry.path.clone(), - entry.is_dir(), - ) - }) - })? - .ok_or_else(|| anyhow!("worktree not found"))?; - let (old_abs_path, new_abs_path) = { - let root_path = worktree.update(&mut cx, |this, _| this.abs_path())?; - ( - root_path.join(&old_path), - root_path.join(&envelope.payload.new_path), - ) - }; - let lsp_store = this - .update(&mut cx, |this, _| this.lsp_store())? - .downgrade(); - LspStore::will_rename_entry( - lsp_store, - worktree_id, - &old_abs_path, - &new_abs_path, - is_dir, - cx.clone(), - ) - .await; - let response = Worktree::handle_rename_entry(worktree, envelope.payload, cx.clone()).await; - this.update(&mut cx, |this, cx| { - this.lsp_store().read(cx).did_rename_entry( - worktree_id, - &old_abs_path, - &new_abs_path, - is_dir, - ); - }) - .ok(); - response - } - pub async fn handle_copy_project_entry( this: Model, envelope: TypedEnvelope, diff --git a/crates/remote_server/src/remote_editing_tests.rs b/crates/remote_server/src/remote_editing_tests.rs index e1ec1b65a390c12997e89cd790a898130b638d74..723a5f5fc34180a97d7bf252dcfdc8b0173b4ad7 100644 --- a/crates/remote_server/src/remote_editing_tests.rs +++ b/crates/remote_server/src/remote_editing_tests.rs @@ -1135,6 +1135,46 @@ async fn test_remote_root_rename(cx: &mut TestAppContext, server_cx: &mut TestAp }) } +#[gpui::test] +async fn test_remote_rename_entry(cx: &mut TestAppContext, server_cx: &mut TestAppContext) { + let fs = FakeFs::new(server_cx.executor()); + fs.insert_tree( + "/code", + json!({ + "project1": { + ".git": {}, + "README.md": "# project 1", + }, + }), + ) + .await; + + let (project, _) = init_test(&fs, cx, server_cx).await; + let (worktree, _) = project + .update(cx, |project, cx| { + project.find_or_create_worktree("/code/project1", true, cx) + }) + .await + .unwrap(); + + cx.run_until_parked(); + + let entry = worktree + .update(cx, |worktree, cx| { + let entry = worktree.entry_for_path("README.md").unwrap(); + worktree.rename_entry(entry.id, Path::new("README.rst"), cx) + }) + .await + .unwrap() + .to_included() + .unwrap(); + + cx.run_until_parked(); + + worktree.update(cx, |worktree, _| { + assert_eq!(worktree.entry_for_path("README.rst").unwrap().id, entry.id) + }); +} #[gpui::test] async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestAppContext) { let fs = FakeFs::new(server_cx.executor());