diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 01343e4d96428c9ede784e4bc3ef1a610b1c1329..c4cd49b0e11847cd6bb2bb054b329f4f6905efa8 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -101,7 +101,7 @@ pub trait Fs: Send + Sync { self.remove_file(path, options).await } async fn open_handle(&self, path: &Path) -> Result>; - async fn open_sync(&self, path: &Path) -> Result>; + async fn open_sync(&self, path: &Path) -> Result>; async fn load(&self, path: &Path) -> Result { Ok(String::from_utf8(self.load_bytes(path).await?)?) } @@ -499,7 +499,7 @@ impl Fs for RealFs { Ok(()) } - async fn open_sync(&self, path: &Path) -> Result> { + async fn open_sync(&self, path: &Path) -> Result> { Ok(Box::new(std::fs::File::open(path)?)) } @@ -1746,7 +1746,7 @@ impl Fs for FakeFs { Ok(()) } - async fn open_sync(&self, path: &Path) -> Result> { + async fn open_sync(&self, path: &Path) -> Result> { let bytes = self.load_internal(path).await?; Ok(Box::new(io::Cursor::new(bytes))) } diff --git a/crates/project/src/search.rs b/crates/project/src/search.rs index f70baeb6d804b8bf77a24671dd8a92b936eddd3c..dc54da54b66540f28214292428d1f4f81d72edf9 100644 --- a/crates/project/src/search.rs +++ b/crates/project/src/search.rs @@ -210,14 +210,17 @@ impl SearchQuery { } } - pub fn detect(&self, stream: T) -> Result { + pub(crate) fn detect( + &self, + mut reader: BufReader>, + ) -> Result { if self.as_str().is_empty() { return Ok(false); } match self { Self::Text { search, .. } => { - let mat = search.stream_find_iter(stream).next(); + let mat = search.stream_find_iter(reader).next(); match mat { Some(Ok(_)) => Ok(true), Some(Err(err)) => Err(err.into()), @@ -227,7 +230,6 @@ impl SearchQuery { Self::Regex { regex, multiline, .. } => { - let mut reader = BufReader::new(stream); if *multiline { let mut text = String::new(); if let Err(err) = reader.read_to_string(&mut text) { diff --git a/crates/project/src/worktree_store.rs b/crates/project/src/worktree_store.rs index 3595ed06d628d244378b390ccfb566a58408a1e8..be1c824f50e70796ebef6577136984381ea702b4 100644 --- a/crates/project/src/worktree_store.rs +++ b/crates/project/src/worktree_store.rs @@ -1,4 +1,5 @@ use std::{ + io::{BufRead, BufReader}, path::{Path, PathBuf}, pin::pin, sync::{atomic::AtomicUsize, Arc}, @@ -985,7 +986,6 @@ impl WorktreeStore { } repo.change_branch(&new_branch)?; - Ok(()) }); @@ -1020,6 +1020,20 @@ impl WorktreeStore { let Some(file) = fs.open_sync(&abs_path).await.log_err() else { continue; }; + + let mut file = BufReader::new(file); + let file_start = file.fill_buf()?; + + if let Err(Some(starting_position)) = + std::str::from_utf8(file_start).map_err(|e| e.error_len()) + { + // Before attempting to match the file content, throw away files that have invalid UTF-8 sequences early on; + // That way we can still match files in a streaming fashion without having look at "obviously binary" files. + return Err(anyhow!( + "Invalid UTF-8 sequence at position {starting_position}" + )); + } + if query.detect(file).unwrap_or(false) { entry.respond.send(entry.path).await? }