Add File.disk_state
enum to clarify filesystem states (#20776)
Motivation for this is to make things more understandable while figuring out #20775. This is intended to be a refactoring that does not affect behavior, but there are a few tricky spots: * Previously `File.mtime()` (now `File.disk_state().mtime()`) would return last known modification time for deleted files. Looking at uses, I believe this will not affect anything. If there are behavior changes here I believe they would be improvements. * `BufferEvent::DirtyChanged` is now only emitted if dirtiness actually changed, rather than if it may have changed. This should only be an efficiency improvement. Release Notes: - N/A Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
df1d0dec0a
commit
d99f5fe83e
10 changed files with 161 additions and 134 deletions
|
@ -20,7 +20,7 @@ use language::{
|
|||
deserialize_line_ending, deserialize_version, serialize_line_ending, serialize_version,
|
||||
split_operations,
|
||||
},
|
||||
Buffer, BufferEvent, Capability, File as _, Language, Operation,
|
||||
Buffer, BufferEvent, Capability, DiskState, File as _, Language, Operation,
|
||||
};
|
||||
use rpc::{proto, AnyProtoClient, ErrorExt as _, TypedEnvelope};
|
||||
use smol::channel::Receiver;
|
||||
|
@ -434,7 +434,10 @@ impl LocalBufferStore {
|
|||
let line_ending = buffer.line_ending();
|
||||
let version = buffer.version();
|
||||
let buffer_id = buffer.remote_id();
|
||||
if buffer.file().is_some_and(|file| !file.is_created()) {
|
||||
if buffer
|
||||
.file()
|
||||
.is_some_and(|file| file.disk_state() == DiskState::New)
|
||||
{
|
||||
has_changed_file = true;
|
||||
}
|
||||
|
||||
|
@ -444,7 +447,7 @@ impl LocalBufferStore {
|
|||
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
let new_file = save.await?;
|
||||
let mtime = new_file.mtime;
|
||||
let mtime = new_file.disk_state().mtime();
|
||||
this.update(&mut cx, |this, cx| {
|
||||
if let Some((downstream_client, project_id)) = this.downstream_client(cx) {
|
||||
if has_changed_file {
|
||||
|
@ -658,37 +661,30 @@ impl LocalBufferStore {
|
|||
return None;
|
||||
}
|
||||
|
||||
let new_file = if let Some(entry) = old_file
|
||||
let snapshot_entry = old_file
|
||||
.entry_id
|
||||
.and_then(|entry_id| snapshot.entry_for_id(entry_id))
|
||||
{
|
||||
.or_else(|| snapshot.entry_for_path(old_file.path.as_ref()));
|
||||
|
||||
let new_file = if let Some(entry) = snapshot_entry {
|
||||
File {
|
||||
disk_state: match entry.mtime {
|
||||
Some(mtime) => DiskState::Present { mtime },
|
||||
None => old_file.disk_state,
|
||||
},
|
||||
is_local: true,
|
||||
entry_id: Some(entry.id),
|
||||
mtime: entry.mtime,
|
||||
path: entry.path.clone(),
|
||||
worktree: worktree.clone(),
|
||||
is_deleted: false,
|
||||
is_private: entry.is_private,
|
||||
}
|
||||
} else if let Some(entry) = snapshot.entry_for_path(old_file.path.as_ref()) {
|
||||
File {
|
||||
is_local: true,
|
||||
entry_id: Some(entry.id),
|
||||
mtime: entry.mtime,
|
||||
path: entry.path.clone(),
|
||||
worktree: worktree.clone(),
|
||||
is_deleted: false,
|
||||
is_private: entry.is_private,
|
||||
}
|
||||
} else {
|
||||
File {
|
||||
disk_state: DiskState::Deleted,
|
||||
is_local: true,
|
||||
entry_id: old_file.entry_id,
|
||||
path: old_file.path.clone(),
|
||||
mtime: old_file.mtime,
|
||||
worktree: worktree.clone(),
|
||||
is_deleted: true,
|
||||
is_private: old_file.is_private,
|
||||
}
|
||||
};
|
||||
|
@ -867,10 +863,9 @@ impl BufferStoreImpl for Model<LocalBufferStore> {
|
|||
Some(Arc::new(File {
|
||||
worktree,
|
||||
path,
|
||||
mtime: None,
|
||||
disk_state: DiskState::New,
|
||||
entry_id: None,
|
||||
is_local: true,
|
||||
is_deleted: false,
|
||||
is_private: false,
|
||||
})),
|
||||
Capability::ReadWrite,
|
||||
|
|
|
@ -9,7 +9,7 @@ use gpui::{
|
|||
hash, prelude::*, AppContext, EventEmitter, Img, Model, ModelContext, Subscription, Task,
|
||||
WeakModel,
|
||||
};
|
||||
use language::File;
|
||||
use language::{DiskState, File};
|
||||
use rpc::{AnyProtoClient, ErrorExt as _};
|
||||
use std::ffi::OsStr;
|
||||
use std::num::NonZeroU64;
|
||||
|
@ -74,11 +74,12 @@ impl ImageItem {
|
|||
file_changed = true;
|
||||
}
|
||||
|
||||
if !new_file.is_deleted() {
|
||||
let new_mtime = new_file.mtime();
|
||||
if new_mtime != old_file.mtime() {
|
||||
file_changed = true;
|
||||
cx.emit(ImageItemEvent::ReloadNeeded);
|
||||
let old_state = old_file.disk_state();
|
||||
let new_state = new_file.disk_state();
|
||||
if old_state != new_state {
|
||||
file_changed = true;
|
||||
if matches!(new_state, DiskState::Present { .. }) {
|
||||
cx.emit(ImageItemEvent::ReloadNeeded)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,37 +504,30 @@ impl LocalImageStore {
|
|||
return;
|
||||
}
|
||||
|
||||
let new_file = if let Some(entry) = old_file
|
||||
let snapshot_entry = old_file
|
||||
.entry_id
|
||||
.and_then(|entry_id| snapshot.entry_for_id(entry_id))
|
||||
{
|
||||
.or_else(|| snapshot.entry_for_path(old_file.path.as_ref()));
|
||||
|
||||
let new_file = if let Some(entry) = snapshot_entry {
|
||||
worktree::File {
|
||||
disk_state: match entry.mtime {
|
||||
Some(mtime) => DiskState::Present { mtime },
|
||||
None => old_file.disk_state,
|
||||
},
|
||||
is_local: true,
|
||||
entry_id: Some(entry.id),
|
||||
mtime: entry.mtime,
|
||||
path: entry.path.clone(),
|
||||
worktree: worktree.clone(),
|
||||
is_deleted: false,
|
||||
is_private: entry.is_private,
|
||||
}
|
||||
} else if let Some(entry) = snapshot.entry_for_path(old_file.path.as_ref()) {
|
||||
worktree::File {
|
||||
is_local: true,
|
||||
entry_id: Some(entry.id),
|
||||
mtime: entry.mtime,
|
||||
path: entry.path.clone(),
|
||||
worktree: worktree.clone(),
|
||||
is_deleted: false,
|
||||
is_private: entry.is_private,
|
||||
}
|
||||
} else {
|
||||
worktree::File {
|
||||
disk_state: DiskState::Deleted,
|
||||
is_local: true,
|
||||
entry_id: old_file.entry_id,
|
||||
path: old_file.path.clone(),
|
||||
mtime: old_file.mtime,
|
||||
worktree: worktree.clone(),
|
||||
is_deleted: true,
|
||||
is_private: old_file.is_private,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,12 +5,12 @@ use gpui::{AppContext, SemanticVersion, UpdateGlobal};
|
|||
use http_client::Url;
|
||||
use language::{
|
||||
language_settings::{language_settings, AllLanguageSettings, LanguageSettingsContent},
|
||||
tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticSet, FakeLspAdapter,
|
||||
tree_sitter_rust, tree_sitter_typescript, Diagnostic, DiagnosticSet, DiskState, FakeLspAdapter,
|
||||
LanguageConfig, LanguageMatcher, LanguageName, LineEnding, OffsetRangeExt, Point, ToPoint,
|
||||
};
|
||||
use lsp::{DiagnosticSeverity, NumberOrString};
|
||||
use parking_lot::Mutex;
|
||||
use pretty_assertions::assert_eq;
|
||||
use pretty_assertions::{assert_eq, assert_matches};
|
||||
use serde_json::json;
|
||||
#[cfg(not(windows))]
|
||||
use std::os;
|
||||
|
@ -3239,10 +3239,22 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
|
|||
Path::new("b/c/file5")
|
||||
);
|
||||
|
||||
assert!(!buffer2.read(cx).file().unwrap().is_deleted());
|
||||
assert!(!buffer3.read(cx).file().unwrap().is_deleted());
|
||||
assert!(!buffer4.read(cx).file().unwrap().is_deleted());
|
||||
assert!(buffer5.read(cx).file().unwrap().is_deleted());
|
||||
assert_matches!(
|
||||
buffer2.read(cx).file().unwrap().disk_state(),
|
||||
DiskState::Present { .. }
|
||||
);
|
||||
assert_matches!(
|
||||
buffer3.read(cx).file().unwrap().disk_state(),
|
||||
DiskState::Present { .. }
|
||||
);
|
||||
assert_matches!(
|
||||
buffer4.read(cx).file().unwrap().disk_state(),
|
||||
DiskState::Present { .. }
|
||||
);
|
||||
assert_eq!(
|
||||
buffer5.read(cx).file().unwrap().disk_state(),
|
||||
DiskState::Deleted
|
||||
);
|
||||
});
|
||||
|
||||
// Update the remote worktree. Check that it becomes consistent with the
|
||||
|
@ -3416,7 +3428,11 @@ async fn test_buffer_is_dirty(cx: &mut gpui::TestAppContext) {
|
|||
]
|
||||
);
|
||||
events.lock().clear();
|
||||
buffer.did_save(buffer.version(), buffer.file().unwrap().mtime(), cx);
|
||||
buffer.did_save(
|
||||
buffer.version(),
|
||||
buffer.file().unwrap().disk_state().mtime(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
// after saving, the buffer is not dirty, and emits a saved event.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue