mirror of
https://github.com/zed-industries/zed.git
synced 2024-10-25 16:09:44 +00:00
Emit Dirtied
event when a clean buffer's file is deleted
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
02bd9c8420
commit
d8eed53f13
2 changed files with 54 additions and 19 deletions
|
@ -1620,7 +1620,7 @@ impl<'a, T: Entity> ModelContext<'a, T> {
|
|||
});
|
||||
}
|
||||
|
||||
fn handle(&self) -> ModelHandle<T> {
|
||||
pub fn handle(&self) -> ModelHandle<T> {
|
||||
ModelHandle::new(self.model_id, &self.app.ctx.ref_counts)
|
||||
}
|
||||
|
||||
|
|
|
@ -377,7 +377,12 @@ impl Buffer {
|
|||
ctx: &mut ModelContext<Self>,
|
||||
) -> Self {
|
||||
if let Some(file) = file.as_ref() {
|
||||
file.observe_from_model(ctx, |_, _, ctx| ctx.emit(Event::FileHandleChanged));
|
||||
file.observe_from_model(ctx, |this, file, ctx| {
|
||||
if this.version == this.saved_version && file.is_deleted() {
|
||||
ctx.emit(Event::Dirtied);
|
||||
}
|
||||
ctx.emit(Event::FileHandleChanged);
|
||||
});
|
||||
}
|
||||
|
||||
let mut insertion_splits = HashMap::default();
|
||||
|
@ -2989,19 +2994,21 @@ mod tests {
|
|||
App::test_async((), |mut app| async move {
|
||||
let dir = temp_tree(json!({
|
||||
"file1": "",
|
||||
"file2": "",
|
||||
"file3": "",
|
||||
}));
|
||||
let tree = app.add_model(|ctx| Worktree::new(dir.path(), ctx));
|
||||
app.read(|ctx| tree.read(ctx).scan_complete()).await;
|
||||
|
||||
let file = app.read(|ctx| tree.file("file1", ctx));
|
||||
let model = app.add_model(|ctx| {
|
||||
Buffer::from_history(0, History::new("abc".into()), Some(file), ctx)
|
||||
let file1 = app.read(|ctx| tree.file("file1", ctx));
|
||||
let buffer1 = app.add_model(|ctx| {
|
||||
Buffer::from_history(0, History::new("abc".into()), Some(file1), ctx)
|
||||
});
|
||||
let events = Rc::new(RefCell::new(Vec::new()));
|
||||
|
||||
// initially, the buffer isn't dirty.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
ctx.subscribe(&model, {
|
||||
buffer1.update(&mut app, |buffer, ctx| {
|
||||
ctx.subscribe(&buffer1, {
|
||||
let events = events.clone();
|
||||
move |_, event, _| events.borrow_mut().push(event.clone())
|
||||
});
|
||||
|
@ -3013,7 +3020,7 @@ mod tests {
|
|||
});
|
||||
|
||||
// after the first edit, the buffer is dirty, and emits a dirtied event.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
buffer1.update(&mut app, |buffer, ctx| {
|
||||
assert!(buffer.text() == "ac");
|
||||
assert!(buffer.is_dirty());
|
||||
assert_eq!(*events.borrow(), &[Event::Edited, Event::Dirtied]);
|
||||
|
@ -3023,7 +3030,7 @@ mod tests {
|
|||
});
|
||||
|
||||
// after saving, the buffer is not dirty, and emits a saved event.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
buffer1.update(&mut app, |buffer, ctx| {
|
||||
assert!(!buffer.is_dirty());
|
||||
assert_eq!(*events.borrow(), &[Event::Saved]);
|
||||
events.borrow_mut().clear();
|
||||
|
@ -3033,7 +3040,7 @@ mod tests {
|
|||
});
|
||||
|
||||
// after editing again, the buffer is dirty, and emits another dirty event.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
buffer1.update(&mut app, |buffer, ctx| {
|
||||
assert!(buffer.text() == "aBDc");
|
||||
assert!(buffer.is_dirty());
|
||||
assert_eq!(
|
||||
|
@ -3051,22 +3058,50 @@ mod tests {
|
|||
|
||||
assert_eq!(*events.borrow(), &[Event::Edited]);
|
||||
|
||||
// When the file is deleted, the buffer is considered dirty.
|
||||
model.update(&mut app, |buffer, ctx| {
|
||||
buffer.did_save(buffer.version(), None, ctx);
|
||||
assert!(!buffer.is_dirty());
|
||||
// When a file is deleted, the buffer is considered dirty.
|
||||
let events = Rc::new(RefCell::new(Vec::new()));
|
||||
let file2 = app.read(|ctx| tree.file("file2", ctx));
|
||||
let buffer2 = app.add_model(|ctx: &mut ModelContext<Buffer>| {
|
||||
ctx.subscribe(&ctx.handle(), {
|
||||
let events = events.clone();
|
||||
move |_, event, _| events.borrow_mut().push(event.clone())
|
||||
});
|
||||
|
||||
Buffer::from_history(0, History::new("abc".into()), Some(file2), ctx)
|
||||
});
|
||||
events.borrow_mut().clear();
|
||||
|
||||
tree.flush_fs_events(&app).await;
|
||||
fs::remove_file(dir.path().join("file1")).unwrap();
|
||||
fs::remove_file(dir.path().join("file2")).unwrap();
|
||||
tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
|
||||
.await;
|
||||
assert_eq!(
|
||||
*events.borrow(),
|
||||
&[Event::Dirtied, Event::FileHandleChanged]
|
||||
);
|
||||
app.read(|ctx| assert!(buffer2.read(ctx).is_dirty()));
|
||||
|
||||
model.update(&mut app, |buffer, _| {
|
||||
assert_eq!(*events.borrow(), &[Event::FileHandleChanged]);
|
||||
assert!(buffer.is_dirty());
|
||||
// When a file is already dirty when deleted, we don't emit a Dirtied event.
|
||||
let events = Rc::new(RefCell::new(Vec::new()));
|
||||
let file3 = app.read(|ctx| tree.file("file3", ctx));
|
||||
let buffer3 = app.add_model(|ctx: &mut ModelContext<Buffer>| {
|
||||
ctx.subscribe(&ctx.handle(), {
|
||||
let events = events.clone();
|
||||
move |_, event, _| events.borrow_mut().push(event.clone())
|
||||
});
|
||||
|
||||
Buffer::from_history(0, History::new("abc".into()), Some(file3), ctx)
|
||||
});
|
||||
|
||||
tree.flush_fs_events(&app).await;
|
||||
buffer3.update(&mut app, |buffer, ctx| {
|
||||
buffer.edit(Some(0..0), "x", Some(ctx)).unwrap();
|
||||
});
|
||||
events.borrow_mut().clear();
|
||||
fs::remove_file(dir.path().join("file3")).unwrap();
|
||||
tree.update(&mut app, |tree, ctx| tree.next_scan_complete(ctx))
|
||||
.await;
|
||||
assert_eq!(*events.borrow(), &[Event::FileHandleChanged]);
|
||||
app.read(|ctx| assert!(buffer3.read(ctx).is_dirty()));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue