diff --git a/Cargo.lock b/Cargo.lock index a3e577531b..89ed71b4e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -998,6 +998,14 @@ dependencies = [ "syn", ] +[[package]] +name = "clock" +version = "0.1.0" +dependencies = [ + "smallvec", + "zrpc", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -5909,6 +5917,7 @@ dependencies = [ "async-trait", "async-tungstenite", "cargo-bundle", + "clock", "crossbeam-channel", "ctor", "dirs 3.0.1", diff --git a/Cargo.toml b/Cargo.toml index e26dc720f8..8d4c21bde8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,15 @@ [workspace] -members = ["fsevent", "fuzzy", "gpui", "gpui_macros", "server", "sum_tree", "zed", "zrpc"] +members = [ + "clock", + "fsevent", + "fuzzy", + "gpui", + "gpui_macros", + "server", + "sum_tree", + "zed", + "zrpc" +] default-members = ["zed"] [patch.crates-io] diff --git a/clock/Cargo.toml b/clock/Cargo.toml new file mode 100644 index 0000000000..9770b1d7d7 --- /dev/null +++ b/clock/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "clock" +version = "0.1.0" +edition = "2018" + +[dependencies] +smallvec = { version = "1.6", features = ["union"] } +zrpc = { path = "../zrpc" } diff --git a/zed/src/time.rs b/clock/src/lib.rs similarity index 100% rename from zed/src/time.rs rename to clock/src/lib.rs diff --git a/zed/Cargo.toml b/zed/Cargo.toml index 06ad32a498..6edeb1c9cc 100644 --- a/zed/Cargo.toml +++ b/zed/Cargo.toml @@ -22,6 +22,7 @@ async-recursion = "0.3" async-trait = "0.1" arrayvec = "0.7.1" async-tungstenite = { version = "0.14", features = ["async-tls"] } +clock = { path = "../clock" } crossbeam-channel = "0.5.0" ctor = "0.1.20" dirs = "3.0" @@ -52,7 +53,7 @@ similar = "1.3" simplelog = "0.9" smallvec = { version = "1.6", features = ["union"] } smol = "1.2.5" -sum_tree = { "path" = "../sum_tree" } +sum_tree = { path = "../sum_tree" } surf = "2.2" tempdir = { version = "0.3.7", optional = true } thiserror = "1.0.29" diff --git a/zed/src/editor.rs b/zed/src/editor.rs index 4def017a86..145f2c3f66 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -8,13 +8,13 @@ use crate::{ project::ProjectPath, settings::Settings, theme::Theme, - time::ReplicaId, util::{post_inc, Bias}, workspace, worktree::Worktree, }; use anyhow::Result; pub use buffer::*; +use clock::ReplicaId; pub use display_map::DisplayPoint; use display_map::*; pub use element::*; diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index 457c012d22..5961d72bf1 100644 --- a/zed/src/editor/buffer.rs +++ b/zed/src/editor/buffer.rs @@ -7,11 +7,11 @@ mod selection; use crate::{ language::{Language, Tree}, settings::{HighlightId, HighlightMap}, - time::{self, ReplicaId}, util::Bias, }; pub use anchor::*; use anyhow::{anyhow, Result}; +use clock::ReplicaId; use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task}; use lazy_static::lazy_static; use operation_queue::OperationQueue; @@ -66,9 +66,9 @@ pub trait File { &self, buffer_id: u64, text: Rope, - version: time::Global, + version: clock::Global, cx: &mut MutableAppContext, - ) -> Task>; + ) -> Task>; fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext); @@ -150,10 +150,10 @@ pub struct Buffer { fragments: SumTree, visible_text: Rope, deleted_text: Rope, - pub version: time::Global, - saved_version: time::Global, + pub version: clock::Global, + saved_version: clock::Global, saved_mtime: SystemTime, - last_edit: time::Local, + last_edit: clock::Local, undo_map: UndoMap, history: History, file: Option>, @@ -167,8 +167,8 @@ pub struct Buffer { deferred_replicas: HashSet, replica_id: ReplicaId, remote_id: u64, - local_clock: time::Local, - lamport_clock: time::Lamport, + local_clock: clock::Local, + lamport_clock: clock::Lamport, #[cfg(test)] operations: Vec, } @@ -183,15 +183,15 @@ pub struct SelectionSet { struct SyntaxTree { tree: Tree, dirty: bool, - version: time::Global, + version: clock::Global, } #[derive(Clone, Debug)] struct Transaction { - start: time::Global, - end: time::Global, + start: clock::Global, + end: clock::Global, buffer_was_dirty: bool, - edits: Vec, + edits: Vec, ranges: Vec>, selections_before: Option<(SelectionSetId, Arc<[Selection]>)>, selections_after: Option<(SelectionSetId, Arc<[Selection]>)>, @@ -251,7 +251,7 @@ impl Transaction { pub struct History { // TODO: Turn this into a String or Rope, maybe. pub base_text: Arc, - ops: HashMap, + ops: HashMap, undo_stack: Vec, redo_stack: Vec, transaction_depth: usize, @@ -276,7 +276,7 @@ impl History { fn start_transaction( &mut self, - start: time::Global, + start: clock::Global, buffer_was_dirty: bool, selections: Option<(SelectionSetId, Arc<[Selection]>)>, now: Instant, @@ -349,7 +349,7 @@ impl History { self.undo_stack.truncate(new_len); } - fn push_undo(&mut self, edit_id: time::Local) { + fn push_undo(&mut self, edit_id: clock::Local) { assert_ne!(self.transaction_depth, 0); let last_transaction = self.undo_stack.last_mut().unwrap(); last_transaction.push_edit(&self.ops[&edit_id]); @@ -377,7 +377,7 @@ impl History { } #[derive(Clone, Default, Debug)] -struct UndoMap(HashMap>); +struct UndoMap(HashMap>); impl UndoMap { fn insert(&mut self, undo: &UndoOperation) { @@ -386,11 +386,11 @@ impl UndoMap { } } - fn is_undone(&self, edit_id: time::Local) -> bool { + fn is_undone(&self, edit_id: clock::Local) -> bool { self.undo_count(edit_id) % 2 == 1 } - fn was_undone(&self, edit_id: time::Local, version: &time::Global) -> bool { + fn was_undone(&self, edit_id: clock::Local, version: &clock::Global) -> bool { let undo_count = self .0 .get(&edit_id) @@ -403,7 +403,7 @@ impl UndoMap { undo_count % 2 == 1 } - fn undo_count(&self, edit_id: time::Local) -> u32 { + fn undo_count(&self, edit_id: clock::Local) -> u32 { self.0 .get(&edit_id) .unwrap_or(&Vec::new()) @@ -419,7 +419,7 @@ struct Edits<'a, F: Fn(&FragmentSummary) -> bool> { deleted_text: &'a Rope, cursor: Option>, undos: &'a UndoMap, - since: time::Global, + since: clock::Global, old_offset: usize, new_offset: usize, old_point: Point, @@ -452,7 +452,7 @@ impl Edit { } struct Diff { - base_version: time::Global, + base_version: clock::Global, new_text: Arc, changes: Vec<(ChangeTag, usize)>, } @@ -460,20 +460,20 @@ struct Diff { #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] struct InsertionTimestamp { replica_id: ReplicaId, - local: time::Seq, - lamport: time::Seq, + local: clock::Seq, + lamport: clock::Seq, } impl InsertionTimestamp { - fn local(&self) -> time::Local { - time::Local { + fn local(&self) -> clock::Local { + clock::Local { replica_id: self.replica_id, value: self.local, } } - fn lamport(&self) -> time::Lamport { - time::Lamport { + fn lamport(&self) -> clock::Lamport { + clock::Lamport { replica_id: self.replica_id, value: self.lamport, } @@ -485,16 +485,16 @@ struct Fragment { timestamp: InsertionTimestamp, len: usize, visible: bool, - deletions: HashSet, - max_undos: time::Global, + deletions: HashSet, + max_undos: clock::Global, } #[derive(Eq, PartialEq, Clone, Debug)] pub struct FragmentSummary { text: FragmentTextSummary, - max_version: time::Global, - min_insertion_version: time::Global, - max_insertion_version: time::Global, + max_version: clock::Global, + min_insertion_version: clock::Global, + max_insertion_version: clock::Global, } #[derive(Copy, Default, Clone, Debug, PartialEq, Eq)] @@ -504,7 +504,7 @@ struct FragmentTextSummary { } impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FragmentTextSummary { - fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option) { + fn add_summary(&mut self, summary: &'a FragmentSummary, _: &Option) { self.visible += summary.text.visible; self.deleted += summary.text.deleted; } @@ -515,35 +515,35 @@ pub enum Operation { Edit(EditOperation), Undo { undo: UndoOperation, - lamport_timestamp: time::Lamport, + lamport_timestamp: clock::Lamport, }, UpdateSelections { set_id: SelectionSetId, selections: Option>, - lamport_timestamp: time::Lamport, + lamport_timestamp: clock::Lamport, }, SetActiveSelections { set_id: Option, - lamport_timestamp: time::Lamport, + lamport_timestamp: clock::Lamport, }, #[cfg(test)] - Test(time::Lamport), + Test(clock::Lamport), } #[derive(Clone, Debug, Eq, PartialEq)] pub struct EditOperation { timestamp: InsertionTimestamp, - version: time::Global, + version: clock::Global, ranges: Vec>, new_text: Option, } #[derive(Clone, Debug, Eq, PartialEq)] pub struct UndoOperation { - id: time::Local, - counts: HashMap, + id: clock::Local, + counts: HashMap, ranges: Vec>, - version: time::Global, + version: clock::Global, } impl Buffer { @@ -614,9 +614,9 @@ impl Buffer { visible_text, deleted_text: Rope::new(), fragments, - version: time::Global::new(), - saved_version: time::Global::new(), - last_edit: time::Local::default(), + version: clock::Global::new(), + saved_version: clock::Global::new(), + last_edit: clock::Local::default(), undo_map: Default::default(), history, file, @@ -631,8 +631,8 @@ impl Buffer { deferred_replicas: HashSet::default(), replica_id, remote_id, - local_clock: time::Local::new(replica_id), - lamport_clock: time::Lamport::new(replica_id), + local_clock: clock::Local::new(replica_id), + lamport_clock: clock::Lamport::new(replica_id), #[cfg(test)] operations: Default::default(), @@ -681,7 +681,7 @@ impl Buffer { .selections .into_iter() .map(|set| { - let set_id = time::Lamport { + let set_id = clock::Lamport { replica_id: set.replica_id as ReplicaId, value: set.local_timestamp, }; @@ -730,7 +730,7 @@ impl Buffer { pub fn save( &mut self, cx: &mut ModelContext, - ) -> Result>> { + ) -> Result>> { let file = self .file .as_ref() @@ -758,7 +758,7 @@ impl Buffer { pub fn did_save( &mut self, - version: time::Global, + version: clock::Global, mtime: SystemTime, new_file: Option>, cx: &mut ModelContext, @@ -1063,7 +1063,7 @@ impl Buffer { self.remote_id } - pub fn version(&self) -> time::Global { + pub fn version(&self) -> clock::Global { self.version.clone() } @@ -1106,7 +1106,7 @@ impl Buffer { self.visible_text.chars_at(offset) } - pub fn edits_since<'a>(&'a self, since: time::Global) -> impl 'a + Iterator { + pub fn edits_since<'a>(&'a self, since: clock::Global) -> impl 'a + Iterator { let since_2 = since.clone(); let cursor = if since == self.version { None @@ -1461,7 +1461,7 @@ impl Buffer { fn apply_remote_edit( &mut self, - version: &time::Global, + version: &clock::Global, ranges: &[Range], new_text: Option<&str>, timestamp: InsertionTimestamp, @@ -1992,7 +1992,7 @@ impl Clone for Buffer { pub struct Snapshot { visible_text: Rope, fragments: SumTree, - version: time::Global, + version: clock::Global, tree: Option, is_parsing: bool, language: Option>, @@ -2110,7 +2110,7 @@ impl Snapshot { pub struct Content<'a> { visible_text: &'a Rope, fragments: &'a SumTree, - version: &'a time::Global, + version: &'a clock::Global, } impl<'a> From<&'a Snapshot> for Content<'a> { @@ -2489,7 +2489,7 @@ impl Fragment { && self.deletions.iter().all(|d| undos.is_undone(*d)) } - fn was_visible(&self, version: &time::Global, undos: &UndoMap) -> bool { + fn was_visible(&self, version: &clock::Global, undos: &UndoMap) -> bool { (version.observed(self.timestamp.local()) && !undos.was_undone(self.timestamp.local(), version)) && self @@ -2503,14 +2503,14 @@ impl sum_tree::Item for Fragment { type Summary = FragmentSummary; fn summary(&self) -> Self::Summary { - let mut max_version = time::Global::new(); + let mut max_version = clock::Global::new(); max_version.observe(self.timestamp.local()); for deletion in &self.deletions { max_version.observe(*deletion); } max_version.join(&self.max_undos); - let mut min_insertion_version = time::Global::new(); + let mut min_insertion_version = clock::Global::new(); min_insertion_version.observe(self.timestamp.local()); let max_insertion_version = min_insertion_version.clone(); if self.visible { @@ -2538,7 +2538,7 @@ impl sum_tree::Item for Fragment { } impl sum_tree::Summary for FragmentSummary { - type Context = Option; + type Context = Option; fn add_summary(&mut self, other: &Self, _: &Self::Context) { self.text.visible += &other.text.visible; @@ -2555,15 +2555,15 @@ impl Default for FragmentSummary { fn default() -> Self { FragmentSummary { text: FragmentTextSummary::default(), - max_version: time::Global::new(), - min_insertion_version: time::Global::new(), - max_insertion_version: time::Global::new(), + max_version: clock::Global::new(), + min_insertion_version: clock::Global::new(), + max_insertion_version: clock::Global::new(), } } } impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize { - fn add_summary(&mut self, summary: &FragmentSummary, _: &Option) { + fn add_summary(&mut self, summary: &FragmentSummary, _: &Option) { *self += summary.text.visible; } } @@ -2591,7 +2591,7 @@ impl Default for VersionedOffset { } impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset { - fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option) { + fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option) { if let Self::Offset(offset) = self { let version = cx.as_ref().unwrap(); if *version >= summary.max_insertion_version { @@ -2608,7 +2608,7 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset { } impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedOffset { - fn cmp(&self, other: &Self, _: &Option) -> cmp::Ordering { + fn cmp(&self, other: &Self, _: &Option) -> cmp::Ordering { match (self, other) { (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b), (Self::Offset(_), Self::InvalidVersion) => cmp::Ordering::Less, @@ -2622,7 +2622,7 @@ impl Operation { self.lamport_timestamp().replica_id } - fn lamport_timestamp(&self) -> time::Lamport { + fn lamport_timestamp(&self) -> clock::Lamport { match self { Operation::Edit(edit) => edit.timestamp.lamport(), Operation::Undo { @@ -2765,12 +2765,12 @@ impl TryFrom for Operation { { proto::operation::Variant::Edit(edit) => Operation::Edit(edit.into()), proto::operation::Variant::Undo(undo) => Operation::Undo { - lamport_timestamp: time::Lamport { + lamport_timestamp: clock::Lamport { replica_id: undo.replica_id as ReplicaId, value: undo.lamport_timestamp, }, undo: UndoOperation { - id: time::Local { + id: clock::Local { replica_id: undo.replica_id as ReplicaId, value: undo.local_timestamp, }, @@ -2779,7 +2779,7 @@ impl TryFrom for Operation { .into_iter() .map(|c| { ( - time::Local { + clock::Local { replica_id: c.replica_id as ReplicaId, value: c.local_timestamp, }, @@ -2807,11 +2807,11 @@ impl TryFrom for Operation { None }; Operation::UpdateSelections { - set_id: time::Lamport { + set_id: clock::Lamport { replica_id: message.replica_id as ReplicaId, value: message.local_timestamp, }, - lamport_timestamp: time::Lamport { + lamport_timestamp: clock::Lamport { replica_id: message.replica_id as ReplicaId, value: message.lamport_timestamp, }, @@ -2820,11 +2820,11 @@ impl TryFrom for Operation { } proto::operation::Variant::SetActiveSelections(message) => { Operation::SetActiveSelections { - set_id: message.local_timestamp.map(|value| time::Lamport { + set_id: message.local_timestamp.map(|value| clock::Lamport { replica_id: message.replica_id as ReplicaId, value, }), - lamport_timestamp: time::Lamport { + lamport_timestamp: clock::Lamport { replica_id: message.replica_id as ReplicaId, value: message.lamport_timestamp, }, @@ -2859,9 +2859,9 @@ impl TryFrom for Anchor { type Error = anyhow::Error; fn try_from(message: proto::Anchor) -> Result { - let mut version = time::Global::new(); + let mut version = clock::Global::new(); for entry in message.version { - version.observe(time::Local { + version.observe(clock::Local { replica_id: entry.replica_id as ReplicaId, value: entry.timestamp, }); diff --git a/zed/src/editor/buffer/anchor.rs b/zed/src/editor/buffer/anchor.rs index bd46c4fbbb..c10e5c8b8e 100644 --- a/zed/src/editor/buffer/anchor.rs +++ b/zed/src/editor/buffer/anchor.rs @@ -1,5 +1,5 @@ use super::{Buffer, Content}; -use crate::{time, util::Bias}; +use crate::util::Bias; use anyhow::Result; use std::{cmp::Ordering, ops::Range}; @@ -7,7 +7,7 @@ use std::{cmp::Ordering, ops::Range}; pub struct Anchor { pub offset: usize, pub bias: Bias, - pub version: time::Global, + pub version: clock::Global, } impl Anchor { diff --git a/zed/src/editor/buffer/operation_queue.rs b/zed/src/editor/buffer/operation_queue.rs index ae426d77a4..3c3a644024 100644 --- a/zed/src/editor/buffer/operation_queue.rs +++ b/zed/src/editor/buffer/operation_queue.rs @@ -1,5 +1,4 @@ use super::Operation; -use crate::time; use std::{fmt::Debug, ops::Add}; use sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary}; @@ -7,7 +6,7 @@ use sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary}; pub struct OperationQueue(SumTree); #[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] -pub struct OperationKey(time::Lamport); +pub struct OperationKey(clock::Lamport); #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub struct OperationSummary { @@ -16,7 +15,7 @@ pub struct OperationSummary { } impl OperationKey { - pub fn new(timestamp: time::Lamport) -> Self { + pub fn new(timestamp: clock::Lamport) -> Self { Self(timestamp) } } @@ -102,7 +101,7 @@ mod tests { #[test] fn test_len() { - let mut clock = time::Lamport::new(0); + let mut clock = clock::Lamport::new(0); let mut queue = OperationQueue::new(); assert_eq!(queue.len(), 0); @@ -124,5 +123,5 @@ mod tests { } #[derive(Clone, Debug, Eq, PartialEq)] - struct TestOperation(time::Lamport); + struct TestOperation(clock::Lamport); } diff --git a/zed/src/editor/buffer/selection.rs b/zed/src/editor/buffer/selection.rs index 254d7cbc6f..9d4bf01f89 100644 --- a/zed/src/editor/buffer/selection.rs +++ b/zed/src/editor/buffer/selection.rs @@ -1,13 +1,10 @@ -use crate::{ - editor::{ - buffer::{Anchor, Buffer, Point, ToOffset as _, ToPoint as _}, - Bias, DisplayMapSnapshot, DisplayPoint, - }, - time, +use crate::editor::{ + buffer::{Anchor, Buffer, Point, ToOffset as _, ToPoint as _}, + Bias, DisplayMapSnapshot, DisplayPoint, }; use std::{cmp::Ordering, mem, ops::Range}; -pub type SelectionSetId = time::Lamport; +pub type SelectionSetId = clock::Lamport; pub type SelectionsVersion = usize; #[derive(Copy, Clone, Debug, Eq, PartialEq)] diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index aa7d0f44fa..b83e9d7688 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -2,7 +2,7 @@ use super::{ buffer::{AnchorRangeExt, TextSummary}, Anchor, Buffer, Point, ToOffset, }; -use crate::{editor::buffer, settings::HighlightId, time, util::Bias}; +use crate::{editor::buffer, settings::HighlightId, util::Bias}; use gpui::{AppContext, ModelHandle}; use parking_lot::Mutex; use std::{ @@ -200,7 +200,7 @@ pub struct FoldMap { #[derive(Clone)] struct SyncState { - version: time::Global, + version: clock::Global, parse_count: usize, } diff --git a/zed/src/editor/element.rs b/zed/src/editor/element.rs index 7c65b1a22d..5cc76bde8e 100644 --- a/zed/src/editor/element.rs +++ b/zed/src/editor/element.rs @@ -2,7 +2,8 @@ use super::{ DisplayPoint, Editor, EditorMode, EditorStyle, Insert, Scroll, Select, SelectPhase, Snapshot, MAX_LINE_LEN, }; -use crate::{theme::HighlightId, time::ReplicaId}; +use crate::theme::HighlightId; +use clock::ReplicaId; use gpui::{ color::Color, geometry::{ diff --git a/zed/src/lib.rs b/zed/src/lib.rs index 12a38938b8..32fa9a4c36 100644 --- a/zed/src/lib.rs +++ b/zed/src/lib.rs @@ -17,7 +17,6 @@ pub mod settings; pub mod test; pub mod theme; pub mod theme_selector; -mod time; pub mod user; mod util; pub mod workspace; diff --git a/zed/src/test.rs b/zed/src/test.rs index 59edd380d5..5cd0d37bbd 100644 --- a/zed/src/test.rs +++ b/zed/src/test.rs @@ -6,11 +6,11 @@ use crate::{ language::LanguageRegistry, rpc::{self, Client, Credentials, EstablishConnectionError}, settings::{self, ThemeRegistry}, - time::ReplicaId, user::UserStore, AppState, }; use anyhow::{anyhow, Result}; +use clock::ReplicaId; use futures::{future::BoxFuture, Future}; use gpui::{AsyncAppContext, Entity, ModelHandle, MutableAppContext, TestAppContext}; use parking_lot::Mutex; diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index cdc8bb5648..2785e4f76d 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -7,11 +7,11 @@ use crate::{ fuzzy::CharBag, language::LanguageRegistry, rpc::{self, proto, Status}, - time::{self, ReplicaId}, util::{Bias, TryFutureExt}, }; use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Result}; +use clock::ReplicaId; use futures::{Stream, StreamExt}; use gpui::{ executor, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, @@ -1847,9 +1847,9 @@ impl buffer::File for File { &self, buffer_id: u64, text: Rope, - version: time::Global, + version: clock::Global, cx: &mut MutableAppContext, - ) -> Task> { + ) -> Task> { self.worktree.update(cx, |worktree, cx| match worktree { Worktree::Local(worktree) => { let rpc = worktree.rpc.clone();