Extract a BufferStore object from Project (#14037)

This is a ~small~ pure refactor that's a step toward SSH remoting. I've
extracted the Project's buffer state management into a smaller, separate
struct called `BufferStore`, currently in the same crate. I did this as
a separate PR to reduce conflicts between main and `remoting-over-ssh`.

The idea is to make use of this struct (and other smaller structs that
make up `Project`) in a dedicated, simpler `HeadlessProject` type that
we will use in the SSH server to model the remote end of a project. With
this approach, as we develop the headless project, we can avoid adding
more conditional logic to `Project` itself (which is already very
complex), and actually make `Project` a bit smaller by extracting out
helper objects.

Release Notes:

- N/A
This commit is contained in:
Max Brunsfeld 2024-07-12 15:25:54 -07:00 committed by GitHub
parent 21c5ce2bbd
commit 489077befc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 1394 additions and 1115 deletions

View file

@ -37,7 +37,7 @@ use postage::{
prelude::{Sink as _, Stream as _},
watch,
};
use rpc::proto::{self, EnvelopedMessage as _, RequestMessage};
use rpc::proto::{self, AnyProtoClient};
use settings::{Settings, SettingsLocation, SettingsStore};
use smol::channel::{self, Sender};
use std::{
@ -131,7 +131,7 @@ pub struct RemoteWorktree {
snapshot: Snapshot,
background_snapshot: Arc<Mutex<Snapshot>>,
project_id: u64,
client: Box<dyn RemoteWorktreeClient>,
client: AnyProtoClient,
updates_tx: Option<UnboundedSender<proto::UpdateWorktree>>,
update_observer: Arc<
Mutex<Option<Box<dyn Send + FnMut(proto::UpdateWorktree) -> BoxFuture<'static, bool>>>>,
@ -142,14 +142,6 @@ pub struct RemoteWorktree {
disconnected: bool,
}
pub trait RemoteWorktreeClient {
fn request(
&self,
envelope: proto::Envelope,
request_type: &'static str,
) -> BoxFuture<'static, Result<proto::Envelope>>;
}
#[derive(Clone)]
pub struct Snapshot {
id: WorktreeId,
@ -461,7 +453,7 @@ impl Worktree {
project_id: u64,
replica_id: ReplicaId,
worktree: proto::WorktreeMetadata,
client: Box<dyn RemoteWorktreeClient>,
client: AnyProtoClient,
cx: &mut AppContext,
) -> Model<Self> {
cx.new_model(|cx: &mut ModelContext<Self>| {
@ -706,7 +698,7 @@ impl Worktree {
Worktree::Local(this) => this.create_entry(path, is_directory, cx),
Worktree::Remote(this) => {
let project_id = this.project_id;
let request = this.rpc_request(proto::CreateProjectEntry {
let request = this.client.request(proto::CreateProjectEntry {
worktree_id: worktree_id.to_proto(),
project_id,
path: path.to_string_lossy().into(),
@ -748,7 +740,7 @@ impl Worktree {
match self {
Worktree::Local(this) => this.delete_entry(entry_id, trash, cx),
Worktree::Remote(this) => {
let response = this.rpc_request(proto::DeleteProjectEntry {
let response = this.client.request(proto::DeleteProjectEntry {
project_id: this.project_id,
entry_id: entry_id.to_proto(),
use_trash: trash,
@ -778,7 +770,7 @@ impl Worktree {
match self {
Worktree::Local(this) => this.rename_entry(entry_id, new_path, cx),
Worktree::Remote(this) => {
let response = this.rpc_request(proto::RenameProjectEntry {
let response = this.client.request(proto::RenameProjectEntry {
project_id: this.project_id,
entry_id: entry_id.to_proto(),
new_path: new_path.to_string_lossy().into(),
@ -820,7 +812,7 @@ impl Worktree {
match self {
Worktree::Local(this) => this.copy_entry(entry_id, new_path, cx),
Worktree::Remote(this) => {
let response = this.rpc_request(proto::CopyProjectEntry {
let response = this.client.request(proto::CopyProjectEntry {
project_id: this.project_id,
entry_id: entry_id.to_proto(),
new_path: new_path.to_string_lossy().into(),
@ -870,7 +862,7 @@ impl Worktree {
match self {
Worktree::Local(this) => this.expand_entry(entry_id, cx),
Worktree::Remote(this) => {
let response = this.rpc_request(proto::ExpandProjectEntry {
let response = this.client.request(proto::ExpandProjectEntry {
project_id: this.project_id,
entry_id: entry_id.to_proto(),
});
@ -1811,24 +1803,20 @@ impl LocalWorktree {
}
impl RemoteWorktree {
pub fn project_id(&self) -> u64 {
self.project_id
}
pub fn client(&self) -> AnyProtoClient {
self.client.clone()
}
pub fn disconnected_from_host(&mut self) {
self.updates_tx.take();
self.snapshot_subscriptions.clear();
self.disconnected = true;
}
fn rpc_request<T: RequestMessage>(
&self,
request: T,
) -> impl Future<Output = Result<T::Response>> {
let envelope = request.into_envelope(0, None, None);
let response = self.client.request(envelope, T::NAME);
async move {
T::Response::from_envelope(response.await?)
.ok_or_else(|| anyhow!("received response of the wrong type"))
}
}
pub fn update_from_remote(&mut self, update: proto::UpdateWorktree) {
if let Some(updates_tx) = &self.updates_tx {
updates_tx