Root rename detection (#20313)
Closes #5349 Release Notes: - Fixed Zed when the directory that you opened is renamed.
This commit is contained in:
parent
216ea4ddc4
commit
e645aa9d20
3 changed files with 196 additions and 4 deletions
|
@ -285,6 +285,9 @@ pub struct LocalSnapshot {
|
|||
/// All of the git repositories in the worktree, indexed by the project entry
|
||||
/// id of their parent directory.
|
||||
git_repositories: TreeMap<ProjectEntryId, LocalRepositoryEntry>,
|
||||
/// The file handle of the root dir
|
||||
/// (so we can find it after it's been moved)
|
||||
root_file_handle: Option<Arc<dyn fs::FileHandle>>,
|
||||
}
|
||||
|
||||
struct BackgroundScannerState {
|
||||
|
@ -341,6 +344,9 @@ enum ScanState {
|
|||
barrier: SmallVec<[barrier::Sender; 1]>,
|
||||
scanning: bool,
|
||||
},
|
||||
RootUpdated {
|
||||
new_path: Option<Arc<Path>>,
|
||||
},
|
||||
}
|
||||
|
||||
struct UpdateObservationState {
|
||||
|
@ -382,6 +388,8 @@ impl Worktree {
|
|||
true
|
||||
});
|
||||
|
||||
let root_file_handle = fs.open_handle(&abs_path).await.log_err();
|
||||
|
||||
cx.new_model(move |cx: &mut ModelContext<Worktree>| {
|
||||
let mut snapshot = LocalSnapshot {
|
||||
ignores_by_parent_abs_path: Default::default(),
|
||||
|
@ -393,6 +401,7 @@ impl Worktree {
|
|||
.map_or(String::new(), |f| f.to_string_lossy().to_string()),
|
||||
abs_path,
|
||||
),
|
||||
root_file_handle,
|
||||
};
|
||||
|
||||
if let Some(metadata) = metadata {
|
||||
|
@ -1076,6 +1085,17 @@ impl LocalWorktree {
|
|||
this.set_snapshot(snapshot, changes, cx);
|
||||
drop(barrier);
|
||||
}
|
||||
ScanState::RootUpdated { new_path } => {
|
||||
if let Some(new_path) = new_path {
|
||||
this.snapshot.git_repositories = Default::default();
|
||||
this.snapshot.ignores_by_parent_abs_path = Default::default();
|
||||
let root_name = new_path
|
||||
.file_name()
|
||||
.map_or(String::new(), |f| f.to_string_lossy().to_string());
|
||||
this.snapshot.update_abs_path(new_path, root_name);
|
||||
}
|
||||
this.restart_background_scanners(cx);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
})
|
||||
|
@ -2073,12 +2093,24 @@ impl Snapshot {
|
|||
.and_then(|entry| entry.git_status)
|
||||
}
|
||||
|
||||
fn update_abs_path(&mut self, abs_path: Arc<Path>, root_name: String) {
|
||||
self.abs_path = abs_path;
|
||||
if root_name != self.root_name {
|
||||
self.root_char_bag = root_name.chars().map(|c| c.to_ascii_lowercase()).collect();
|
||||
self.root_name = root_name;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn apply_remote_update(&mut self, mut update: proto::UpdateWorktree) -> Result<()> {
|
||||
log::trace!(
|
||||
"applying remote worktree update. {} entries updated, {} removed",
|
||||
update.updated_entries.len(),
|
||||
update.removed_entries.len()
|
||||
);
|
||||
self.update_abs_path(
|
||||
Arc::from(PathBuf::from(update.abs_path).as_path()),
|
||||
update.root_name,
|
||||
);
|
||||
|
||||
let mut entries_by_path_edits = Vec::new();
|
||||
let mut entries_by_id_edits = Vec::new();
|
||||
|
@ -3732,7 +3764,29 @@ impl BackgroundScanner {
|
|||
let root_canonical_path = match self.fs.canonicalize(&root_path).await {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
log::error!("failed to canonicalize root path: {}", err);
|
||||
let new_path = self
|
||||
.state
|
||||
.lock()
|
||||
.snapshot
|
||||
.root_file_handle
|
||||
.clone()
|
||||
.and_then(|handle| handle.current_path(&self.fs).log_err())
|
||||
.filter(|new_path| **new_path != *root_path);
|
||||
|
||||
if let Some(new_path) = new_path.as_ref() {
|
||||
log::info!(
|
||||
"root renamed from {} to {}",
|
||||
root_path.display(),
|
||||
new_path.display()
|
||||
)
|
||||
} else {
|
||||
log::warn!("root path could not be canonicalized: {}", err);
|
||||
}
|
||||
self.status_updates_tx
|
||||
.unbounded_send(ScanState::RootUpdated {
|
||||
new_path: new_path.map(|p| p.into()),
|
||||
})
|
||||
.ok();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue