Polish agent checkpoints (#29265)

Release Notes:

- Improved performance of agent checkpoint creation.
- Fixed a bug that sometimes caused accidental deletions when restoring
to a previous agent checkpoint.
- Fixed a bug that caused checkpoints to be visible in the Git history.
This commit is contained in:
Antonio Scandurra 2025-04-23 13:37:55 +02:00 committed by GitHub
parent 55ea481707
commit e515b2c714
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 13 additions and 89 deletions

View file

@ -314,9 +314,6 @@ pub trait GitRepository: Send + Sync {
right: GitRepositoryCheckpoint,
) -> BoxFuture<Result<bool>>;
/// Deletes a previously-created checkpoint.
fn delete_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>>;
/// Computes a diff between two checkpoints.
fn diff_checkpoints(
&self,
@ -374,7 +371,6 @@ impl RealGitRepository {
#[derive(Clone, Debug)]
pub struct GitRepositoryCheckpoint {
pub ref_name: String,
pub commit_sha: Oid,
}
@ -1225,11 +1221,8 @@ impl GitRepository for RealGitRepository {
} else {
git.run(&["commit-tree", &tree, "-m", "Checkpoint"]).await?
};
let ref_name = format!("refs/zed/{}", Uuid::new_v4());
git.run(&["update-ref", &ref_name, &checkpoint_sha]).await?;
Ok(GitRepositoryCheckpoint {
ref_name,
commit_sha: checkpoint_sha.parse()?,
})
})
@ -1308,21 +1301,6 @@ impl GitRepository for RealGitRepository {
.boxed()
}
fn delete_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>> {
let working_directory = self.working_directory();
let git_binary_path = self.git_binary_path.clone();
let executor = self.executor.clone();
self.executor
.spawn(async move {
let working_directory = working_directory?;
let git = GitBinary::new(git_binary_path, working_directory, executor);
git.run(&["update-ref", "-d", &checkpoint.ref_name]).await?;
Ok(())
})
.boxed()
}
fn diff_checkpoints(
&self,
base_checkpoint: GitRepositoryCheckpoint,
@ -1340,8 +1318,8 @@ impl GitRepository for RealGitRepository {
"diff",
"--find-renames",
"--patch",
&base_checkpoint.ref_name,
&target_checkpoint.ref_name,
&base_checkpoint.commit_sha.to_string(),
&target_checkpoint.commit_sha.to_string(),
])
.await
})
@ -1414,6 +1392,15 @@ impl GitBinary {
}
});
// Copy the default index file so that Git doesn't have to rebuild the
// whole index from scratch. This might fail if this is an empty repository.
smol::fs::copy(
self.working_directory.join(".git").join("index"),
&index_file_path,
)
.await
.ok();
self.index_file_path = Some(index_file_path.clone());
let result = f(self).await;
self.index_file_path = None;
@ -1856,13 +1843,6 @@ mod tests {
.ok(),
None
);
// Garbage collecting after deleting a checkpoint makes it unreachable.
repo.delete_checkpoint(checkpoint.clone()).await.unwrap();
repo.gc().await.unwrap();
repo.restore_checkpoint(checkpoint.clone())
.await
.unwrap_err();
}
#[gpui::test]
@ -1975,7 +1955,7 @@ mod tests {
let git_binary_path = git_binary_path.clone();
let working_directory = working_directory?;
let git = GitBinary::new(git_binary_path, working_directory, executor);
git.run(&["gc", "--prune=now"]).await?;
git.run(&["gc", "--prune"]).await?;
Ok(())
})
.boxed()