@@ -288,6 +288,7 @@ pub struct Repository {
job_id: JobId,
askpass_delegates: Arc<Mutex<HashMap<u64, AskPassDelegate>>>,
latest_askpass_id: u64,
+ repository_state: Shared<Task<Result<RepositoryState, String>>>,
}
impl std::ops::Deref for Repository {
@@ -299,16 +300,63 @@ impl std::ops::Deref for Repository {
}
#[derive(Clone)]
-pub enum RepositoryState {
- Local {
+pub struct LocalRepositoryState {
+ pub fs: Arc<dyn Fs>,
+ pub backend: Arc<dyn GitRepository>,
+ pub environment: Arc<HashMap<String, String>>,
+}
+
+impl LocalRepositoryState {
+ async fn new(
+ work_directory_abs_path: Arc<Path>,
+ dot_git_abs_path: Arc<Path>,
+ project_environment: WeakEntity<ProjectEnvironment>,
fs: Arc<dyn Fs>,
- backend: Arc<dyn GitRepository>,
- environment: Arc<HashMap<String, String>>,
- },
- Remote {
- project_id: ProjectId,
- client: AnyProtoClient,
- },
+ cx: &mut AsyncApp,
+ ) -> anyhow::Result<Self> {
+ let environment = project_environment
+ .update(cx, |project_environment, cx| {
+ project_environment.local_directory_environment(&Shell::System, work_directory_abs_path.clone(), cx)
+ })?
+ .await
+ .unwrap_or_else(|| {
+ log::error!("failed to get working directory environment for repository {work_directory_abs_path:?}");
+ HashMap::default()
+ });
+ let search_paths = environment.get("PATH").map(|val| val.to_owned());
+ let backend = cx
+ .background_spawn({
+ let fs = fs.clone();
+ async move {
+ let system_git_binary_path = search_paths
+ .and_then(|search_paths| {
+ which::which_in("git", Some(search_paths), &work_directory_abs_path)
+ .ok()
+ })
+ .or_else(|| which::which("git").ok());
+ fs.open_repo(&dot_git_abs_path, system_git_binary_path.as_deref())
+ .with_context(|| format!("opening repository at {dot_git_abs_path:?}"))
+ }
+ })
+ .await?;
+ Ok(LocalRepositoryState {
+ backend,
+ environment: Arc::new(environment),
+ fs,
+ })
+ }
+}
+
+#[derive(Clone)]
+pub struct RemoteRepositoryState {
+ pub project_id: ProjectId,
+ pub client: AnyProtoClient,
+}
+
+#[derive(Clone)]
+pub enum RepositoryState {
+ Local(LocalRepositoryState),
+ Remote(RemoteRepositoryState),
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -966,7 +1014,7 @@ impl GitStore {
&self,
buffer: &Entity<Buffer>,
version: Option<clock::Global>,
- cx: &mut App,
+ cx: &mut Context<Self>,
) -> Task<Result<Option<Blame>>> {
let buffer = buffer.read(cx);
let Some((repo, repo_path)) =
@@ -981,29 +1029,30 @@ impl GitStore {
let version = version.unwrap_or(buffer.version());
let buffer_id = buffer.remote_id();
- let rx = repo.update(cx, |repo, _| {
- repo.send_job(None, move |state, _| async move {
- match state {
- RepositoryState::Local { backend, .. } => backend
- .blame(repo_path.clone(), content)
- .await
- .with_context(|| format!("Failed to blame {:?}", repo_path.as_ref()))
- .map(Some),
- RepositoryState::Remote { project_id, client } => {
- let response = client
- .request(proto::BlameBuffer {
- project_id: project_id.to_proto(),
- buffer_id: buffer_id.into(),
- version: serialize_version(&version),
- })
- .await?;
- Ok(deserialize_blame_buffer_response(response))
- }
+ let repo = repo.downgrade();
+ cx.spawn(async move |_, cx| {
+ let repository_state = repo
+ .update(cx, |repo, _| repo.repository_state.clone())?
+ .await
+ .map_err(|err| anyhow::anyhow!(err))?;
+ match repository_state {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => backend
+ .blame(repo_path.clone(), content)
+ .await
+ .with_context(|| format!("Failed to blame {:?}", repo_path.as_ref()))
+ .map(Some),
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
+ let response = client
+ .request(proto::BlameBuffer {
+ project_id: project_id.to_proto(),
+ buffer_id: buffer_id.into(),
+ version: serialize_version(&version),
+ })
+ .await?;
+ Ok(deserialize_blame_buffer_response(response))
}
- })
- });
-
- cx.spawn(|_: &mut AsyncApp| async move { rx.await? })
+ }
+ })
}
pub fn get_permalink_to_line(
@@ -1051,7 +1100,7 @@ impl GitStore {
let rx = repo.update(cx, |repo, _| {
repo.send_job(None, move |state, cx| async move {
match state {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
let origin_url = backend
.remote_url(&remote)
.with_context(|| format!("remote \"{remote}\" not found"))?;
@@ -1070,7 +1119,7 @@ impl GitStore {
BuildPermalinkParams::new(&sha, &repo_path, Some(selection)),
))
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::GetPermalinkToLine {
project_id: project_id.to_proto(),
@@ -1309,8 +1358,8 @@ impl GitStore {
} else if let UpdatedGitRepository {
new_work_directory_abs_path: Some(work_directory_abs_path),
dot_git_abs_path: Some(dot_git_abs_path),
- repository_dir_abs_path: Some(repository_dir_abs_path),
- common_dir_abs_path: Some(common_dir_abs_path),
+ repository_dir_abs_path: Some(_repository_dir_abs_path),
+ common_dir_abs_path: Some(_common_dir_abs_path),
..
} = update
{
@@ -1321,8 +1370,6 @@ impl GitStore {
id,
work_directory_abs_path.clone(),
dot_git_abs_path.clone(),
- repository_dir_abs_path.clone(),
- common_dir_abs_path.clone(),
project_environment.downgrade(),
fs.clone(),
git_store,
@@ -3356,8 +3403,6 @@ impl Repository {
id: RepositoryId,
work_directory_abs_path: Arc<Path>,
dot_git_abs_path: Arc<Path>,
- repository_dir_abs_path: Arc<Path>,
- common_dir_abs_path: Arc<Path>,
project_environment: WeakEntity<ProjectEnvironment>,
fs: Arc<dyn Fs>,
git_store: WeakEntity<GitStore>,
@@ -3365,24 +3410,38 @@ impl Repository {
) -> Self {
let snapshot =
RepositorySnapshot::empty(id, work_directory_abs_path.clone(), PathStyle::local());
+ let state = cx
+ .spawn(async move |_, cx| {
+ LocalRepositoryState::new(
+ work_directory_abs_path,
+ dot_git_abs_path,
+ project_environment,
+ fs,
+ cx,
+ )
+ .await
+ .map_err(|err| err.to_string())
+ })
+ .shared();
+ let job_sender = Repository::spawn_local_git_worker(state.clone(), cx);
+ let state = cx
+ .spawn(async move |_, _| {
+ let state = state.await?;
+ Ok(RepositoryState::Local(state))
+ })
+ .shared();
+
Repository {
this: cx.weak_entity(),
git_store,
snapshot,
pending_ops: Default::default(),
+ repository_state: state,
commit_message_buffer: None,
askpass_delegates: Default::default(),
paths_needing_status_update: Default::default(),
latest_askpass_id: 0,
- job_sender: Repository::spawn_local_git_worker(
- work_directory_abs_path,
- dot_git_abs_path,
- repository_dir_abs_path,
- common_dir_abs_path,
- project_environment,
- fs,
- cx,
- ),
+ job_sender,
job_id: 0,
active_jobs: Default::default(),
}
@@ -3398,6 +3457,9 @@ impl Repository {
cx: &mut Context<Self>,
) -> Self {
let snapshot = RepositorySnapshot::empty(id, work_directory_abs_path, path_style);
+ let repository_state = RemoteRepositoryState { project_id, client };
+ let job_sender = Self::spawn_remote_git_worker(repository_state.clone(), cx);
+ let repository_state = Task::ready(Ok(RepositoryState::Remote(repository_state))).shared();
Self {
this: cx.weak_entity(),
snapshot,
@@ -3405,7 +3467,8 @@ impl Repository {
git_store,
pending_ops: Default::default(),
paths_needing_status_update: Default::default(),
- job_sender: Self::spawn_remote_git_worker(project_id, client, cx),
+ job_sender,
+ repository_state,
askpass_delegates: Default::default(),
latest_askpass_id: 0,
active_jobs: Default::default(),
@@ -3424,7 +3487,7 @@ impl Repository {
Some(GitJobKey::ReloadBufferDiffBases),
None,
|state, mut cx| async move {
- let RepositoryState::Local { backend, .. } = state else {
+ let RepositoryState::Local(LocalRepositoryState { backend, .. }) = state else {
log::error!("tried to recompute diffs for a non-local repository");
return Ok(());
};
@@ -3710,13 +3773,13 @@ impl Repository {
bail!("git store was dropped");
};
match state {
- RepositoryState::Local { .. } => {
+ RepositoryState::Local(..) => {
this.update(&mut cx, |_, cx| {
Self::open_local_commit_buffer(languages, buffer_store, cx)
})?
.await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let request = client.request(proto::OpenCommitMessageBuffer {
project_id: project_id.0,
repository_id: id.to_proto(),
@@ -3789,16 +3852,19 @@ impl Repository {
Some(format!("git checkout {}", commit).into()),
move |git_repo, _| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => {
+ }) => {
backend
.checkout_files(commit, paths, environment.clone())
.await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState {
+ project_id,
+ client,
+ }) => {
client
.request(proto::GitCheckoutFiles {
project_id: project_id.0,
@@ -3832,12 +3898,12 @@ impl Repository {
self.send_job(None, move |git_repo, _| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.reset(commit, reset_mode, environment).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.reset(commit, reset_mode, environment).await,
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::GitReset {
project_id: project_id.0,
@@ -3860,8 +3926,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local { backend, .. } => backend.show(commit).await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.show(commit).await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let resp = client
.request(proto::GitShow {
project_id: project_id.0,
@@ -3886,10 +3954,12 @@ impl Repository {
let id = self.id;
self.send_job(None, move |git_repo, cx| async move {
match git_repo {
- RepositoryState::Local { backend, .. } => backend.load_commit(commit, cx).await,
- RepositoryState::Remote {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.load_commit(commit, cx).await
+ }
+ RepositoryState::Remote(RemoteRepositoryState {
client, project_id, ..
- } => {
+ }) => {
let response = client
.request(proto::LoadCommitDiff {
project_id: project_id.0,
@@ -3979,12 +4049,15 @@ impl Repository {
Some(status.into()),
move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.stage_paths(entries, environment.clone()).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.stage_paths(entries, environment.clone()).await,
+ RepositoryState::Remote(RemoteRepositoryState {
+ project_id,
+ client,
+ }) => {
client
.request(proto::Stage {
project_id: project_id.0,
@@ -4041,12 +4114,15 @@ impl Repository {
Some(status.into()),
move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.unstage_paths(entries, environment).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.unstage_paths(entries, environment).await,
+ RepositoryState::Remote(RemoteRepositoryState {
+ project_id,
+ client,
+ }) => {
client
.request(proto::Unstage {
project_id: project_id.0,
@@ -4127,12 +4203,12 @@ impl Repository {
this.update(cx, |this, _| {
this.send_job(None, move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.stash_paths(entries, environment).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.stash_paths(entries, environment).await,
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::Stash {
project_id: project_id.0,
@@ -4164,12 +4240,12 @@ impl Repository {
this.update(cx, |this, _| {
this.send_job(None, move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.stash_pop(index, environment).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.stash_pop(index, environment).await,
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::StashPop {
project_id: project_id.0,
@@ -4198,12 +4274,12 @@ impl Repository {
this.update(cx, |this, _| {
this.send_job(None, move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.stash_apply(index, environment).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.stash_apply(index, environment).await,
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::StashApply {
project_id: project_id.0,
@@ -4239,11 +4315,11 @@ impl Repository {
let this = cx.weak_entity();
self.send_job(None, move |git_repo, mut cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => {
+ }) => {
// TODO would be nice to not have to do this manually
let result = backend.stash_drop(index, environment).await;
if result.is_ok()
@@ -4263,7 +4339,7 @@ impl Repository {
result
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::StashDrop {
project_id: project_id.0,
@@ -4284,12 +4360,12 @@ impl Repository {
Some(format!("git hook {}", hook.as_str()).into()),
move |git_repo, _cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.run_hook(hook, environment.clone()).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.run_hook(hook, environment.clone()).await,
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::RunGitHook {
project_id: project_id.0,
@@ -4323,16 +4399,16 @@ impl Repository {
rx.await??;
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => {
+ }) => {
backend
.commit(message, name_and_email, options, askpass, environment)
.await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
askpass_delegates.lock().insert(askpass_id, askpass);
let _defer = util::defer(|| {
let askpass_delegate = askpass_delegates.lock().remove(&askpass_id);
@@ -4373,12 +4449,12 @@ impl Repository {
self.send_job(Some("git fetch".into()), move |git_repo, cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => backend.fetch(fetch_options, askpass, environment, cx).await,
- RepositoryState::Remote { project_id, client } => {
+ }) => backend.fetch(fetch_options, askpass, environment, cx).await,
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
askpass_delegates.lock().insert(askpass_id, askpass);
let _defer = util::defer(|| {
let askpass_delegate = askpass_delegates.lock().remove(&askpass_id);
@@ -4437,11 +4513,11 @@ impl Repository {
Some(format!("git push {} {} {}", args, remote, branch).into()),
move |git_repo, mut cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => {
+ }) => {
let result = backend
.push(
branch.to_string(),
@@ -4470,7 +4546,7 @@ impl Repository {
}
result
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
askpass_delegates.lock().insert(askpass_id, askpass);
let _defer = util::defer(|| {
let askpass_delegate = askpass_delegates.lock().remove(&askpass_id);
@@ -4527,11 +4603,11 @@ impl Repository {
self.send_job(Some(status.into()), move |git_repo, cx| async move {
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
backend,
environment,
..
- } => {
+ }) => {
backend
.pull(
branch.as_ref().map(|b| b.to_string()),
@@ -4543,7 +4619,7 @@ impl Repository {
)
.await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
askpass_delegates.lock().insert(askpass_id, askpass);
let _defer = util::defer(|| {
let askpass_delegate = askpass_delegates.lock().remove(&askpass_id);
@@ -4591,12 +4667,12 @@ impl Repository {
);
match git_repo {
- RepositoryState::Local {
+ RepositoryState::Local(LocalRepositoryState {
fs,
backend,
environment,
..
- } => {
+ }) => {
let executable = match fs.metadata(&abs_path).await {
Ok(Some(meta)) => meta.is_executable,
Ok(None) => false,
@@ -4606,7 +4682,7 @@ impl Repository {
.set_index_text(path.clone(), content, environment.clone(), executable)
.await?;
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::SetIndexText {
project_id: project_id.0,
@@ -4654,8 +4730,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.get_remotes(branch_name).await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.get_remotes(branch_name).await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::GetRemotes {
project_id: project_id.0,
@@ -4682,8 +4760,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |repo, _| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.branches().await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.branches().await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::GitGetBranches {
project_id: project_id.0,
@@ -4707,8 +4787,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |repo, _| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.worktrees().await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.worktrees().await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::GitGetWorktrees {
project_id: project_id.0,
@@ -4739,10 +4821,10 @@ impl Repository {
Some("git worktree add".into()),
move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend.create_worktree(name, path, commit).await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::GitCreateWorktree {
project_id: project_id.0,
@@ -4764,8 +4846,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |repo, _| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.default_branch().await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.default_branch().await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::GetDefaultBranch {
project_id: project_id.0,
@@ -4787,8 +4871,10 @@ impl Repository {
let repository_id = self.snapshot.id;
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.diff_tree(diff_type).await,
- RepositoryState::Remote { client, project_id } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.diff_tree(diff_type).await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { client, project_id }) => {
let response = client
.request(proto::GetTreeDiff {
project_id: project_id.0,
@@ -4841,8 +4927,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.diff(diff_type).await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.diff(diff_type).await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::GitDiff {
project_id: project_id.0,
@@ -4877,10 +4965,10 @@ impl Repository {
};
self.send_job(Some(status_msg), move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend.create_branch(branch_name, base_branch).await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::GitCreateBranch {
project_id: project_id.0,
@@ -4901,10 +4989,10 @@ impl Repository {
Some(format!("git switch {branch_name}").into()),
move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend.change_branch(branch_name).await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::GitChangeBranch {
project_id: project_id.0,
@@ -4930,10 +5018,10 @@ impl Repository {
Some(format!("git branch -m {branch} {new_name}").into()),
move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend.rename_branch(branch, new_name).await
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
client
.request(proto::GitRenameBranch {
project_id: project_id.0,
@@ -4954,8 +5042,10 @@ impl Repository {
let id = self.id;
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.check_for_pushed_commit().await,
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.check_for_pushed_commit().await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::CheckForPushedCommits {
project_id: project_id.0,
@@ -4974,8 +5064,10 @@ impl Repository {
pub fn checkpoint(&mut self) -> oneshot::Receiver<Result<GitRepositoryCheckpoint>> {
self.send_job(None, |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => backend.checkpoint().await,
- RepositoryState::Remote { .. } => anyhow::bail!("not implemented yet"),
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.checkpoint().await
+ }
+ RepositoryState::Remote(..) => anyhow::bail!("not implemented yet"),
}
})
}
@@ -4986,7 +5078,7 @@ impl Repository {
) -> oneshot::Receiver<Result<()>> {
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend.restore_checkpoint(checkpoint).await
}
RepositoryState::Remote { .. } => anyhow::bail!("not implemented yet"),
@@ -5065,7 +5157,7 @@ impl Repository {
) -> oneshot::Receiver<Result<bool>> {
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend.compare_checkpoints(left, right).await
}
RepositoryState::Remote { .. } => anyhow::bail!("not implemented yet"),
@@ -5080,7 +5172,7 @@ impl Repository {
) -> oneshot::Receiver<Result<String>> {
self.send_job(None, move |repo, _cx| async move {
match repo {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
backend
.diff_checkpoints(base_checkpoint, target_checkpoint)
.await
@@ -5131,7 +5223,7 @@ impl Repository {
let Some(this) = this.upgrade() else {
return Ok(());
};
- let RepositoryState::Local { backend, .. } = state else {
+ let RepositoryState::Local(LocalRepositoryState { backend, .. }) = state else {
bail!("not a local repository")
};
let (snapshot, events) = this
@@ -5163,52 +5255,22 @@ impl Repository {
}
fn spawn_local_git_worker(
- work_directory_abs_path: Arc<Path>,
- dot_git_abs_path: Arc<Path>,
- _repository_dir_abs_path: Arc<Path>,
- _common_dir_abs_path: Arc<Path>,
- project_environment: WeakEntity<ProjectEnvironment>,
- fs: Arc<dyn Fs>,
+ state: Shared<Task<Result<LocalRepositoryState, String>>>,
cx: &mut Context<Self>,
) -> mpsc::UnboundedSender<GitJob> {
let (job_tx, mut job_rx) = mpsc::unbounded::<GitJob>();
- let fs_cloned = fs.clone();
cx.spawn(async move |_, cx| {
- let environment = project_environment
- .upgrade()
- .context("missing project environment")?
- .update(cx, |project_environment, cx| {
- project_environment.local_directory_environment(&Shell::System, work_directory_abs_path.clone(), cx)
- })?
- .await
- .unwrap_or_else(|| {
- log::error!("failed to get working directory environment for repository {work_directory_abs_path:?}");
- HashMap::default()
- });
- let search_paths = environment.get("PATH").map(|val| val.to_owned());
- let backend = cx
- .background_spawn(async move {
- let system_git_binary_path = search_paths.and_then(|search_paths| which::which_in("git", Some(search_paths), &work_directory_abs_path).ok())
- .or_else(|| which::which("git").ok());
- fs.open_repo(&dot_git_abs_path, system_git_binary_path.as_deref())
- .with_context(|| format!("opening repository at {dot_git_abs_path:?}"))
- })
- .await?;
-
+ let state = state.await.map_err(|err| anyhow::anyhow!(err))?;
if let Some(git_hosting_provider_registry) =
cx.update(|cx| GitHostingProviderRegistry::try_global(cx))?
{
git_hosting_providers::register_additional_providers(
git_hosting_provider_registry,
- backend.clone(),
+ state.backend.clone(),
);
}
- let state = RepositoryState::Local {
- fs: fs_cloned,
- backend,
- environment: Arc::new(environment),
- };
+ let state = RepositoryState::Local(state);
let mut jobs = VecDeque::new();
loop {
while let Ok(Some(next_job)) = job_rx.try_next() {
@@ -5220,9 +5282,9 @@ impl Repository {
&& jobs
.iter()
.any(|other_job| other_job.key.as_ref() == Some(current_key))
- {
- continue;
- }
+ {
+ continue;
+ }
(job.job)(state.clone(), cx).await;
} else if let Some(job) = job_rx.next().await {
jobs.push_back(job);
@@ -5238,14 +5300,13 @@ impl Repository {
}
fn spawn_remote_git_worker(
- project_id: ProjectId,
- client: AnyProtoClient,
+ state: RemoteRepositoryState,
cx: &mut Context<Self>,
) -> mpsc::UnboundedSender<GitJob> {
let (job_tx, mut job_rx) = mpsc::unbounded::<GitJob>();
cx.spawn(async move |_, cx| {
- let state = RepositoryState::Remote { project_id, client };
+ let state = RepositoryState::Remote(state);
let mut jobs = VecDeque::new();
loop {
while let Ok(Some(next_job)) = job_rx.try_next() {
@@ -5282,10 +5343,10 @@ impl Repository {
) -> Task<Result<Option<String>>> {
let rx = self.send_job(None, move |state, _| async move {
match state {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
anyhow::Ok(backend.load_index_text(repo_path).await)
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
let response = client
.request(proto::OpenUnstagedDiff {
project_id: project_id.to_proto(),
@@ -5307,7 +5368,7 @@ impl Repository {
) -> Task<Result<DiffBasesChange>> {
let rx = self.send_job(None, move |state, _| async move {
match state {
- RepositoryState::Local { backend, .. } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
let committed_text = backend.load_committed_text(repo_path.clone()).await;
let staged_text = backend.load_index_text(repo_path).await;
let diff_bases_change = if committed_text == staged_text {
@@ -5320,7 +5381,7 @@ impl Repository {
};
anyhow::Ok(diff_bases_change)
}
- RepositoryState::Remote { project_id, client } => {
+ RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => {
use proto::open_uncommitted_diff_response::Mode;
let response = client
@@ -5348,8 +5409,10 @@ impl Repository {
let repository_id = self.snapshot.id;
let rx = self.send_job(None, move |state, _| async move {
match state {
- RepositoryState::Local { backend, .. } => backend.load_blob_content(oid).await,
- RepositoryState::Remote { client, project_id } => {
+ RepositoryState::Local(LocalRepositoryState { backend, .. }) => {
+ backend.load_blob_content(oid).await
+ }
+ RepositoryState::Remote(RemoteRepositoryState { client, project_id }) => {
let response = client
.request(proto::GetBlobContent {
project_id: project_id.to_proto(),
@@ -5383,7 +5446,7 @@ impl Repository {
mem::take(&mut this.paths_needing_status_update),
)
})?;
- let RepositoryState::Local { backend, .. } = state else {
+ let RepositoryState::Local(LocalRepositoryState { backend, .. }) = state else {
bail!("not a local repository")
};