Use correct worktree when getting permalink to line (#8888)

Previously this code would call `project.visible_worktrees(cx).next`
which might not necessarily return the worktree matching the currently
open file.

What this change does is it adds `get_repo` method on `Project` that
allows us to get the `GitRepository` for the current buffer.

Release Notes:

- Fixed `open permalink to line` not working when multiple folders are
added to the project.

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Thorsten Ball 2024-03-05 16:59:00 +01:00 committed by GitHub
parent d286c56ebb
commit 2b8b913b6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 22 deletions

View file

@ -89,6 +89,7 @@ pub use multi_buffer::{
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use project::project_settings::{GitGutterSetting, ProjectSettings}; use project::project_settings::{GitGutterSetting, ProjectSettings};
use project::Item;
use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction}; use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
use rand::prelude::*; use rand::prelude::*;
use rpc::proto::*; use rpc::proto::*;
@ -8657,22 +8658,23 @@ impl Editor {
fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> { fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
use git::permalink::{build_permalink, BuildPermalinkParams}; use git::permalink::{build_permalink, BuildPermalinkParams};
let project = self.project.clone().ok_or_else(|| anyhow!("no project"))?; let (path, repo) = maybe!({
let project = project.read(cx); let project_handle = self.project.as_ref()?.clone();
let project = project_handle.read(cx);
let worktree = project let buffer = self.buffer().read(cx).as_singleton()?;
.visible_worktrees(cx) let path = buffer
.next() .read(cx)
.ok_or_else(|| anyhow!("no worktree"))?; .file()?
.as_local()?
let mut cwd = worktree.read(cx).abs_path().to_path_buf(); .path()
cwd.push(".git"); .to_str()?
.to_string();
let repo = project.get_repo(&buffer.read(cx).project_path(cx)?, cx)?;
Some((path, repo))
})
.ok_or_else(|| anyhow!("unable to open git repository"))?;
const REMOTE_NAME: &str = "origin"; const REMOTE_NAME: &str = "origin";
let repo = project
.fs()
.open_repo(&cwd)
.ok_or_else(|| anyhow!("no Git repo"))?;
let origin_url = repo let origin_url = repo
.lock() .lock()
.remote_url(REMOTE_NAME) .remote_url(REMOTE_NAME)
@ -8681,14 +8683,6 @@ impl Editor {
.lock() .lock()
.head_sha() .head_sha()
.ok_or_else(|| anyhow!("failed to read HEAD SHA"))?; .ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
let path = maybe!({
let buffer = self.buffer().read(cx).as_singleton()?;
let file = buffer.read(cx).file().and_then(|f| f.as_local())?;
file.path().to_str().map(|path| path.to_string())
})
.ok_or_else(|| anyhow!("failed to determine file path"))?;
let selections = self.selections.all::<Point>(cx); let selections = self.selections.all::<Point>(cx);
let selection = selections.iter().peekable().next(); let selection = selections.iter().peekable().next();

View file

@ -16,6 +16,7 @@ use clock::ReplicaId;
use collections::{hash_map, BTreeMap, HashMap, HashSet, VecDeque}; use collections::{hash_map, BTreeMap, HashMap, HashSet, VecDeque};
use copilot::Copilot; use copilot::Copilot;
use debounced_delay::DebouncedDelay; use debounced_delay::DebouncedDelay;
use fs::repository::GitRepository;
use futures::{ use futures::{
channel::mpsc::{self, UnboundedReceiver}, channel::mpsc::{self, UnboundedReceiver},
future::{try_join_all, Shared}, future::{try_join_all, Shared},
@ -7302,6 +7303,18 @@ impl Project {
}) })
} }
pub fn get_repo(
&self,
project_path: &ProjectPath,
cx: &AppContext,
) -> Option<Arc<Mutex<dyn GitRepository>>> {
self.worktree_for_id(project_path.worktree_id, cx)?
.read(cx)
.as_local()?
.snapshot()
.local_git_repo(&project_path.path)
}
// RPC message handlers // RPC message handlers
async fn handle_unshare_project( async fn handle_unshare_project(

View file

@ -2116,6 +2116,11 @@ impl LocalSnapshot {
Some((path, self.git_repositories.get(&repo.work_directory_id())?)) Some((path, self.git_repositories.get(&repo.work_directory_id())?))
} }
pub fn local_git_repo(&self, path: &Path) -> Option<Arc<Mutex<dyn GitRepository>>> {
self.local_repo_for_path(path)
.map(|(_, entry)| entry.repo_ptr.clone())
}
fn build_update( fn build_update(
&self, &self,
project_id: u64, project_id: u64,