Move repository state RPC handlers to the GitStore (#27391)
This is another in the series of PRs to make the GitStore own all repository state and enable better concurrency control for git repository scans. After this PR, the `RepositoryEntry`s stored in worktree snapshots are used only as a staging ground for local GitStores to pull from after git-related events; non-local worktrees don't store them at all, although this is not reflected in the types. GitTraversal and other places that need information about repositories get it from the GitStore. The GitStore also takes over handling of the new UpdateRepository and RemoveRepository messages. However, repositories are still discovered and scanned on a per-worktree basis, and we're still identifying them by the (worktree-specific) project entry ID of their working directory. - [x] Remove WorkDirectory from RepositoryEntry - [x] Remove worktree IDs from repository-related RPC messages - [x] Handle UpdateRepository and RemoveRepository RPCs from the GitStore Release Notes: - N/A --------- Co-authored-by: Max <max@zed.dev> Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
parent
1e8b50f471
commit
6924720b35
22 changed files with 1387 additions and 1399 deletions
|
@ -57,12 +57,14 @@ impl FakeGitRepository {
|
|||
where
|
||||
F: FnOnce(&mut FakeGitRepositoryState) -> T,
|
||||
{
|
||||
self.fs.with_git_state(&self.dot_git_path, false, f)
|
||||
self.fs
|
||||
.with_git_state(&self.dot_git_path, false, f)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn with_state_async<F, T>(&self, write: bool, f: F) -> BoxFuture<T>
|
||||
fn with_state_async<F, T>(&self, write: bool, f: F) -> BoxFuture<Result<T>>
|
||||
where
|
||||
F: 'static + Send + FnOnce(&mut FakeGitRepositoryState) -> T,
|
||||
F: 'static + Send + FnOnce(&mut FakeGitRepositoryState) -> Result<T>,
|
||||
T: Send,
|
||||
{
|
||||
let fs = self.fs.clone();
|
||||
|
@ -70,7 +72,7 @@ impl FakeGitRepository {
|
|||
let dot_git_path = self.dot_git_path.clone();
|
||||
async move {
|
||||
executor.simulate_random_delay().await;
|
||||
fs.with_git_state(&dot_git_path, write, f)
|
||||
fs.with_git_state(&dot_git_path, write, f)?
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
|
@ -80,15 +82,33 @@ impl GitRepository for FakeGitRepository {
|
|||
fn reload_index(&self) {}
|
||||
|
||||
fn load_index_text(&self, path: RepoPath, _cx: AsyncApp) -> BoxFuture<Option<String>> {
|
||||
self.with_state_async(false, move |state| {
|
||||
state.index_contents.get(path.as_ref()).cloned()
|
||||
})
|
||||
async {
|
||||
self.with_state_async(false, move |state| {
|
||||
state
|
||||
.index_contents
|
||||
.get(path.as_ref())
|
||||
.ok_or_else(|| anyhow!("not present in index"))
|
||||
.cloned()
|
||||
})
|
||||
.await
|
||||
.ok()
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn load_committed_text(&self, path: RepoPath, _cx: AsyncApp) -> BoxFuture<Option<String>> {
|
||||
self.with_state_async(false, move |state| {
|
||||
state.head_contents.get(path.as_ref()).cloned()
|
||||
})
|
||||
async {
|
||||
self.with_state_async(false, move |state| {
|
||||
state
|
||||
.head_contents
|
||||
.get(path.as_ref())
|
||||
.ok_or_else(|| anyhow!("not present in HEAD"))
|
||||
.cloned()
|
||||
})
|
||||
.await
|
||||
.ok()
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn set_index_text(
|
||||
|
@ -194,7 +214,7 @@ impl GitRepository for FakeGitRepository {
|
|||
})
|
||||
.collect();
|
||||
|
||||
self.with_state(|state| {
|
||||
self.fs.with_git_state(&self.dot_git_path, false, |state| {
|
||||
let mut entries = Vec::new();
|
||||
let paths = state
|
||||
.head_contents
|
||||
|
@ -278,7 +298,7 @@ impl GitRepository for FakeGitRepository {
|
|||
Ok(GitStatus {
|
||||
entries: entries.into(),
|
||||
})
|
||||
})
|
||||
})?
|
||||
}
|
||||
|
||||
fn branches(&self) -> BoxFuture<Result<Vec<Branch>>> {
|
||||
|
|
|
@ -1248,12 +1248,12 @@ impl FakeFs {
|
|||
.boxed()
|
||||
}
|
||||
|
||||
pub fn with_git_state<T, F>(&self, dot_git: &Path, emit_git_event: bool, f: F) -> T
|
||||
pub fn with_git_state<T, F>(&self, dot_git: &Path, emit_git_event: bool, f: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&mut FakeGitRepositoryState) -> T,
|
||||
{
|
||||
let mut state = self.state.lock();
|
||||
let entry = state.read_path(dot_git).unwrap();
|
||||
let entry = state.read_path(dot_git).context("open .git")?;
|
||||
let mut entry = entry.lock();
|
||||
|
||||
if let FakeFsEntry::Dir { git_repo_state, .. } = &mut *entry {
|
||||
|
@ -1271,9 +1271,9 @@ impl FakeFs {
|
|||
state.emit_event([(dot_git, None)]);
|
||||
}
|
||||
|
||||
result
|
||||
Ok(result)
|
||||
} else {
|
||||
panic!("not a directory");
|
||||
Err(anyhow!("not a directory"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1283,6 +1283,7 @@ impl FakeFs {
|
|||
state.branches.extend(branch.clone());
|
||||
state.current_branch_name = branch
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn insert_branches(&self, dot_git: &Path, branches: &[&str]) {
|
||||
|
@ -1296,6 +1297,7 @@ impl FakeFs {
|
|||
.branches
|
||||
.extend(branches.iter().map(ToString::to_string));
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_unmerged_paths_for_repo(
|
||||
|
@ -1310,7 +1312,8 @@ impl FakeFs {
|
|||
.iter()
|
||||
.map(|(path, content)| (path.clone(), *content)),
|
||||
);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_index_for_repo(&self, dot_git: &Path, index_state: &[(RepoPath, String)]) {
|
||||
|
@ -1321,7 +1324,8 @@ impl FakeFs {
|
|||
.iter()
|
||||
.map(|(path, content)| (path.clone(), content.clone())),
|
||||
);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_head_for_repo(&self, dot_git: &Path, head_state: &[(RepoPath, String)]) {
|
||||
|
@ -1332,7 +1336,8 @@ impl FakeFs {
|
|||
.iter()
|
||||
.map(|(path, content)| (path.clone(), content.clone())),
|
||||
);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_git_content_for_repo(
|
||||
|
@ -1356,7 +1361,8 @@ impl FakeFs {
|
|||
)
|
||||
},
|
||||
));
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_head_and_index_for_repo(
|
||||
|
@ -1371,14 +1377,16 @@ impl FakeFs {
|
|||
state
|
||||
.index_contents
|
||||
.extend(contents_by_path.iter().cloned());
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn set_blame_for_repo(&self, dot_git: &Path, blames: Vec<(RepoPath, git::blame::Blame)>) {
|
||||
self.with_git_state(dot_git, true, |state| {
|
||||
state.blames.clear();
|
||||
state.blames.extend(blames);
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Put the given git repository into a state with the given status,
|
||||
|
@ -1460,13 +1468,14 @@ impl FakeFs {
|
|||
state.head_contents.insert(repo_path.clone(), content);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
pub fn set_error_message_for_index_write(&self, dot_git: &Path, message: Option<String>) {
|
||||
self.with_git_state(dot_git, true, |state| {
|
||||
state.simulated_index_write_error_message = message;
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn paths(&self, include_dot_git: bool) -> Vec<PathBuf> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue