git: Use the CLI for loading commit SHAs and details (#29351)
Since #28065 merged we've seen deadlocks inside iconv when opening Zed in a repository containing many submodules. These calls to iconv happen inside libgit2, in our implementations of the methods `head_sha`, `merge_head_shas`, and `show` on `RealGitRepository`. This PR moves those methods to use the git CLI instead, sidestepping the issue. For the sake of efficiency, a new `revparse_batch` method is added that uses `git cat-file` to resolve several ref names in one invocation. I originally intended to make `show` operate in batch mode as well (or instead), but I can't see a good way to do that with the git CLI; `git show` always bails on the first ref that it can't resolve, and `for-each-ref` doesn't support symbolic refs like `HEAD`. Separately, I removed the calls to `show` in `MergeDetails::load`, going back to only loading the SHAs of the various merge heads. Loading full commit details was intended to support the inlays feature that ended up being cut from #28065, and we can add it back in when we need it. Release Notes: - N/A
This commit is contained in:
parent
8cc2ade21c
commit
7f5c874a38
5 changed files with 129 additions and 117 deletions
|
@ -34,8 +34,8 @@ pub struct FakeGitRepositoryState {
|
|||
pub blames: HashMap<RepoPath, Blame>,
|
||||
pub current_branch_name: Option<String>,
|
||||
pub branches: HashSet<String>,
|
||||
pub merge_head_shas: Vec<String>,
|
||||
pub simulated_index_write_error_message: Option<String>,
|
||||
pub refs: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl FakeGitRepositoryState {
|
||||
|
@ -48,20 +48,13 @@ impl FakeGitRepositoryState {
|
|||
blames: Default::default(),
|
||||
current_branch_name: Default::default(),
|
||||
branches: Default::default(),
|
||||
merge_head_shas: Default::default(),
|
||||
simulated_index_write_error_message: Default::default(),
|
||||
refs: HashMap::from_iter([("HEAD".into(), "abc".into())]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FakeGitRepository {
|
||||
fn with_state<F, T>(&self, write: bool, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&mut FakeGitRepositoryState) -> T,
|
||||
{
|
||||
self.fs.with_git_state(&self.dot_git_path, write, f)
|
||||
}
|
||||
|
||||
fn with_state_async<F, T>(&self, write: bool, f: F) -> BoxFuture<'static, Result<T>>
|
||||
where
|
||||
F: 'static + Send + FnOnce(&mut FakeGitRepositoryState) -> Result<T>,
|
||||
|
@ -141,13 +134,13 @@ impl GitRepository for FakeGitRepository {
|
|||
None
|
||||
}
|
||||
|
||||
fn head_sha(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn merge_head_shas(&self) -> Vec<String> {
|
||||
self.with_state(false, |state| state.merge_head_shas.clone())
|
||||
.unwrap()
|
||||
fn revparse_batch(&self, revs: Vec<String>) -> BoxFuture<Result<Vec<Option<String>>>> {
|
||||
self.with_state_async(false, |state| {
|
||||
Ok(revs
|
||||
.into_iter()
|
||||
.map(|rev| state.refs.get(&rev).cloned())
|
||||
.collect())
|
||||
})
|
||||
}
|
||||
|
||||
fn show(&self, commit: String) -> BoxFuture<Result<CommitDetails>> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue