mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-29 05:33:49 +00:00
Introduce a File trait object to buffer
This will remove the dependency of buffer on `worktree::File`
This commit is contained in:
parent
7728467790
commit
f00045544f
5 changed files with 216 additions and 138 deletions
|
@ -1383,7 +1383,7 @@ mod tests {
|
|||
.update(&mut cx_b, |worktree, cx| worktree.open_buffer("a.txt", cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let mtime = buffer_b.read_with(&cx_b, |buf, _| buf.file().unwrap().mtime);
|
||||
let mtime = buffer_b.read_with(&cx_b, |buf, _| buf.file().unwrap().mtime());
|
||||
|
||||
buffer_b.update(&mut cx_b, |buf, cx| buf.edit([0..0], "world ", cx));
|
||||
buffer_b.read_with(&cx_b, |buf, _| {
|
||||
|
@ -1398,7 +1398,7 @@ mod tests {
|
|||
.unwrap();
|
||||
worktree_b
|
||||
.condition(&cx_b, |_, cx| {
|
||||
buffer_b.read(cx).file().unwrap().mtime != mtime
|
||||
buffer_b.read(cx).file().unwrap().mtime() != mtime
|
||||
})
|
||||
.await;
|
||||
buffer_b.read_with(&cx_b, |buf, _| {
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
time::ReplicaId,
|
||||
util::{post_inc, Bias},
|
||||
workspace,
|
||||
worktree::{File, Worktree},
|
||||
worktree::Worktree,
|
||||
};
|
||||
use anyhow::Result;
|
||||
pub use buffer::*;
|
||||
|
@ -2554,10 +2554,6 @@ impl View for Editor {
|
|||
impl workspace::Item for Buffer {
|
||||
type View = Editor;
|
||||
|
||||
fn file(&self) -> Option<&File> {
|
||||
self.file()
|
||||
}
|
||||
|
||||
fn build_view(
|
||||
handle: ModelHandle<Self>,
|
||||
settings: watch::Receiver<Settings>,
|
||||
|
@ -2592,6 +2588,10 @@ impl workspace::Item for Buffer {
|
|||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
fn worktree_id_and_path(&self) -> Option<(usize, Arc<Path>)> {
|
||||
self.file().map(|f| (f.worktree_id(), f.path().clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl workspace::ItemView for Editor {
|
||||
|
@ -2623,8 +2623,11 @@ impl workspace::ItemView for Editor {
|
|||
}
|
||||
}
|
||||
|
||||
fn entry_id(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)> {
|
||||
self.buffer.read(cx).file().map(|file| file.entry_id())
|
||||
fn worktree_id_and_path(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)> {
|
||||
self.buffer
|
||||
.read(cx)
|
||||
.file()
|
||||
.map(|file| (file.worktree_id(), file.path().clone()))
|
||||
}
|
||||
|
||||
fn clone_on_split(&self, cx: &mut ViewContext<Self>) -> Option<Self>
|
||||
|
@ -2678,7 +2681,7 @@ impl workspace::ItemView for Editor {
|
|||
});
|
||||
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.did_save(version, new_file.mtime, Some(new_file), cx);
|
||||
buffer.did_save(version, new_file.mtime, Some(Box::new(new_file)), cx);
|
||||
buffer.set_language(language, cx);
|
||||
});
|
||||
})
|
||||
|
|
|
@ -9,11 +9,10 @@ use crate::{
|
|||
settings::{HighlightId, HighlightMap},
|
||||
time::{self, ReplicaId},
|
||||
util::Bias,
|
||||
worktree::File,
|
||||
};
|
||||
pub use anchor::*;
|
||||
use anyhow::{anyhow, Result};
|
||||
use gpui::{AppContext, Entity, ModelContext, Task};
|
||||
use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task};
|
||||
use lazy_static::lazy_static;
|
||||
use operation_queue::OperationQueue;
|
||||
use parking_lot::Mutex;
|
||||
|
@ -23,13 +22,15 @@ use seahash::SeaHasher;
|
|||
pub use selection::*;
|
||||
use similar::{ChangeTag, TextDiff};
|
||||
use std::{
|
||||
any::Any,
|
||||
cell::RefCell,
|
||||
cmp,
|
||||
convert::{TryFrom, TryInto},
|
||||
ffi::OsString,
|
||||
hash::BuildHasher,
|
||||
iter::Iterator,
|
||||
ops::{Deref, DerefMut, Range},
|
||||
path::Path,
|
||||
path::{Path, PathBuf},
|
||||
str,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
|
||||
|
@ -38,6 +39,46 @@ use sum_tree::{self, FilterCursor, SumTree};
|
|||
use tree_sitter::{InputEdit, Parser, QueryCursor};
|
||||
use zrpc::proto;
|
||||
|
||||
pub trait File {
|
||||
fn worktree_id(&self) -> usize;
|
||||
|
||||
fn entry_id(&self) -> Option<usize>;
|
||||
|
||||
fn set_entry_id(&mut self, entry_id: Option<usize>);
|
||||
|
||||
fn mtime(&self) -> SystemTime;
|
||||
|
||||
fn set_mtime(&mut self, mtime: SystemTime);
|
||||
|
||||
fn path(&self) -> &Arc<Path>;
|
||||
|
||||
fn set_path(&mut self, path: Arc<Path>);
|
||||
|
||||
fn full_path(&self, cx: &AppContext) -> PathBuf;
|
||||
|
||||
/// Returns the last component of this handle's absolute path. If this handle refers to the root
|
||||
/// of its worktree, then this method will return the name of the worktree itself.
|
||||
fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString>;
|
||||
|
||||
fn is_deleted(&self) -> bool;
|
||||
|
||||
fn save(
|
||||
&self,
|
||||
buffer_id: u64,
|
||||
text: Rope,
|
||||
version: time::Global,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Task<Result<(time::Global, SystemTime)>>;
|
||||
|
||||
fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
|
||||
|
||||
fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
|
||||
|
||||
fn boxed_clone(&self) -> Box<dyn File>;
|
||||
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct DeterministicState;
|
||||
|
||||
|
@ -115,7 +156,7 @@ pub struct Buffer {
|
|||
last_edit: time::Local,
|
||||
undo_map: UndoMap,
|
||||
history: History,
|
||||
file: Option<File>,
|
||||
file: Option<Box<dyn File>>,
|
||||
language: Option<Arc<Language>>,
|
||||
sync_parse_timeout: Duration,
|
||||
syntax_tree: Mutex<Option<SyntaxTree>>,
|
||||
|
@ -524,7 +565,7 @@ impl Buffer {
|
|||
pub fn from_history(
|
||||
replica_id: ReplicaId,
|
||||
history: History,
|
||||
file: Option<File>,
|
||||
file: Option<Box<dyn File>>,
|
||||
language: Option<Arc<Language>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
|
@ -541,14 +582,14 @@ impl Buffer {
|
|||
fn build(
|
||||
replica_id: ReplicaId,
|
||||
history: History,
|
||||
file: Option<File>,
|
||||
file: Option<Box<dyn File>>,
|
||||
remote_id: u64,
|
||||
language: Option<Arc<Language>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
let saved_mtime;
|
||||
if let Some(file) = file.as_ref() {
|
||||
saved_mtime = file.mtime;
|
||||
saved_mtime = file.mtime();
|
||||
} else {
|
||||
saved_mtime = UNIX_EPOCH;
|
||||
}
|
||||
|
@ -619,7 +660,7 @@ impl Buffer {
|
|||
pub fn from_proto(
|
||||
replica_id: ReplicaId,
|
||||
message: proto::Buffer,
|
||||
file: Option<File>,
|
||||
file: Option<Box<dyn File>>,
|
||||
language: Option<Arc<Language>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Result<Self> {
|
||||
|
@ -678,12 +719,12 @@ impl Buffer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn file(&self) -> Option<&File> {
|
||||
self.file.as_ref()
|
||||
pub fn file(&self) -> Option<&dyn File> {
|
||||
self.file.as_deref()
|
||||
}
|
||||
|
||||
pub fn file_mut(&mut self) -> Option<&mut File> {
|
||||
self.file.as_mut()
|
||||
pub fn file_mut(&mut self) -> Option<&mut dyn File> {
|
||||
self.file.as_mut().map(|f| f.deref_mut() as &mut dyn File)
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
|
@ -719,7 +760,7 @@ impl Buffer {
|
|||
&mut self,
|
||||
version: time::Global,
|
||||
mtime: SystemTime,
|
||||
new_file: Option<File>,
|
||||
new_file: Option<Box<dyn File>>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
self.saved_mtime = mtime;
|
||||
|
@ -739,13 +780,13 @@ impl Buffer {
|
|||
) {
|
||||
let file = self.file.as_mut().unwrap();
|
||||
let mut changed = false;
|
||||
if path != file.path {
|
||||
file.path = path;
|
||||
if path != *file.path() {
|
||||
file.set_path(path);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if mtime != file.mtime {
|
||||
file.mtime = mtime;
|
||||
if mtime != file.mtime() {
|
||||
file.set_mtime(mtime);
|
||||
changed = true;
|
||||
if let Some(new_text) = new_text {
|
||||
if self.version == self.saved_version {
|
||||
|
@ -1015,7 +1056,7 @@ impl Buffer {
|
|||
&& self
|
||||
.file
|
||||
.as_ref()
|
||||
.map_or(false, |file| file.mtime > self.saved_mtime)
|
||||
.map_or(false, |file| file.mtime() > self.saved_mtime)
|
||||
}
|
||||
|
||||
pub fn remote_id(&self) -> u64 {
|
||||
|
@ -1930,7 +1971,7 @@ impl Clone for Buffer {
|
|||
history: self.history.clone(),
|
||||
selections: self.selections.clone(),
|
||||
deferred_ops: self.deferred_ops.clone(),
|
||||
file: self.file.clone(),
|
||||
file: self.file.as_ref().map(|f| f.boxed_clone()),
|
||||
language: self.language.clone(),
|
||||
syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
|
||||
parsing_in_background: false,
|
||||
|
@ -3415,7 +3456,7 @@ mod tests {
|
|||
assert!(buffer.is_dirty());
|
||||
assert_eq!(*events.borrow(), &[Event::Edited, Event::Dirtied]);
|
||||
events.borrow_mut().clear();
|
||||
buffer.did_save(buffer.version(), buffer.file().unwrap().mtime, None, cx);
|
||||
buffer.did_save(buffer.version(), buffer.file().unwrap().mtime(), None, cx);
|
||||
});
|
||||
|
||||
// after saving, the buffer is not dirty, and emits a saved event.
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
settings::Settings,
|
||||
user,
|
||||
workspace::sidebar::{Side, Sidebar, SidebarItemId, ToggleSidebarItem, ToggleSidebarItemFocus},
|
||||
worktree::{File, Worktree},
|
||||
worktree::Worktree,
|
||||
AppState, Authenticate,
|
||||
};
|
||||
use anyhow::Result;
|
||||
|
@ -164,12 +164,12 @@ pub trait Item: Entity + Sized {
|
|||
cx: &mut ViewContext<Self::View>,
|
||||
) -> Self::View;
|
||||
|
||||
fn file(&self) -> Option<&File>;
|
||||
fn worktree_id_and_path(&self) -> Option<(usize, Arc<Path>)>;
|
||||
}
|
||||
|
||||
pub trait ItemView: View {
|
||||
fn title(&self, cx: &AppContext) -> String;
|
||||
fn entry_id(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)>;
|
||||
fn worktree_id_and_path(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)>;
|
||||
fn clone_on_split(&self, _: &mut ViewContext<Self>) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -206,7 +206,6 @@ pub trait ItemHandle: Send + Sync {
|
|||
}
|
||||
|
||||
pub trait WeakItemHandle {
|
||||
fn file<'a>(&'a self, cx: &'a AppContext) -> Option<&'a File>;
|
||||
fn add_view(
|
||||
&self,
|
||||
window_id: usize,
|
||||
|
@ -214,6 +213,7 @@ pub trait WeakItemHandle {
|
|||
cx: &mut MutableAppContext,
|
||||
) -> Option<Box<dyn ItemViewHandle>>;
|
||||
fn alive(&self, cx: &AppContext) -> bool;
|
||||
fn worktree_id_and_path(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)>;
|
||||
}
|
||||
|
||||
pub trait ItemViewHandle {
|
||||
|
@ -246,10 +246,6 @@ impl<T: Item> ItemHandle for ModelHandle<T> {
|
|||
}
|
||||
|
||||
impl<T: Item> WeakItemHandle for WeakModelHandle<T> {
|
||||
fn file<'a>(&'a self, cx: &'a AppContext) -> Option<&'a File> {
|
||||
self.upgrade(cx).and_then(|h| h.read(cx).file())
|
||||
}
|
||||
|
||||
fn add_view(
|
||||
&self,
|
||||
window_id: usize,
|
||||
|
@ -268,6 +264,11 @@ impl<T: Item> WeakItemHandle for WeakModelHandle<T> {
|
|||
fn alive(&self, cx: &AppContext) -> bool {
|
||||
self.upgrade(cx).is_some()
|
||||
}
|
||||
|
||||
fn worktree_id_and_path(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)> {
|
||||
self.upgrade(cx)
|
||||
.and_then(|h| h.read(cx).worktree_id_and_path())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ItemView> ItemViewHandle for ViewHandle<T> {
|
||||
|
@ -276,7 +277,7 @@ impl<T: ItemView> ItemViewHandle for ViewHandle<T> {
|
|||
}
|
||||
|
||||
fn entry_id(&self, cx: &AppContext) -> Option<(usize, Arc<Path>)> {
|
||||
self.read(cx).entry_id(cx)
|
||||
self.read(cx).worktree_id_and_path(cx)
|
||||
}
|
||||
|
||||
fn boxed_clone(&self) -> Box<dyn ItemViewHandle> {
|
||||
|
@ -717,9 +718,7 @@ impl Workspace {
|
|||
self.items.retain(|item| {
|
||||
if item.alive(cx.as_ref()) {
|
||||
if view_for_existing_item.is_none()
|
||||
&& item
|
||||
.file(cx.as_ref())
|
||||
.map_or(false, |file| file.entry_id() == entry)
|
||||
&& item.worktree_id_and_path(cx).map_or(false, |e| e == entry)
|
||||
{
|
||||
view_for_existing_item = Some(
|
||||
item.add_view(cx.window_id(), settings.clone(), cx.as_mut())
|
||||
|
|
|
@ -2,7 +2,7 @@ mod ignore;
|
|||
|
||||
use self::ignore::IgnoreStack;
|
||||
use crate::{
|
||||
editor::{self, Buffer, History, Operation, Rope},
|
||||
editor::{self, buffer, Buffer, History, Operation, Rope},
|
||||
fs::{self, Fs},
|
||||
fuzzy::CharBag,
|
||||
language::LanguageRegistry,
|
||||
|
@ -25,21 +25,10 @@ use postage::{
|
|||
};
|
||||
use serde::Deserialize;
|
||||
use smol::channel::{self, Sender};
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
collections::HashMap,
|
||||
convert::{TryFrom, TryInto},
|
||||
ffi::{OsStr, OsString},
|
||||
fmt,
|
||||
future::Future,
|
||||
ops::Deref,
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
use std::{any::Any, cmp::{self, Ordering}, collections::HashMap, convert::{TryFrom, TryInto}, ffi::{OsStr, OsString}, fmt, future::Future, ops::Deref, path::{Path, PathBuf}, sync::{
|
||||
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
Arc,
|
||||
},
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
}, time::{Duration, SystemTime}};
|
||||
use sum_tree::{self, Edit, SeekTarget, SumTree};
|
||||
use zrpc::{PeerId, TypedEnvelope};
|
||||
|
||||
|
@ -404,7 +393,7 @@ impl Worktree {
|
|||
open_buffers
|
||||
.find(|buffer| {
|
||||
if let Some(file) = buffer.upgrade(cx).and_then(|buffer| buffer.read(cx).file()) {
|
||||
file.path.as_ref() == path
|
||||
file.path().as_ref() == path
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -599,30 +588,30 @@ impl Worktree {
|
|||
let mut file_changed = false;
|
||||
|
||||
if let Some(entry) = file
|
||||
.entry_id
|
||||
.entry_id()
|
||||
.and_then(|entry_id| self.entry_for_id(entry_id))
|
||||
{
|
||||
if entry.path != file.path {
|
||||
file.path = entry.path.clone();
|
||||
if entry.path != *file.path() {
|
||||
file.set_path(entry.path.clone());
|
||||
file_changed = true;
|
||||
}
|
||||
|
||||
if entry.mtime != file.mtime {
|
||||
file.mtime = entry.mtime;
|
||||
if entry.mtime != file.mtime() {
|
||||
file.set_mtime(entry.mtime);
|
||||
file_changed = true;
|
||||
if let Some(worktree) = self.as_local() {
|
||||
if buffer_is_clean {
|
||||
let abs_path = worktree.absolutize(&file.path);
|
||||
let abs_path = worktree.absolutize(file.path().as_ref());
|
||||
refresh_buffer(abs_path, &worktree.fs, cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(entry) = self.entry_for_path(&file.path) {
|
||||
file.entry_id = Some(entry.id);
|
||||
file.mtime = entry.mtime;
|
||||
} else if let Some(entry) = self.entry_for_path(file.path().as_ref()) {
|
||||
file.set_entry_id(Some(entry.id));
|
||||
file.set_mtime(entry.mtime);
|
||||
if let Some(worktree) = self.as_local() {
|
||||
if buffer_is_clean {
|
||||
let abs_path = worktree.absolutize(&file.path);
|
||||
let abs_path = worktree.absolutize(file.path().as_ref());
|
||||
refresh_buffer(abs_path, &worktree.fs, cx);
|
||||
}
|
||||
}
|
||||
|
@ -631,7 +620,7 @@ impl Worktree {
|
|||
if buffer_is_clean {
|
||||
cx.emit(editor::buffer::Event::Dirtied);
|
||||
}
|
||||
file.entry_id = None;
|
||||
file.set_entry_id(None);
|
||||
file_changed = true;
|
||||
}
|
||||
|
||||
|
@ -845,7 +834,7 @@ impl LocalWorktree {
|
|||
self.open_buffers.retain(|_buffer_id, buffer| {
|
||||
if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
|
||||
if let Some(file) = buffer.read(cx.as_ref()).file() {
|
||||
if file.worktree_id() == handle.id() && file.path.as_ref() == path {
|
||||
if file.worktree_id() == handle.id() && file.path().as_ref() == path {
|
||||
existing_buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
|
@ -864,12 +853,20 @@ impl LocalWorktree {
|
|||
.update(&mut cx, |this, cx| this.as_local().unwrap().load(&path, cx))
|
||||
.await?;
|
||||
let language = this.read_with(&cx, |this, cx| {
|
||||
use buffer::File;
|
||||
|
||||
this.languages()
|
||||
.select_language(file.full_path(cx))
|
||||
.cloned()
|
||||
});
|
||||
let buffer = cx.add_model(|cx| {
|
||||
Buffer::from_history(0, History::new(contents.into()), Some(file), language, cx)
|
||||
Buffer::from_history(
|
||||
0,
|
||||
History::new(contents.into()),
|
||||
Some(Box::new(file)),
|
||||
language,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
this.update(&mut cx, |this, _| {
|
||||
let this = this
|
||||
|
@ -1238,7 +1235,7 @@ impl RemoteWorktree {
|
|||
self.open_buffers.retain(|_buffer_id, buffer| {
|
||||
if let Some(buffer) = buffer.upgrade(cx.as_ref()) {
|
||||
if let Some(file) = buffer.read(cx.as_ref()).file() {
|
||||
if file.worktree_id() == cx.model_id() && file.path.as_ref() == path {
|
||||
if file.worktree_id() == cx.model_id() && file.path().as_ref() == path {
|
||||
existing_buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
|
@ -1273,6 +1270,8 @@ impl RemoteWorktree {
|
|||
.ok_or_else(|| anyhow!("worktree was closed"))?;
|
||||
let file = File::new(entry.id, this.clone(), entry.path, entry.mtime);
|
||||
let language = this.read_with(&cx, |this, cx| {
|
||||
use buffer::File;
|
||||
|
||||
this.languages()
|
||||
.select_language(file.full_path(cx))
|
||||
.cloned()
|
||||
|
@ -1280,7 +1279,14 @@ impl RemoteWorktree {
|
|||
let remote_buffer = response.buffer.ok_or_else(|| anyhow!("empty buffer"))?;
|
||||
let buffer_id = remote_buffer.id as usize;
|
||||
let buffer = cx.add_model(|cx| {
|
||||
Buffer::from_proto(replica_id, remote_buffer, Some(file), language, cx).unwrap()
|
||||
Buffer::from_proto(
|
||||
replica_id,
|
||||
remote_buffer,
|
||||
Some(Box::new(file)),
|
||||
language,
|
||||
cx,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let this = this.as_remote_mut().unwrap();
|
||||
|
@ -1774,67 +1780,45 @@ impl File {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext) {
|
||||
self.worktree.update(cx, |worktree, cx| {
|
||||
if let Some((rpc, remote_id)) = match worktree {
|
||||
Worktree::Local(worktree) => worktree
|
||||
.remote_id
|
||||
.borrow()
|
||||
.map(|id| (worktree.rpc.clone(), id)),
|
||||
Worktree::Remote(worktree) => Some((worktree.rpc.clone(), worktree.remote_id)),
|
||||
} {
|
||||
cx.spawn(|worktree, mut cx| async move {
|
||||
if let Err(error) = rpc
|
||||
.request(proto::UpdateBuffer {
|
||||
worktree_id: remote_id,
|
||||
buffer_id,
|
||||
operations: vec![(&operation).into()],
|
||||
})
|
||||
.await
|
||||
{
|
||||
worktree.update(&mut cx, |worktree, _| {
|
||||
log::error!("error sending buffer operation: {}", error);
|
||||
match worktree {
|
||||
Worktree::Local(t) => &mut t.queued_operations,
|
||||
Worktree::Remote(t) => &mut t.queued_operations,
|
||||
}
|
||||
.push((buffer_id, operation));
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
});
|
||||
// pub fn exists(&self) -> bool {
|
||||
// !self.is_deleted()
|
||||
// }
|
||||
|
||||
pub fn worktree_id_and_path(&self) -> (usize, Arc<Path>) {
|
||||
(self.worktree.id(), self.path.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl buffer::File for File {
|
||||
fn worktree_id(&self) -> usize {
|
||||
self.worktree.id()
|
||||
}
|
||||
|
||||
pub fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext) {
|
||||
self.worktree.update(cx, |worktree, cx| {
|
||||
if let Worktree::Remote(worktree) = worktree {
|
||||
let worktree_id = worktree.remote_id;
|
||||
let rpc = worktree.rpc.clone();
|
||||
cx.background()
|
||||
.spawn(async move {
|
||||
if let Err(error) = rpc
|
||||
.send(proto::CloseBuffer {
|
||||
worktree_id,
|
||||
buffer_id,
|
||||
})
|
||||
.await
|
||||
{
|
||||
log::error!("error closing remote buffer: {}", error);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
});
|
||||
fn entry_id(&self) -> Option<usize> {
|
||||
self.entry_id
|
||||
}
|
||||
|
||||
/// Returns this file's path relative to the root of its worktree.
|
||||
pub fn path(&self) -> Arc<Path> {
|
||||
self.path.clone()
|
||||
fn set_entry_id(&mut self, entry_id: Option<usize>) {
|
||||
self.entry_id = entry_id;
|
||||
}
|
||||
|
||||
pub fn full_path(&self, cx: &AppContext) -> PathBuf {
|
||||
fn mtime(&self) -> SystemTime {
|
||||
self.mtime
|
||||
}
|
||||
|
||||
fn set_mtime(&mut self, mtime: SystemTime) {
|
||||
self.mtime = mtime;
|
||||
}
|
||||
|
||||
fn path(&self) -> &Arc<Path> {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn set_path(&mut self, path: Arc<Path>) {
|
||||
self.path = path;
|
||||
}
|
||||
|
||||
fn full_path(&self, cx: &AppContext) -> PathBuf {
|
||||
let worktree = self.worktree.read(cx);
|
||||
let mut full_path = PathBuf::new();
|
||||
full_path.push(worktree.root_name());
|
||||
|
@ -1844,22 +1828,18 @@ impl File {
|
|||
|
||||
/// Returns the last component of this handle's absolute path. If this handle refers to the root
|
||||
/// of its worktree, then this method will return the name of the worktree itself.
|
||||
pub fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString> {
|
||||
fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString> {
|
||||
self.path
|
||||
.file_name()
|
||||
.or_else(|| Some(OsStr::new(self.worktree.read(cx).root_name())))
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
pub fn is_deleted(&self) -> bool {
|
||||
fn is_deleted(&self) -> bool {
|
||||
self.entry_id.is_none()
|
||||
}
|
||||
|
||||
pub fn exists(&self) -> bool {
|
||||
!self.is_deleted()
|
||||
}
|
||||
|
||||
pub fn save(
|
||||
fn save(
|
||||
&self,
|
||||
buffer_id: u64,
|
||||
text: Rope,
|
||||
|
@ -1906,12 +1886,67 @@ impl File {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn worktree_id(&self) -> usize {
|
||||
self.worktree.id()
|
||||
fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext) {
|
||||
self.worktree.update(cx, |worktree, cx| {
|
||||
if let Some((rpc, remote_id)) = match worktree {
|
||||
Worktree::Local(worktree) => worktree
|
||||
.remote_id
|
||||
.borrow()
|
||||
.map(|id| (worktree.rpc.clone(), id)),
|
||||
Worktree::Remote(worktree) => Some((worktree.rpc.clone(), worktree.remote_id)),
|
||||
} {
|
||||
cx.spawn(|worktree, mut cx| async move {
|
||||
if let Err(error) = rpc
|
||||
.request(proto::UpdateBuffer {
|
||||
worktree_id: remote_id,
|
||||
buffer_id,
|
||||
operations: vec![(&operation).into()],
|
||||
})
|
||||
.await
|
||||
{
|
||||
worktree.update(&mut cx, |worktree, _| {
|
||||
log::error!("error sending buffer operation: {}", error);
|
||||
match worktree {
|
||||
Worktree::Local(t) => &mut t.queued_operations,
|
||||
Worktree::Remote(t) => &mut t.queued_operations,
|
||||
}
|
||||
.push((buffer_id, operation));
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn entry_id(&self) -> (usize, Arc<Path>) {
|
||||
(self.worktree.id(), self.path.clone())
|
||||
fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext) {
|
||||
self.worktree.update(cx, |worktree, cx| {
|
||||
if let Worktree::Remote(worktree) = worktree {
|
||||
let worktree_id = worktree.remote_id;
|
||||
let rpc = worktree.rpc.clone();
|
||||
cx.background()
|
||||
.spawn(async move {
|
||||
if let Err(error) = rpc
|
||||
.send(proto::CloseBuffer {
|
||||
worktree_id,
|
||||
buffer_id,
|
||||
})
|
||||
.await
|
||||
{
|
||||
log::error!("error closing remote buffer: {}", error);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn boxed_clone(&self) -> Box<dyn buffer::File> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue