Allow guests to rename stuff

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-05-04 10:27:04 -07:00
parent 470d693d5e
commit 438e4e7a19
7 changed files with 113 additions and 29 deletions

View File

@ -127,6 +127,7 @@ impl Server {
.add_request_handler(Server::forward_project_request::<proto::ReloadBuffers>)
.add_request_handler(Server::forward_project_request::<proto::FormatBuffers>)
.add_request_handler(Server::forward_project_request::<proto::CreateProjectEntry>)
.add_request_handler(Server::forward_project_request::<proto::RenameProjectEntry>)
.add_request_handler(Server::update_buffer)
.add_message_handler(Server::update_buffer_file)
.add_message_handler(Server::buffer_reloaded)
@ -1810,7 +1811,7 @@ mod tests {
}
#[gpui::test(iterations = 10)]
async fn test_worktree_manipulation(
async fn test_fs_operations(
executor: Arc<Deterministic>,
cx_a: &mut TestAppContext,
cx_b: &mut TestAppContext,
@ -1848,14 +1849,12 @@ mod tests {
let worktree_b =
project_b.read_with(cx_b, |project, cx| project.worktrees(cx).next().unwrap());
project_b
let entry = project_b
.update(cx_b, |project, cx| {
project.create_file((worktree_id, "c.txt"), cx).unwrap()
})
.await
.unwrap();
executor.run_until_parked();
worktree_a.read_with(cx_a, |worktree, _| {
assert_eq!(
worktree
@ -1874,6 +1873,32 @@ mod tests {
[".zed.toml", "a.txt", "b.txt", "c.txt"]
);
});
project_b
.update(cx_b, |project, cx| {
project.rename_entry(entry.id, Path::new("d.txt"), cx)
})
.unwrap()
.await
.unwrap();
worktree_a.read_with(cx_a, |worktree, _| {
assert_eq!(
worktree
.paths()
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>(),
[".zed.toml", "a.txt", "b.txt", "d.txt"]
);
});
worktree_b.read_with(cx_b, |worktree, _| {
assert_eq!(
worktree
.paths()
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>(),
[".zed.toml", "a.txt", "b.txt", "d.txt"]
);
});
}
#[gpui::test(iterations = 10)]

View File

@ -262,6 +262,7 @@ impl Project {
client.add_model_message_handler(Self::handle_update_diagnostic_summary);
client.add_model_message_handler(Self::handle_update_worktree);
client.add_model_request_handler(Self::handle_create_project_entry);
client.add_model_request_handler(Self::handle_rename_project_entry);
client.add_model_request_handler(Self::handle_apply_additional_edits_for_completion);
client.add_model_request_handler(Self::handle_apply_code_action);
client.add_model_request_handler(Self::handle_reload_buffers);
@ -736,9 +737,9 @@ impl Project {
new_path: impl Into<Arc<Path>>,
cx: &mut ModelContext<Self>,
) -> Option<Task<Result<Entry>>> {
if self.is_local() {
let worktree = self.worktree_for_entry(entry_id, cx)?;
let new_path = new_path.into();
if self.is_local() {
worktree.update(cx, |worktree, cx| {
worktree
.as_local_mut()
@ -746,7 +747,27 @@ impl Project {
.rename_entry(entry_id, new_path, cx)
})
} else {
todo!()
let client = self.client.clone();
let project_id = self.remote_id().unwrap();
Some(cx.spawn_weak(|_, mut cx| async move {
let response = client
.request(proto::RenameProjectEntry {
project_id,
entry_id: entry_id.to_proto(),
new_path: new_path.as_os_str().as_bytes().to_vec(),
})
.await?;
worktree.update(&mut cx, |worktree, _| {
let worktree = worktree.as_remote_mut().unwrap();
worktree.snapshot.remove_entry(entry_id);
worktree.snapshot.insert_entry(
response
.entry
.ok_or_else(|| anyhow!("missing entry in response"))?,
)
})
}))
}
}
@ -3802,7 +3823,7 @@ impl Project {
envelope: TypedEnvelope<proto::CreateProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<proto::CreateProjectEntryResponse> {
) -> Result<proto::ProjectEntryResponse> {
let entry = this
.update(&mut cx, |this, cx| {
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
@ -3820,7 +3841,26 @@ impl Project {
})
})?
.await?;
Ok(proto::CreateProjectEntryResponse {
Ok(proto::ProjectEntryResponse {
entry: Some((&entry).into()),
})
}
async fn handle_rename_project_entry(
this: ModelHandle<Self>,
envelope: TypedEnvelope<proto::RenameProjectEntry>,
_: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<proto::ProjectEntryResponse> {
let entry = this
.update(&mut cx, |this, cx| {
let entry_id = ProjectEntryId::from_proto(envelope.payload.entry_id);
let new_path = PathBuf::from(OsString::from_vec(envelope.payload.new_path));
this.rename_entry(entry_id, new_path, cx)
.ok_or_else(|| anyhow!("invalid entry"))
})?
.await?;
Ok(proto::ProjectEntryResponse {
entry: Some((&entry).into()),
})
}

View File

@ -956,6 +956,14 @@ impl Snapshot {
self.entries_by_id.get(&entry_id, &()).is_some()
}
pub(crate) fn remove_entry(&mut self, entry_id: ProjectEntryId) -> Option<Entry> {
if let Some(entry) = self.entries_by_id.remove(&entry_id, &()) {
self.entries_by_path.remove(&PathKey(entry.path), &())
} else {
None
}
}
pub(crate) fn insert_entry(&mut self, entry: proto::Entry) -> Result<Entry> {
let entry = Entry::try_from((&self.root_char_bag, entry))?;
self.entries_by_id.insert_or_replace(

View File

@ -295,11 +295,6 @@ impl ProjectPanel {
Ok(())
}))
} else {
// TODO - implement this for remote projects
if !worktree.read(cx).is_local() {
return None;
}
let old_path = entry.path.clone();
let new_path = if let Some(parent) = old_path.parent() {
parent.join(filename)

View File

@ -38,9 +38,9 @@ message Envelope {
UpdateWorktree update_worktree = 31;
CreateProjectEntry create_project_entry = 32;
CreateProjectEntryResponse create_project_entry_response = 33;
RenameProjectEntry rename_project_entry = 34;
DeleteProjectEntry delete_project_entry = 35;
RenameProjectEntry rename_project_entry = 33;
DeleteProjectEntry delete_project_entry = 34;
ProjectEntryResponse project_entry_response = 35;
UpdateDiagnosticSummary update_diagnostic_summary = 36;
StartLanguageServer start_language_server = 37;
@ -171,16 +171,10 @@ message CreateProjectEntry {
bool is_directory = 4;
}
message CreateProjectEntryResponse {
Entry entry = 1;
}
message RenameProjectEntry {
uint64 project_id = 1;
uint64 old_worktree_id = 2;
string old_path = 3;
uint64 new_worktree_id = 4;
string new_path = 5;
uint64 entry_id = 2;
bytes new_path = 3;
}
message DeleteProjectEntry {
@ -189,6 +183,10 @@ message DeleteProjectEntry {
string path = 3;
}
message ProjectEntryResponse {
Entry entry = 1;
}
message AddProjectCollaborator {
uint64 project_id = 1;
Collaborator collaborator = 2;

View File

@ -148,7 +148,6 @@ messages!(
(BufferSaved, Foreground),
(ChannelMessageSent, Foreground),
(CreateProjectEntry, Foreground),
(CreateProjectEntryResponse, Foreground),
(DeleteProjectEntry, Foreground),
(Error, Foreground),
(Follow, Foreground),
@ -177,8 +176,6 @@ messages!(
(JoinChannelResponse, Foreground),
(JoinProject, Foreground),
(JoinProjectResponse, Foreground),
(StartLanguageServer, Foreground),
(UpdateLanguageServer, Foreground),
(LeaveChannel, Foreground),
(LeaveProject, Foreground),
(OpenBufferById, Background),
@ -190,6 +187,7 @@ messages!(
(PerformRenameResponse, Background),
(PrepareRename, Background),
(PrepareRenameResponse, Background),
(ProjectEntryResponse, Foreground),
(RegisterProjectResponse, Foreground),
(Ping, Foreground),
(RegisterProject, Foreground),
@ -204,6 +202,7 @@ messages!(
(SendChannelMessage, Foreground),
(SendChannelMessageResponse, Foreground),
(ShareProject, Foreground),
(StartLanguageServer, Foreground),
(Test, Foreground),
(Unfollow, Foreground),
(UnregisterProject, Foreground),
@ -214,6 +213,7 @@ messages!(
(UpdateContacts, Foreground),
(UpdateDiagnosticSummary, Foreground),
(UpdateFollowers, Foreground),
(UpdateLanguageServer, Foreground),
(UpdateWorktree, Foreground),
);
@ -223,7 +223,7 @@ request_messages!(
ApplyCompletionAdditionalEdits,
ApplyCompletionAdditionalEditsResponse
),
(CreateProjectEntry, CreateProjectEntryResponse),
(CreateProjectEntry, ProjectEntryResponse),
(Follow, FollowResponse),
(FormatBuffers, FormatBuffersResponse),
(GetChannelMessages, GetChannelMessagesResponse),
@ -246,6 +246,7 @@ request_messages!(
(RegisterProject, RegisterProjectResponse),
(RegisterWorktree, Ack),
(ReloadBuffers, ReloadBuffersResponse),
(RenameProjectEntry, ProjectEntryResponse),
(SaveBuffer, BufferSaved),
(SearchProject, SearchProjectResponse),
(SendChannelMessage, SendChannelMessageResponse),

View File

@ -502,6 +502,23 @@ impl<T: KeyedItem> SumTree<T> {
replaced
}
pub fn remove(&mut self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<T> {
let mut removed = None;
*self = {
let mut cursor = self.cursor::<T::Key>();
let mut new_tree = cursor.slice(key, Bias::Left, cx);
if let Some(item) = cursor.item() {
if item.key() == *key {
removed = Some(item.clone());
cursor.next(cx);
}
}
new_tree.push_tree(cursor.suffix(cx), cx);
new_tree
};
removed
}
pub fn edit(
&mut self,
mut edits: Vec<Edit<T>>,