diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 7ed488b0ba62c10326a0e2154f0d2ba895e20a4f..20316fc3403de0e6212d13d455c5b619000d71b1 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -435,6 +435,7 @@ impl Server { .add_request_handler(forward_mutating_project_request::) .add_request_handler(forward_mutating_project_request::) .add_request_handler(forward_read_only_project_request::) + .add_request_handler(forward_read_only_project_request::) .add_request_handler(forward_mutating_project_request::) .add_request_handler(disallow_guest_request::) .add_request_handler(disallow_guest_request::) diff --git a/crates/collab/tests/integration/git_tests.rs b/crates/collab/tests/integration/git_tests.rs index fdaacd768444bd44d8414247f922f38afb7e81d5..2fa67b072f1c3d49ef5ca1b90056fd08d57df1ba 100644 --- a/crates/collab/tests/integration/git_tests.rs +++ b/crates/collab/tests/integration/git_tests.rs @@ -424,6 +424,58 @@ async fn test_remote_git_worktrees( ); } +#[gpui::test] +async fn test_remote_git_head_sha( + executor: BackgroundExecutor, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + let mut server = TestServer::start(executor.clone()).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + server + .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) + .await; + let active_call_a = cx_a.read(ActiveCall::global); + + client_a + .fs() + .insert_tree( + path!("/project"), + json!({ ".git": {}, "file.txt": "content" }), + ) + .await; + + let (project_a, _) = client_a.build_local_project(path!("/project"), cx_a).await; + let local_head_sha = cx_a.update(|cx| { + project_a + .read(cx) + .active_repository(cx) + .unwrap() + .update(cx, |repository, _| repository.head_sha()) + }); + let local_head_sha = local_head_sha.await.unwrap().unwrap(); + + let project_id = active_call_a + .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) + .await + .unwrap(); + let project_b = client_b.join_remote_project(project_id, cx_b).await; + + executor.run_until_parked(); + + let remote_head_sha = cx_b.update(|cx| { + project_b + .read(cx) + .active_repository(cx) + .unwrap() + .update(cx, |repository, _| repository.head_sha()) + }); + let remote_head_sha = remote_head_sha.await.unwrap(); + + assert_eq!(remote_head_sha.unwrap(), local_head_sha); +} + #[gpui::test] async fn test_linked_worktrees_sync( executor: BackgroundExecutor, diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index 1c18182b8949dad91aa53e8517acbc535c076319..fa37c43b4f4090aa97ea86087559949eec7b912a 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -594,6 +594,7 @@ impl GitStore { client.add_entity_request_handler(Self::handle_create_worktree); client.add_entity_request_handler(Self::handle_remove_worktree); client.add_entity_request_handler(Self::handle_rename_worktree); + client.add_entity_request_handler(Self::handle_get_head_sha); } pub fn is_local(&self) -> bool { @@ -2466,6 +2467,21 @@ impl GitStore { Ok(proto::Ack {}) } + async fn handle_get_head_sha( + this: Entity, + envelope: TypedEnvelope, + mut cx: AsyncApp, + ) -> Result { + let repository_id = RepositoryId::from_proto(envelope.payload.repository_id); + let repository_handle = Self::repository_for_request(&this, repository_id, &mut cx)?; + + let head_sha = repository_handle + .update(&mut cx, |repository_handle, _| repository_handle.head_sha()) + .await??; + + Ok(proto::GitGetHeadShaResponse { sha: head_sha }) + } + async fn handle_get_branches( this: Entity, envelope: TypedEnvelope, @@ -6052,13 +6068,21 @@ impl Repository { } pub fn head_sha(&mut self) -> oneshot::Receiver>> { + let id = self.id; self.send_job(None, move |repo, _cx| async move { match repo { RepositoryState::Local(LocalRepositoryState { backend, .. }) => { Ok(backend.head_sha().await) } - RepositoryState::Remote(_) => { - anyhow::bail!("head_sha is not supported for remote repositories") + RepositoryState::Remote(RemoteRepositoryState { project_id, client }) => { + let response = client + .request(proto::GitGetHeadSha { + project_id: project_id.0, + repository_id: id.to_proto(), + }) + .await?; + + Ok(response.sha) } } }) diff --git a/crates/proto/proto/git.proto b/crates/proto/proto/git.proto index 10b8914784ba9238e700f75b935accdc2fde2fac..779a71cf34d72684f1d4166894aac618bfdafffe 100644 --- a/crates/proto/proto/git.proto +++ b/crates/proto/proto/git.proto @@ -568,6 +568,15 @@ message GitGetWorktrees { uint64 repository_id = 2; } +message GitGetHeadSha { + uint64 project_id = 1; + uint64 repository_id = 2; +} + +message GitGetHeadShaResponse { + optional string sha = 1; +} + message GitWorktreesResponse { repeated Worktree worktrees = 1; } diff --git a/crates/proto/proto/zed.proto b/crates/proto/proto/zed.proto index 24e7c5372f2679eab1726487e1967edcef6024ed..8b62754d7af40b7c4f5e1a87ad42899d682ba453 100644 --- a/crates/proto/proto/zed.proto +++ b/crates/proto/proto/zed.proto @@ -474,7 +474,9 @@ message Envelope { GitCompareCheckpoints git_compare_checkpoints = 436; GitCompareCheckpointsResponse git_compare_checkpoints_response = 437; GitDiffCheckpoints git_diff_checkpoints = 438; - GitDiffCheckpointsResponse git_diff_checkpoints_response = 439; // current max + GitDiffCheckpointsResponse git_diff_checkpoints_response = 439; + GitGetHeadSha git_get_head_sha = 440; + GitGetHeadShaResponse git_get_head_sha_response = 441; // current max } reserved 87 to 88; diff --git a/crates/proto/src/proto.rs b/crates/proto/src/proto.rs index dd77d2a2da8d4dbc2c0f91f63cb59dd1591ee3f4..b77bd02313c13a9b04eb7762a97f9e77ac8cbaf8 100644 --- a/crates/proto/src/proto.rs +++ b/crates/proto/src/proto.rs @@ -351,6 +351,8 @@ messages!( (NewExternalAgentVersionAvailable, Background), (RemoteStarted, Background), (GitGetWorktrees, Background), + (GitGetHeadSha, Background), + (GitGetHeadShaResponse, Background), (GitWorktreesResponse, Background), (GitCreateWorktree, Background), (GitRemoveWorktree, Background), @@ -558,6 +560,7 @@ request_messages!( (GetContextServerCommand, ContextServerCommand), (RemoteStarted, Ack), (GitGetWorktrees, GitWorktreesResponse), + (GitGetHeadSha, GitGetHeadShaResponse), (GitCreateWorktree, Ack), (GitRemoveWorktree, Ack), (GitRenameWorktree, Ack), @@ -749,6 +752,7 @@ entity_messages!( ExternalAgentLoadingStatusUpdated, NewExternalAgentVersionAvailable, GitGetWorktrees, + GitGetHeadSha, GitCreateWorktree, GitRemoveWorktree, GitRenameWorktree,