Use anyhow more idiomatically (#31052)

https://github.com/zed-industries/zed/issues/30972 brought up another
case where our context is not enough to track the actual source of the
issue: we get a general top-level error without inner error.

The reason for this was `.ok_or_else(|| anyhow!("failed to read HEAD
SHA"))?; ` on the top level.

The PR finally reworks the way we use anyhow to reduce such issues (or
at least make it simpler to bubble them up later in a fix).
On top of that, uses a few more anyhow methods for better readability.

* `.ok_or_else(|| anyhow!("..."))`, `map_err` and other similar error
conversion/option reporting cases are replaced with `context` and
`with_context` calls
* in addition to that, various `anyhow!("failed to do ...")` are
stripped with `.context("Doing ...")` messages instead to remove the
parasitic `failed to` text
* `anyhow::ensure!` is used instead of `if ... { return Err(...); }`
calls
* `anyhow::bail!` is used instead of `return Err(anyhow!(...));`

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-05-21 02:06:07 +03:00 committed by GitHub
parent 1e51a7ac44
commit 16366cf9f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
294 changed files with 2037 additions and 2610 deletions

View file

@ -1,5 +1,5 @@
use crate::FakeFs;
use anyhow::{Context as _, Result, anyhow};
use anyhow::{Context as _, Result};
use collections::{HashMap, HashSet};
use futures::future::{self, BoxFuture};
use git::{
@ -80,7 +80,7 @@ impl GitRepository for FakeGitRepository {
state
.index_contents
.get(path.as_ref())
.ok_or_else(|| anyhow!("not present in index"))
.context("not present in index")
.cloned()
})
.await
@ -95,7 +95,7 @@ impl GitRepository for FakeGitRepository {
state
.head_contents
.get(path.as_ref())
.ok_or_else(|| anyhow!("not present in HEAD"))
.context("not present in HEAD")
.cloned()
})
.await
@ -119,8 +119,8 @@ impl GitRepository for FakeGitRepository {
_env: Arc<HashMap<String, String>>,
) -> BoxFuture<anyhow::Result<()>> {
self.with_state_async(true, move |state| {
if let Some(message) = state.simulated_index_write_error_message.clone() {
return Err(anyhow!("{}", message));
if let Some(message) = &state.simulated_index_write_error_message {
anyhow::bail!("{message}");
} else if let Some(content) = content {
state.index_contents.insert(path, content);
} else {

View file

@ -360,7 +360,7 @@ impl Fs for RealFs {
if options.ignore_if_exists {
return Ok(());
} else {
return Err(anyhow!("{target:?} already exists"));
anyhow::bail!("{target:?} already exists");
}
}
@ -373,7 +373,7 @@ impl Fs for RealFs {
if options.ignore_if_exists {
return Ok(());
} else {
return Err(anyhow!("{target:?} already exists"));
anyhow::bail!("{target:?} already exists");
}
}
@ -538,7 +538,7 @@ impl Fs for RealFs {
}?;
tmp_file.write_all(data.as_bytes())?;
tmp_file.persist(path)?;
Ok::<(), anyhow::Error>(())
anyhow::Ok(())
})
.await?;
@ -568,7 +568,7 @@ impl Fs for RealFs {
temp_file_path
};
atomic_replace(path.as_path(), temp_file.as_path())?;
Ok::<(), anyhow::Error>(())
anyhow::Ok(())
})
.await?;
Ok(())
@ -672,7 +672,7 @@ impl Fs for RealFs {
) -> Result<Pin<Box<dyn Send + Stream<Item = Result<PathBuf>>>>> {
let result = smol::fs::read_dir(path).await?.map(|entry| match entry {
Ok(entry) => Ok(entry.path()),
Err(error) => Err(anyhow!("failed to read dir entry {:?}", error)),
Err(error) => Err(anyhow!("failed to read dir entry {error:?}")),
});
Ok(Box::pin(result))
}
@ -942,7 +942,7 @@ impl FakeFsState {
.ok_or_else(|| {
anyhow!(io::Error::new(
io::ErrorKind::NotFound,
format!("not found: {}", target.display())
format!("not found: {target:?}")
))
})?
.0)
@ -1012,9 +1012,7 @@ impl FakeFsState {
Fn: FnOnce(btree_map::Entry<String, Arc<Mutex<FakeFsEntry>>>) -> Result<T>,
{
let path = normalize_path(path);
let filename = path
.file_name()
.ok_or_else(|| anyhow!("cannot overwrite the root"))?;
let filename = path.file_name().context("cannot overwrite the root")?;
let parent_path = path.parent().unwrap();
let parent = self.read_path(parent_path)?;
@ -1352,7 +1350,7 @@ impl FakeFs {
let path = std::str::from_utf8(content)
.ok()
.and_then(|content| content.strip_prefix("gitdir:"))
.ok_or_else(|| anyhow!("not a valid gitfile"))?
.context("not a valid gitfile")?
.trim();
git_dir_path.insert(normalize_path(&dot_git.parent().unwrap().join(path)))
}
@ -1394,7 +1392,7 @@ impl FakeFs {
Ok(result)
} else {
Err(anyhow!("not a valid git repository"))
anyhow::bail!("not a valid git repository");
}
}
@ -1744,7 +1742,7 @@ impl FakeFsEntry {
if let Self::File { content, .. } = self {
Ok(content)
} else {
Err(anyhow!("not a file: {}", path.display()))
anyhow::bail!("not a file: {path:?}");
}
}
@ -1755,7 +1753,7 @@ impl FakeFsEntry {
if let Self::Dir { entries, .. } = self {
Ok(entries)
} else {
Err(anyhow!("not a directory: {}", path.display()))
anyhow::bail!("not a directory: {path:?}");
}
}
}
@ -1867,7 +1865,7 @@ impl Fs for FakeFs {
kind = Some(PathEventKind::Changed);
*e.get_mut() = file;
} else if !options.ignore_if_exists {
return Err(anyhow!("path already exists: {}", path.display()));
anyhow::bail!("path already exists: {path:?}");
}
}
btree_map::Entry::Vacant(e) => {
@ -1941,7 +1939,7 @@ impl Fs for FakeFs {
if let btree_map::Entry::Occupied(e) = e {
Ok(e.get().clone())
} else {
Err(anyhow!("path does not exist: {}", &old_path.display()))
anyhow::bail!("path does not exist: {old_path:?}")
}
})?;
@ -1959,7 +1957,7 @@ impl Fs for FakeFs {
if options.overwrite {
*e.get_mut() = moved_entry;
} else if !options.ignore_if_exists {
return Err(anyhow!("path already exists: {}", new_path.display()));
anyhow::bail!("path already exists: {new_path:?}");
}
}
btree_map::Entry::Vacant(e) => {
@ -2003,7 +2001,7 @@ impl Fs for FakeFs {
kind = Some(PathEventKind::Changed);
Ok(Some(e.get().clone()))
} else if !options.ignore_if_exists {
return Err(anyhow!("{target:?} already exists"));
anyhow::bail!("{target:?} already exists");
} else {
Ok(None)
}
@ -2027,10 +2025,8 @@ impl Fs for FakeFs {
self.simulate_random_delay().await;
let path = normalize_path(path);
let parent_path = path
.parent()
.ok_or_else(|| anyhow!("cannot remove the root"))?;
let base_name = path.file_name().unwrap();
let parent_path = path.parent().context("cannot remove the root")?;
let base_name = path.file_name().context("cannot remove the root")?;
let mut state = self.state.lock();
let parent_entry = state.read_path(parent_path)?;
@ -2042,7 +2038,7 @@ impl Fs for FakeFs {
match entry {
btree_map::Entry::Vacant(_) => {
if !options.ignore_if_not_exists {
return Err(anyhow!("{path:?} does not exist"));
anyhow::bail!("{path:?} does not exist");
}
}
btree_map::Entry::Occupied(e) => {
@ -2050,7 +2046,7 @@ impl Fs for FakeFs {
let mut entry = e.get().lock();
let children = entry.dir_entries(&path)?;
if !options.recursive && !children.is_empty() {
return Err(anyhow!("{path:?} is not empty"));
anyhow::bail!("{path:?} is not empty");
}
}
e.remove();
@ -2064,9 +2060,7 @@ impl Fs for FakeFs {
self.simulate_random_delay().await;
let path = normalize_path(path);
let parent_path = path
.parent()
.ok_or_else(|| anyhow!("cannot remove the root"))?;
let parent_path = path.parent().context("cannot remove the root")?;
let base_name = path.file_name().unwrap();
let mut state = self.state.lock();
let parent_entry = state.read_path(parent_path)?;
@ -2077,7 +2071,7 @@ impl Fs for FakeFs {
match entry {
btree_map::Entry::Vacant(_) => {
if !options.ignore_if_not_exists {
return Err(anyhow!("{path:?} does not exist"));
anyhow::bail!("{path:?} does not exist");
}
}
btree_map::Entry::Occupied(e) => {
@ -2148,11 +2142,10 @@ impl Fs for FakeFs {
let path = normalize_path(path);
self.simulate_random_delay().await;
let state = self.state.lock();
if let Some((_, canonical_path)) = state.try_read_path(&path, true) {
Ok(canonical_path)
} else {
Err(anyhow!("path does not exist: {}", path.display()))
}
let (_, canonical_path) = state
.try_read_path(&path, true)
.with_context(|| format!("path does not exist: {path:?}"))?;
Ok(canonical_path)
}
async fn is_file(&self, path: &Path) -> bool {
@ -2220,15 +2213,14 @@ impl Fs for FakeFs {
self.simulate_random_delay().await;
let path = normalize_path(path);
let state = self.state.lock();
if let Some((entry, _)) = state.try_read_path(&path, false) {
let entry = entry.lock();
if let FakeFsEntry::Symlink { target } = &*entry {
Ok(target.clone())
} else {
Err(anyhow!("not a symlink: {}", path.display()))
}
let (entry, _) = state
.try_read_path(&path, false)
.with_context(|| format!("path does not exist: {path:?}"))?;
let entry = entry.lock();
if let FakeFsEntry::Symlink { target } = &*entry {
Ok(target.clone())
} else {
Err(anyhow!("path does not exist: {}", path.display()))
anyhow::bail!("not a symlink: {path:?}")
}
}
@ -2403,7 +2395,7 @@ pub async fn copy_recursive<'a>(
if options.ignore_if_exists {
continue;
} else {
return Err(anyhow!("{target_item:?} already exists"));
anyhow::bail!("{target_item:?} already exists");
}
}
let _ = fs
@ -2443,7 +2435,7 @@ fn read_recursive<'a>(
let metadata = fs
.metadata(source)
.await?
.ok_or_else(|| anyhow!("path does not exist: {}", source.display()))?;
.with_context(|| format!("path does not exist: {source:?}"))?;
if metadata.is_dir {
output.push((source.to_path_buf(), true));

View file

@ -23,7 +23,7 @@ impl FsWatcher {
}
impl Watcher for FsWatcher {
fn add(&self, path: &std::path::Path) -> gpui::Result<()> {
fn add(&self, path: &std::path::Path) -> anyhow::Result<()> {
let root_path = SanitizedPath::from(path);
let tx = self.tx.clone();
@ -78,7 +78,7 @@ impl Watcher for FsWatcher {
Ok(())
}
fn remove(&self, path: &std::path::Path) -> gpui::Result<()> {
fn remove(&self, path: &std::path::Path) -> anyhow::Result<()> {
use notify::Watcher;
Ok(global(|w| w.watcher.lock().unwatch(path))??)
}
@ -130,6 +130,6 @@ pub fn global<T>(f: impl FnOnce(&GlobalWatcher) -> T) -> anyhow::Result<T> {
});
match result {
Ok(g) => Ok(f(g)),
Err(e) => Err(anyhow::anyhow!("{}", e)),
Err(e) => Err(anyhow::anyhow!("{e}")),
}
}

View file

@ -57,7 +57,7 @@ impl Watcher for MacWatcher {
Ok(())
}
fn remove(&self, path: &Path) -> gpui::Result<()> {
fn remove(&self, path: &Path) -> anyhow::Result<()> {
let handles = self
.handles
.upgrade()