Use repository mutex more sparingly. Don't hold it while running git status. (#12489)

Previously, each git `Repository` object was held inside of a mutex.
This was needed because libgit2's Repository object is (as one would
expect) not thread safe. But now, the two longest-running git operations
that Zed performs, (`status` and `blame`) do not use libgit2 - they
invoke the `git` executable. For these operations, it's not necessary to
hold a lock on the repository.

In this PR, I've moved our mutex usage so that it only wraps the libgit2
calls, not our `git` subprocess spawns. The main user-facing impact of
this is that the UI is much more responsive when initially opening a
project with a very large git repository (e.g. `chromium`, `webkit`,
`linux`).

Release Notes:

- Improved Zed's responsiveness when initially opening a project
containing a very large git repository.
This commit is contained in:
Max Brunsfeld 2024-05-30 09:37:11 -07:00 committed by GitHub
parent 1ecd13ba50
commit 8f942bf647
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 69 additions and 79 deletions

View file

@ -109,7 +109,7 @@ impl BranchListDelegate {
.get_first_worktree_root_repo(cx)
.context("failed to get root repository for first worktree")?;
let all_branches = repo.lock().branches()?;
let all_branches = repo.branches()?;
Ok(Self {
matches: vec![],
workspace: handle,
@ -237,7 +237,6 @@ impl PickerDelegate for BranchListDelegate {
.get_first_worktree_root_repo(cx)
.context("failed to get root repository for first worktree")?;
let status = repo
.lock()
.change_branch(&current_pick);
if status.is_err() {
this.delegate.display_error_toast(format!("Failed to checkout branch '{current_pick}', check for conflicts or unstashed files"), cx);
@ -316,8 +315,6 @@ impl PickerDelegate for BranchListDelegate {
let repo = project
.get_first_worktree_root_repo(cx)
.context("failed to get root repository for first worktree")?;
let repo = repo
.lock();
let status = repo
.create_branch(&current_pick);
if status.is_err() {