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:
parent
55ea481707
commit
e515b2c714
4 changed files with 13 additions and 89 deletions
|
@ -619,24 +619,12 @@ impl Thread {
|
||||||
.await
|
.await
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if equal {
|
if !equal {
|
||||||
git_store
|
|
||||||
.update(cx, |store, cx| {
|
|
||||||
store.delete_checkpoint(pending_checkpoint.git_checkpoint, cx)
|
|
||||||
})?
|
|
||||||
.detach();
|
|
||||||
} else {
|
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.insert_checkpoint(pending_checkpoint, cx)
|
this.insert_checkpoint(pending_checkpoint, cx)
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_store
|
|
||||||
.update(cx, |store, cx| {
|
|
||||||
store.delete_checkpoint(final_checkpoint, cx)
|
|
||||||
})?
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(_) => this.update(cx, |this, cx| {
|
Err(_) => this.update(cx, |this, cx| {
|
||||||
|
|
|
@ -431,10 +431,6 @@ impl GitRepository for FakeGitRepository {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_checkpoint(&self, _checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn diff_checkpoints(
|
fn diff_checkpoints(
|
||||||
&self,
|
&self,
|
||||||
_base_checkpoint: GitRepositoryCheckpoint,
|
_base_checkpoint: GitRepositoryCheckpoint,
|
||||||
|
|
|
@ -314,9 +314,6 @@ pub trait GitRepository: Send + Sync {
|
||||||
right: GitRepositoryCheckpoint,
|
right: GitRepositoryCheckpoint,
|
||||||
) -> BoxFuture<Result<bool>>;
|
) -> BoxFuture<Result<bool>>;
|
||||||
|
|
||||||
/// Deletes a previously-created checkpoint.
|
|
||||||
fn delete_checkpoint(&self, checkpoint: GitRepositoryCheckpoint) -> BoxFuture<Result<()>>;
|
|
||||||
|
|
||||||
/// Computes a diff between two checkpoints.
|
/// Computes a diff between two checkpoints.
|
||||||
fn diff_checkpoints(
|
fn diff_checkpoints(
|
||||||
&self,
|
&self,
|
||||||
|
@ -374,7 +371,6 @@ impl RealGitRepository {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GitRepositoryCheckpoint {
|
pub struct GitRepositoryCheckpoint {
|
||||||
pub ref_name: String,
|
|
||||||
pub commit_sha: Oid,
|
pub commit_sha: Oid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,11 +1221,8 @@ impl GitRepository for RealGitRepository {
|
||||||
} else {
|
} else {
|
||||||
git.run(&["commit-tree", &tree, "-m", "Checkpoint"]).await?
|
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 {
|
Ok(GitRepositoryCheckpoint {
|
||||||
ref_name,
|
|
||||||
commit_sha: checkpoint_sha.parse()?,
|
commit_sha: checkpoint_sha.parse()?,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1308,21 +1301,6 @@ impl GitRepository for RealGitRepository {
|
||||||
.boxed()
|
.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(
|
fn diff_checkpoints(
|
||||||
&self,
|
&self,
|
||||||
base_checkpoint: GitRepositoryCheckpoint,
|
base_checkpoint: GitRepositoryCheckpoint,
|
||||||
|
@ -1340,8 +1318,8 @@ impl GitRepository for RealGitRepository {
|
||||||
"diff",
|
"diff",
|
||||||
"--find-renames",
|
"--find-renames",
|
||||||
"--patch",
|
"--patch",
|
||||||
&base_checkpoint.ref_name,
|
&base_checkpoint.commit_sha.to_string(),
|
||||||
&target_checkpoint.ref_name,
|
&target_checkpoint.commit_sha.to_string(),
|
||||||
])
|
])
|
||||||
.await
|
.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());
|
self.index_file_path = Some(index_file_path.clone());
|
||||||
let result = f(self).await;
|
let result = f(self).await;
|
||||||
self.index_file_path = None;
|
self.index_file_path = None;
|
||||||
|
@ -1856,13 +1843,6 @@ mod tests {
|
||||||
.ok(),
|
.ok(),
|
||||||
None
|
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]
|
#[gpui::test]
|
||||||
|
@ -1975,7 +1955,7 @@ mod tests {
|
||||||
let git_binary_path = git_binary_path.clone();
|
let git_binary_path = git_binary_path.clone();
|
||||||
let working_directory = working_directory?;
|
let working_directory = working_directory?;
|
||||||
let git = GitBinary::new(git_binary_path, working_directory, executor);
|
let git = GitBinary::new(git_binary_path, working_directory, executor);
|
||||||
git.run(&["gc", "--prune=now"]).await?;
|
git.run(&["gc", "--prune"]).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.boxed()
|
.boxed()
|
||||||
|
|
|
@ -832,32 +832,6 @@ impl GitStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_checkpoint(
|
|
||||||
&self,
|
|
||||||
checkpoint: GitStoreCheckpoint,
|
|
||||||
cx: &mut App,
|
|
||||||
) -> Task<Result<()>> {
|
|
||||||
let repositories_by_work_directory_abs_path = self
|
|
||||||
.repositories
|
|
||||||
.values()
|
|
||||||
.map(|repo| (repo.read(cx).snapshot.work_directory_abs_path.clone(), repo))
|
|
||||||
.collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
let mut tasks = Vec::new();
|
|
||||||
for (work_dir_abs_path, checkpoint) in checkpoint.checkpoints_by_work_dir_abs_path {
|
|
||||||
if let Some(repository) =
|
|
||||||
repositories_by_work_directory_abs_path.get(&work_dir_abs_path)
|
|
||||||
{
|
|
||||||
let delete = repository.update(cx, |this, _| this.delete_checkpoint(checkpoint));
|
|
||||||
tasks.push(async move { delete.await? });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cx.background_spawn(async move {
|
|
||||||
future::try_join_all(tasks).await?;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Blames a buffer.
|
/// Blames a buffer.
|
||||||
pub fn blame_buffer(
|
pub fn blame_buffer(
|
||||||
&self,
|
&self,
|
||||||
|
@ -3795,20 +3769,6 @@ impl Repository {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_checkpoint(
|
|
||||||
&mut self,
|
|
||||||
checkpoint: GitRepositoryCheckpoint,
|
|
||||||
) -> oneshot::Receiver<Result<()>> {
|
|
||||||
self.send_job(None, move |repo, _cx| async move {
|
|
||||||
match repo {
|
|
||||||
RepositoryState::Local { backend, .. } => {
|
|
||||||
backend.delete_checkpoint(checkpoint).await
|
|
||||||
}
|
|
||||||
RepositoryState::Remote { .. } => Err(anyhow!("not implemented yet")),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn diff_checkpoints(
|
pub fn diff_checkpoints(
|
||||||
&mut self,
|
&mut self,
|
||||||
base_checkpoint: GitRepositoryCheckpoint,
|
base_checkpoint: GitRepositoryCheckpoint,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue