@@ -368,12 +368,15 @@ impl GitBlame {
.spawn({
let snapshot = snapshot.clone();
async move {
- let Blame {
+ let Some(Blame {
entries,
permalinks,
messages,
remote_url,
- } = blame.await?;
+ }) = blame.await?
+ else {
+ return Ok(None);
+ };
let entries = build_blame_entry_sum_tree(entries, snapshot.max_point().row);
let commit_details = parse_commit_messages(
@@ -385,13 +388,16 @@ impl GitBlame {
)
.await;
- anyhow::Ok((entries, commit_details))
+ anyhow::Ok(Some((entries, commit_details)))
}
})
.await;
this.update(&mut cx, |this, cx| match result {
- Ok((entries, commit_details)) => {
+ Ok(None) => {
+ // Nothing to do, e.g. no repository found
+ }
+ Ok(Some((entries, commit_details))) => {
this.buffer_edits = buffer_edits;
this.buffer_snapshot = snapshot;
this.entries = entries;
@@ -410,11 +416,7 @@ impl GitBlame {
} else {
// If we weren't triggered by a user, we just log errors in the background, instead of sending
// notifications.
- // Except for `NoRepositoryError`, which can happen often if a user has inline-blame turned on
- // and opens a non-git file.
- if error.downcast_ref::<project::NoRepositoryError>().is_none() {
- log::error!("failed to get git blame data: {error:?}");
- }
+ log::error!("failed to get git blame data: {error:?}");
}
}),
})
@@ -1,7 +1,7 @@
use crate::{
search::SearchQuery,
worktree_store::{WorktreeStore, WorktreeStoreEvent},
- Item, NoRepositoryError, ProjectPath,
+ Item, ProjectPath,
};
use ::git::{parse_git_remote_url, BuildPermalinkParams, GitHostingProviderRegistry};
use anyhow::{anyhow, Context as _, Result};
@@ -1118,7 +1118,7 @@ impl BufferStore {
buffer: &Model<Buffer>,
version: Option<clock::Global>,
cx: &AppContext,
- ) -> Task<Result<Blame>> {
+ ) -> Task<Result<Option<Blame>>> {
let buffer = buffer.read(cx);
let Some(file) = File::from_dyn(buffer.file()) else {
return Task::ready(Err(anyhow!("buffer has no file")));
@@ -1130,7 +1130,7 @@ impl BufferStore {
let blame_params = maybe!({
let (repo_entry, local_repo_entry) = match worktree.repo_for_path(&file.path) {
Some(repo_for_path) => repo_for_path,
- None => anyhow::bail!(NoRepositoryError {}),
+ None => return Ok(None),
};
let relative_path = repo_entry
@@ -1144,13 +1144,16 @@ impl BufferStore {
None => buffer.as_rope().clone(),
};
- anyhow::Ok((repo, relative_path, content))
+ anyhow::Ok(Some((repo, relative_path, content)))
});
cx.background_executor().spawn(async move {
- let (repo, relative_path, content) = blame_params?;
+ let Some((repo, relative_path, content)) = blame_params? else {
+ return Ok(None);
+ };
repo.blame(&relative_path, content)
.with_context(|| format!("Failed to blame {:?}", relative_path.0))
+ .map(Some)
})
}
Worktree::Remote(worktree) => {
@@ -2112,7 +2115,13 @@ fn is_not_found_error(error: &anyhow::Error) -> bool {
.is_some_and(|err| err.kind() == io::ErrorKind::NotFound)
}
-fn serialize_blame_buffer_response(blame: git::blame::Blame) -> proto::BlameBufferResponse {
+fn serialize_blame_buffer_response(blame: Option<git::blame::Blame>) -> proto::BlameBufferResponse {
+ let Some(blame) = blame else {
+ return proto::BlameBufferResponse {
+ blame_response: None,
+ };
+ };
+
let entries = blame
.entries
.into_iter()
@@ -2154,14 +2163,19 @@ fn serialize_blame_buffer_response(blame: git::blame::Blame) -> proto::BlameBuff
.collect::<Vec<_>>();
proto::BlameBufferResponse {
- entries,
- messages,
- permalinks,
- remote_url: blame.remote_url,
+ blame_response: Some(proto::blame_buffer_response::BlameResponse {
+ entries,
+ messages,
+ permalinks,
+ remote_url: blame.remote_url,
+ }),
}
}
-fn deserialize_blame_buffer_response(response: proto::BlameBufferResponse) -> git::blame::Blame {
+fn deserialize_blame_buffer_response(
+ response: proto::BlameBufferResponse,
+) -> Option<git::blame::Blame> {
+ let response = response.blame_response?;
let entries = response
.entries
.into_iter()
@@ -2202,10 +2216,10 @@ fn deserialize_blame_buffer_response(response: proto::BlameBufferResponse) -> gi
})
.collect::<HashMap<_, _>>();
- Blame {
+ Some(Blame {
entries,
permalinks,
messages,
remote_url: response.remote_url,
- }
+ })
}
@@ -3420,7 +3420,7 @@ impl Project {
buffer: &Model<Buffer>,
version: Option<clock::Global>,
cx: &AppContext,
- ) -> Task<Result<Blame>> {
+ ) -> Task<Result<Option<Blame>>> {
self.buffer_store.read(cx).blame_buffer(buffer, version, cx)
}
@@ -4273,17 +4273,6 @@ impl Completion {
}
}
-#[derive(Debug)]
-pub struct NoRepositoryError {}
-
-impl std::fmt::Display for NoRepositoryError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "no git repository for worktree found")
- }
-}
-
-impl std::error::Error for NoRepositoryError {}
-
pub fn sort_worktree_entries(entries: &mut [Entry]) {
entries.sort_by(|entry_a, entry_b| {
compare_paths(