@@ -791,11 +791,15 @@ impl Fs for RealFs {
let watcher = Arc::new(fs_watcher::FsWatcher::new(tx, pending_paths.clone()));
// If the path doesn't exist yet (e.g. settings.json), watch the parent dir to learn when it's created.
- if watcher.add(path).is_err()
+ if let Err(e) = watcher.add(path)
&& let Some(parent) = path.parent()
- && let Err(e) = watcher.add(parent)
+ && let Err(parent_e) = watcher.add(parent)
{
- log::warn!("Failed to watch: {e}");
+ log::warn!(
+ "Failed to watch {} and its parent directory {}:\n{e}\n{parent_e}",
+ path.display(),
+ parent.display()
+ );
}
// Check if path is a symlink and follow the target parent
@@ -1380,7 +1380,7 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon
cx.executor().run_until_parked();
assert_eq!(mem::take(&mut *file_changes.lock()), &[]);
- assert_eq!(fs.read_dir_call_count() - prev_read_dir_count, 5);
+ assert_eq!(fs.read_dir_call_count() - prev_read_dir_count, 4);
let mut new_watched_paths = fs.watched_paths();
new_watched_paths.retain(|path| {
@@ -158,6 +158,7 @@ pub struct RemoteWorktree {
#[derive(Clone)]
pub struct Snapshot {
id: WorktreeId,
+ /// The absolute path of the worktree root.
abs_path: Arc<SanitizedPath>,
path_style: PathStyle,
root_name: Arc<RelPath>,
@@ -235,7 +236,7 @@ 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
+ /// The file handle of the worktree root. `None` if the worktree is a directory.
/// (so we can find it after it's been moved)
root_file_handle: Option<Arc<dyn fs::FileHandle>>,
}
@@ -370,11 +371,19 @@ impl Worktree {
true
});
- let root_file_handle = fs
- .open_handle(&abs_path)
- .await
- .context("failed to open local worktree root")
- .log_err();
+ let root_file_handle = if metadata.as_ref().is_some() {
+ fs.open_handle(&abs_path)
+ .await
+ .with_context(|| {
+ format!(
+ "failed to open local worktree root at {}",
+ abs_path.display()
+ )
+ })
+ .log_err()
+ } else {
+ None
+ };
cx.new(move |cx: &mut Context<Worktree>| {
let mut snapshot = LocalSnapshot {
@@ -3572,25 +3581,25 @@ impl BackgroundScanner {
log::trace!("containing git repository: {containing_git_repository:?}");
- let global_gitignore_path = paths::global_gitignore_path();
- self.state.lock().snapshot.global_gitignore =
- if let Some(global_gitignore_path) = global_gitignore_path.as_ref() {
- build_gitignore(global_gitignore_path, self.fs.as_ref())
+ let mut global_gitignore_events =
+ if let Some(global_gitignore_path) = &paths::global_gitignore_path() {
+ self.state.lock().snapshot.global_gitignore =
+ if self.fs.is_file(&global_gitignore_path).await {
+ build_gitignore(global_gitignore_path, self.fs.as_ref())
+ .await
+ .ok()
+ .map(Arc::new)
+ } else {
+ None
+ };
+ self.fs
+ .watch(global_gitignore_path, FS_WATCH_LATENCY)
.await
- .ok()
- .map(Arc::new)
+ .0
} else {
- None
+ self.state.lock().snapshot.global_gitignore = None;
+ Box::pin(futures::stream::empty())
};
- let mut global_gitignore_events = if let Some(global_gitignore_path) = global_gitignore_path
- {
- self.fs
- .watch(&global_gitignore_path, FS_WATCH_LATENCY)
- .await
- .0
- } else {
- Box::pin(futures::stream::empty())
- };
let (scan_job_tx, scan_job_rx) = channel::unbounded();
{
@@ -3606,12 +3615,14 @@ impl BackgroundScanner {
root_entry.is_ignored = true;
state.insert_entry(root_entry.clone(), self.fs.as_ref(), self.watcher.as_ref());
}
- state.enqueue_scan_dir(
- root_abs_path.as_path().into(),
- &root_entry,
- &scan_job_tx,
- self.fs.as_ref(),
- );
+ if root_entry.is_dir() {
+ state.enqueue_scan_dir(
+ root_abs_path.as_path().into(),
+ &root_entry,
+ &scan_job_tx,
+ self.fs.as_ref(),
+ );
+ }
}
};