diff --git a/crates/editor/src/git/blame.rs b/crates/editor/src/git/blame.rs index 9ba5c4aa19..a78c37e66d 100644 --- a/crates/editor/src/git/blame.rs +++ b/crates/editor/src/git/blame.rs @@ -522,14 +522,25 @@ impl GitBlame { let id = buffer.read(cx).remote_id(); let snapshot = buffer.read(cx).snapshot(); let buffer_edits = buffer.update(cx, |buffer, _| buffer.subscribe()); - let remote_url = project + + let repository = project .read(cx) .git_store() .read(cx) - .repository_and_path_for_buffer_id(buffer.read(cx).remote_id(), cx) + .repository_and_path_for_buffer_id(id, cx); + + let remote_url = repository + .as_ref() .and_then(|(repo, _)| repo.read(cx).default_remote_url()); - let blame_buffer = project - .update(cx, |project, cx| project.blame_buffer(&buffer, None, cx)); + + let blame_buffer = if repository.is_some() { + project.update(cx, |project, cx| { + project.blame_buffer(&buffer, None, cx) + }) + } else { + Task::ready(Ok(None)) + }; + Ok(async move { (id, snapshot, buffer_edits, blame_buffer.await, remote_url) }) @@ -696,7 +707,7 @@ mod tests { use rand::prelude::*; use serde_json::json; use settings::SettingsStore; - use std::{cmp, env, ops::Range, path::Path}; + use std::{cmp, env, ops::Range, path::Path, sync::Mutex}; use text::BufferId; use unindent::Unindent as _; use util::{RandomCharIter, path}; @@ -811,6 +822,73 @@ mod tests { }); } + #[gpui::test] + async fn test_blame_ignores_buffers_outside_git_repositories(cx: &mut gpui::TestAppContext) { + init_test(cx); + + let fs = FakeFs::new(cx.executor()); + + fs.insert_tree( + "/not-a-repo", + json!({ + "foo": "bar", + }), + ) + .await; + + let project = Project::test(fs, ["/not-a-repo".as_ref()], cx).await; + + let buffer = project + .update(cx, |project, cx| { + project.open_local_buffer("/not-a-repo/foo", cx) + }) + .await + .unwrap(); + + let buffer_id = buffer.read_with(cx, |buffer, _| buffer.remote_id()); + + let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx)); + + let events = Arc::new(Mutex::new(Vec::new())); + + let _subscription = project.update(cx, |_, cx| { + cx.subscribe(&project, { + let events = events.clone(); + + move |_, _, event: &project::Event, _| { + events + .lock() + .expect("events mutex poisoned") + .push(event.clone()); + } + }) + }); + + let blame = cx.new(|cx| GitBlame::new(buffer.clone(), project.clone(), true, true, cx)); + + cx.executor().run_until_parked(); + + assert!(events.lock().expect("events mutex poisoned").is_empty()); + + blame.update(cx, |blame, cx| { + assert_eq!( + blame + .blame_for_rows( + &(0..1) + .map(|row| RowInfo { + buffer_row: Some(row), + buffer_id: Some(buffer_id), + ..Default::default() + }) + .collect::>(), + cx + ) + .collect::>(), + vec![None] + ); + }); + } + #[gpui::test] async fn test_blame_for_rows(cx: &mut gpui::TestAppContext) { init_test(cx);