Fix crash in git checkout (#33499)

Closes #33438

Release Notes:

- git: Use git cli to perform checkouts (to avoid a crash seen in
libgit2)
This commit is contained in:
Conrad Irwin 2025-06-27 09:16:15 -06:00 committed by GitHub
parent 9e2023bffc
commit d74f3f4ea6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1032,14 +1032,15 @@ impl GitRepository for RealGitRepository {
fn change_branch(&self, name: String) -> BoxFuture<'_, Result<()>> { fn change_branch(&self, name: String) -> BoxFuture<'_, Result<()>> {
let repo = self.repository.clone(); let repo = self.repository.clone();
self.executor let working_directory = self.working_directory();
.spawn(async move { let git_binary_path = self.git_binary_path.clone();
let executor = self.executor.clone();
let branch = self.executor.spawn(async move {
let repo = repo.lock(); let repo = repo.lock();
let branch = if let Ok(branch) = repo.find_branch(&name, BranchType::Local) { let branch = if let Ok(branch) = repo.find_branch(&name, BranchType::Local) {
branch branch
} else if let Ok(revision) = repo.find_branch(&name, BranchType::Remote) { } else if let Ok(revision) = repo.find_branch(&name, BranchType::Remote) {
let (_, branch_name) = let (_, branch_name) = name.split_once("/").context("Unexpected branch format")?;
name.split_once("/").context("Unexpected branch format")?;
let revision = revision.get(); let revision = revision.get();
let branch_commit = revision.peel_to_commit()?; let branch_commit = revision.peel_to_commit()?;
let mut branch = repo.branch(&branch_name, &branch_commit, false)?; let mut branch = repo.branch(&branch_name, &branch_commit, false)?;
@ -1049,15 +1050,21 @@ impl GitRepository for RealGitRepository {
anyhow::bail!("Branch not found"); anyhow::bail!("Branch not found");
}; };
let revision = branch.get(); Ok(branch
let as_tree = revision.peel_to_tree()?; .name()?
repo.checkout_tree(as_tree.as_object(), None)?; .context("cannot checkout anonymous branch")?
repo.set_head( .to_string())
revision });
.name()
.context("Branch name could not be retrieved")?, self.executor
)?; .spawn(async move {
Ok(()) let branch = branch.await?;
GitBinary::new(git_binary_path, working_directory?, executor)
.run(&["checkout", &branch])
.await?;
anyhow::Ok(())
}) })
.boxed() .boxed()
} }