Add resolve_commit and repair_worktrees to git layer
Richard Feldman
created 5 days ago
- resolve_commit on Repository entity: wraps revparse_batch to check
if a commit SHA exists in the repo. Used during restore to verify
original_commit_hash is present before attempting recovery.
- repair_worktrees on GitRepository trait + RealGitRepository (runs
git worktree repair) and FakeGitRepository (no-op). Used during
restore when a worktree directory exists on disk but may not be in
git's worktree metadata.
- repair_worktrees wrapper on Repository entity.
Change summary
crates/fs/src/fake_git_repo.rs | 4 ++++
crates/git/src/repository.rs | 13 +++++++++++++
crates/project/src/git_store.rs | 27 +++++++++++++++++++++++++++
3 files changed, 44 insertions(+)
Detailed changes
@@ -1336,6 +1336,10 @@ impl GitRepository for FakeGitRepository {
})
}
+ fn repair_worktrees(&self) -> BoxFuture<'_, Result<()>> {
+ async { Ok(()) }.boxed()
+ }
+
fn set_trusted(&self, trusted: bool) {
self.is_trusted
.store(trusted, std::sync::atomic::Ordering::Release);
@@ -923,6 +923,8 @@ pub trait GitRepository: Send + Sync {
fn stage_all_including_untracked(&self) -> BoxFuture<'_, Result<()>>;
+ fn repair_worktrees(&self) -> BoxFuture<'_, Result<()>>;
+
fn set_trusted(&self, trusted: bool);
fn is_trusted(&self) -> bool;
}
@@ -2232,6 +2234,17 @@ impl GitRepository for RealGitRepository {
.boxed()
}
+ fn repair_worktrees(&self) -> BoxFuture<'_, Result<()>> {
+ let git_binary = self.git_binary();
+ self.executor
+ .spawn(async move {
+ let args: Vec<OsString> = vec!["worktree".into(), "repair".into()];
+ git_binary?.run(&args).await?;
+ Ok(())
+ })
+ .boxed()
+ }
+
fn push(
&self,
branch_name: String,
@@ -6081,6 +6081,33 @@ impl Repository {
})
}
+ pub fn resolve_commit(&mut self, sha: String) -> oneshot::Receiver<Result<bool>> {
+ self.send_job(None, move |repo, _cx| async move {
+ match repo {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ let results = backend.revparse_batch(vec![sha]).await?;
+ Ok(results.into_iter().next().flatten().is_some())
+ }
+ RepositoryState::Remote(_) => {
+ anyhow::bail!("resolve_commit is not supported for remote repositories")
+ }
+ }
+ })
+ }
+
+ pub fn repair_worktrees(&mut self) -> oneshot::Receiver<Result<()>> {
+ self.send_job(None, move |repo, _cx| async move {
+ match repo {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.repair_worktrees().await
+ }
+ RepositoryState::Remote(_) => {
+ anyhow::bail!("repair_worktrees is not supported for remote repositories")
+ }
+ }
+ })
+ }
+
pub fn remove_worktree(&mut self, path: PathBuf, force: bool) -> oneshot::Receiver<Result<()>> {
let id = self.id;
self.send_job(