mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-11 21:13:02 +00:00
Send worktree updates after project metadata has been sent
This commit is contained in:
parent
eeb32fa888
commit
117458f4f6
3 changed files with 56 additions and 27 deletions
|
@ -1561,7 +1561,7 @@ where
|
||||||
let query = format!(
|
let query = format!(
|
||||||
"
|
"
|
||||||
DELETE FROM worktrees
|
DELETE FROM worktrees
|
||||||
WHERE project_id = ? AND worktree_id NOT IN ({params})
|
WHERE project_id = ? AND id NOT IN ({params})
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1580,6 +1580,7 @@ where
|
||||||
WHERE project_id = $1 AND is_host = FALSE
|
WHERE project_id = $1 AND is_host = FALSE
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
|
.bind(project_id)
|
||||||
.fetch(&mut tx);
|
.fetch(&mut tx);
|
||||||
while let Some(connection_id) = db_guest_connection_ids.next().await {
|
while let Some(connection_id) = db_guest_connection_ids.next().await {
|
||||||
guest_connection_ids.push(ConnectionId(connection_id? as u32));
|
guest_connection_ids.push(ConnectionId(connection_id? as u32));
|
||||||
|
|
|
@ -10,7 +10,11 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use client::{proto, Client, PeerId, TypedEnvelope, UserStore};
|
use client::{proto, Client, PeerId, TypedEnvelope, UserStore};
|
||||||
use clock::ReplicaId;
|
use clock::ReplicaId;
|
||||||
use collections::{hash_map, BTreeMap, HashMap, HashSet};
|
use collections::{hash_map, BTreeMap, HashMap, HashSet};
|
||||||
use futures::{future::Shared, AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt};
|
use futures::{
|
||||||
|
channel::{mpsc, oneshot},
|
||||||
|
future::Shared,
|
||||||
|
AsyncWriteExt, Future, FutureExt, StreamExt, TryFutureExt,
|
||||||
|
};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
AnyModelHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
||||||
|
@ -145,7 +149,7 @@ enum WorktreeHandle {
|
||||||
enum ProjectClientState {
|
enum ProjectClientState {
|
||||||
Local {
|
Local {
|
||||||
remote_id: u64,
|
remote_id: u64,
|
||||||
metadata_changed: watch::Sender<()>,
|
metadata_changed: mpsc::UnboundedSender<oneshot::Sender<()>>,
|
||||||
_maintain_metadata: Task<()>,
|
_maintain_metadata: Task<()>,
|
||||||
_detect_unshare: Task<Option<()>>,
|
_detect_unshare: Task<Option<()>>,
|
||||||
},
|
},
|
||||||
|
@ -533,7 +537,7 @@ impl Project {
|
||||||
nonce: StdRng::from_entropy().gen(),
|
nonce: StdRng::from_entropy().gen(),
|
||||||
};
|
};
|
||||||
for worktree in worktrees {
|
for worktree in worktrees {
|
||||||
this.add_worktree(&worktree, cx);
|
let _ = this.add_worktree(&worktree, cx);
|
||||||
}
|
}
|
||||||
this
|
this
|
||||||
});
|
});
|
||||||
|
@ -728,14 +732,22 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) {
|
fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) -> impl Future<Output = ()> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
if let Some(ProjectClientState::Local {
|
if let Some(ProjectClientState::Local {
|
||||||
metadata_changed, ..
|
metadata_changed, ..
|
||||||
}) = &mut self.client_state
|
}) = &mut self.client_state
|
||||||
{
|
{
|
||||||
*metadata_changed.borrow_mut() = ();
|
let _ = metadata_changed.unbounded_send(tx);
|
||||||
}
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
// If the project is shared, this will resolve when the `_maintain_metadata` task has
|
||||||
|
// a chance to update the metadata. Otherwise, it will resolve right away because `tx`
|
||||||
|
// will get dropped.
|
||||||
|
let _ = rx.await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collaborators(&self) -> &HashMap<PeerId, Collaborator> {
|
pub fn collaborators(&self) -> &HashMap<PeerId, Collaborator> {
|
||||||
|
@ -1025,17 +1037,22 @@ impl Project {
|
||||||
|
|
||||||
self.client_subscriptions
|
self.client_subscriptions
|
||||||
.push(self.client.add_model_for_remote_entity(project_id, cx));
|
.push(self.client.add_model_for_remote_entity(project_id, cx));
|
||||||
self.metadata_changed(cx);
|
let _ = self.metadata_changed(cx);
|
||||||
cx.emit(Event::RemoteIdChanged(Some(project_id)));
|
cx.emit(Event::RemoteIdChanged(Some(project_id)));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
||||||
let mut status = self.client.status();
|
let mut status = self.client.status();
|
||||||
let (metadata_changed_tx, mut metadata_changed_rx) = watch::channel();
|
let (metadata_changed_tx, mut metadata_changed_rx) = mpsc::unbounded();
|
||||||
self.client_state = Some(ProjectClientState::Local {
|
self.client_state = Some(ProjectClientState::Local {
|
||||||
remote_id: project_id,
|
remote_id: project_id,
|
||||||
metadata_changed: metadata_changed_tx,
|
metadata_changed: metadata_changed_tx,
|
||||||
_maintain_metadata: cx.spawn_weak(move |this, cx| async move {
|
_maintain_metadata: cx.spawn_weak(move |this, cx| async move {
|
||||||
while let Some(()) = metadata_changed_rx.next().await {
|
while let Some(tx) = metadata_changed_rx.next().await {
|
||||||
|
let mut txs = vec![tx];
|
||||||
|
while let Ok(Some(next_tx)) = metadata_changed_rx.try_next() {
|
||||||
|
txs.push(next_tx);
|
||||||
|
}
|
||||||
|
|
||||||
let Some(this) = this.upgrade(&cx) else { break };
|
let Some(this) = this.upgrade(&cx) else { break };
|
||||||
this.read_with(&cx, |this, cx| {
|
this.read_with(&cx, |this, cx| {
|
||||||
let worktrees = this
|
let worktrees = this
|
||||||
|
@ -1054,6 +1071,10 @@ impl Project {
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.log_err();
|
.log_err();
|
||||||
|
|
||||||
|
for tx in txs {
|
||||||
|
let _ = tx.send(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
_detect_unshare: cx.spawn_weak(move |this, mut cx| {
|
_detect_unshare: cx.spawn_weak(move |this, mut cx| {
|
||||||
|
@ -1105,7 +1126,7 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.metadata_changed(cx);
|
let _ = self.metadata_changed(cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
self.client.send(proto::UnshareProject {
|
self.client.send(proto::UnshareProject {
|
||||||
project_id: remote_id,
|
project_id: remote_id,
|
||||||
|
@ -4162,12 +4183,13 @@ impl Project {
|
||||||
});
|
});
|
||||||
let worktree = worktree?;
|
let worktree = worktree?;
|
||||||
|
|
||||||
let project_id = project.update(&mut cx, |project, cx| {
|
project
|
||||||
project.add_worktree(&worktree, cx);
|
.update(&mut cx, |project, cx| project.add_worktree(&worktree, cx))
|
||||||
project.remote_id()
|
.await;
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(project_id) = project_id {
|
if let Some(project_id) =
|
||||||
|
project.read_with(&cx, |project, _| project.remote_id())
|
||||||
|
{
|
||||||
worktree
|
worktree
|
||||||
.update(&mut cx, |worktree, cx| {
|
.update(&mut cx, |worktree, cx| {
|
||||||
worktree.as_local_mut().unwrap().share(project_id, cx)
|
worktree.as_local_mut().unwrap().share(project_id, cx)
|
||||||
|
@ -4191,7 +4213,11 @@ impl Project {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
|
pub fn remove_worktree(
|
||||||
|
&mut self,
|
||||||
|
id_to_remove: WorktreeId,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> impl Future<Output = ()> {
|
||||||
self.worktrees.retain(|worktree| {
|
self.worktrees.retain(|worktree| {
|
||||||
if let Some(worktree) = worktree.upgrade(cx) {
|
if let Some(worktree) = worktree.upgrade(cx) {
|
||||||
let id = worktree.read(cx).id();
|
let id = worktree.read(cx).id();
|
||||||
|
@ -4205,11 +4231,14 @@ impl Project {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.metadata_changed(cx);
|
self.metadata_changed(cx)
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_worktree(&mut self, worktree: &ModelHandle<Worktree>, cx: &mut ModelContext<Self>) {
|
fn add_worktree(
|
||||||
|
&mut self,
|
||||||
|
worktree: &ModelHandle<Worktree>,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> impl Future<Output = ()> {
|
||||||
cx.observe(worktree, |_, _, cx| cx.notify()).detach();
|
cx.observe(worktree, |_, _, cx| cx.notify()).detach();
|
||||||
if worktree.read(cx).is_local() {
|
if worktree.read(cx).is_local() {
|
||||||
cx.subscribe(worktree, |this, worktree, event, cx| match event {
|
cx.subscribe(worktree, |this, worktree, event, cx| match event {
|
||||||
|
@ -4233,15 +4262,13 @@ impl Project {
|
||||||
.push(WorktreeHandle::Weak(worktree.downgrade()));
|
.push(WorktreeHandle::Weak(worktree.downgrade()));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.metadata_changed(cx);
|
|
||||||
cx.observe_release(worktree, |this, worktree, cx| {
|
cx.observe_release(worktree, |this, worktree, cx| {
|
||||||
this.remove_worktree(worktree.id(), cx);
|
let _ = this.remove_worktree(worktree.id(), cx);
|
||||||
cx.notify();
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
cx.emit(Event::WorktreeAdded);
|
cx.emit(Event::WorktreeAdded);
|
||||||
cx.notify();
|
self.metadata_changed(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_local_worktree_buffers(
|
fn update_local_worktree_buffers(
|
||||||
|
@ -4558,11 +4585,11 @@ impl Project {
|
||||||
} else {
|
} else {
|
||||||
let worktree =
|
let worktree =
|
||||||
Worktree::remote(remote_id, replica_id, worktree, client.clone(), cx);
|
Worktree::remote(remote_id, replica_id, worktree, client.clone(), cx);
|
||||||
this.add_worktree(&worktree, cx);
|
let _ = this.add_worktree(&worktree, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.metadata_changed(cx);
|
let _ = this.metadata_changed(cx);
|
||||||
for (id, _) in old_worktrees_by_id {
|
for (id, _) in old_worktrees_by_id {
|
||||||
cx.emit(Event::WorktreeRemoved(id));
|
cx.emit(Event::WorktreeRemoved(id));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1531,7 +1531,8 @@ impl Workspace {
|
||||||
RemoveWorktreeFromProject(worktree_id): &RemoveWorktreeFromProject,
|
RemoveWorktreeFromProject(worktree_id): &RemoveWorktreeFromProject,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.project
|
let _ = self
|
||||||
|
.project
|
||||||
.update(cx, |project, cx| project.remove_worktree(*worktree_id, cx));
|
.update(cx, |project, cx| project.remove_worktree(*worktree_id, cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3177,7 +3178,7 @@ mod tests {
|
||||||
|
|
||||||
// Remove a project folder
|
// Remove a project folder
|
||||||
project.update(cx, |project, cx| {
|
project.update(cx, |project, cx| {
|
||||||
project.remove_worktree(worktree_id, cx);
|
let _ = project.remove_worktree(worktree_id, cx);
|
||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cx.current_window_title(window_id).as_deref(),
|
cx.current_window_title(window_id).as_deref(),
|
||||||
|
|
Loading…
Reference in a new issue