From 7d708c14e42fcfaba3aa7e716544303066e4c9a4 Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Thu, 12 Jun 2025 13:39:08 -0600 Subject: [PATCH] Use `git config --global user.email` for email address in automatic `Co-authored-by` (#32624) Release Notes: - Automatic population of `Co-authored-by` now uses `git config --global user.email` --------- Co-authored-by: Conrad Irwin Co-authored-by: Conrad --- Cargo.lock | 1 + crates/channel/src/channel_store_tests.rs | 3 - crates/client/src/client.rs | 12 +++- crates/client/src/user.rs | 6 +- .../20221109000000_test_schema.sql | 4 +- ...12153105_add_collaborator_commit_email.sql | 4 ++ crates/collab/src/db.rs | 4 ++ crates/collab/src/db/queries/buffers.rs | 8 +++ crates/collab/src/db/queries/channels.rs | 1 - crates/collab/src/db/queries/projects.rs | 36 ++++++++-- crates/collab/src/db/queries/rooms.rs | 4 ++ .../src/db/tables/project_collaborator.rs | 2 + crates/collab/src/db/tests/buffer_tests.rs | 4 ++ crates/collab/src/rpc.rs | 32 +++------ crates/collab/src/tests/following_tests.rs | 2 + crates/collab/src/tests/integration_tests.rs | 2 - crates/collab_ui/src/chat_panel.rs | 3 - crates/git/src/repository.rs | 46 +++++++++++- crates/git_ui/Cargo.toml | 1 + crates/git_ui/src/commit_modal.rs | 1 + crates/git_ui/src/git_panel.rs | 71 ++++++++++++------- crates/project/src/project.rs | 4 ++ crates/proto/proto/call.proto | 2 + crates/proto/proto/core.proto | 4 +- 24 files changed, 188 insertions(+), 69 deletions(-) create mode 100644 crates/collab/migrations/20250612153105_add_collaborator_commit_email.sql diff --git a/Cargo.lock b/Cargo.lock index 43ccf37022..2710f480e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6162,6 +6162,7 @@ dependencies = [ "anyhow", "askpass", "buffer_diff", + "call", "chrono", "collections", "command_palette_hooks", diff --git a/crates/channel/src/channel_store_tests.rs b/crates/channel/src/channel_store_tests.rs index d0fb1823a3..f8f5de3c39 100644 --- a/crates/channel/src/channel_store_tests.rs +++ b/crates/channel/src/channel_store_tests.rs @@ -269,7 +269,6 @@ async fn test_channel_messages(cx: &mut TestAppContext) { github_login: "nathansobo".into(), avatar_url: "http://avatar.com/nathansobo".into(), name: None, - email: None, }], }, ); @@ -323,7 +322,6 @@ async fn test_channel_messages(cx: &mut TestAppContext) { github_login: "maxbrunsfeld".into(), avatar_url: "http://avatar.com/maxbrunsfeld".into(), name: None, - email: None, }], }, ); @@ -368,7 +366,6 @@ async fn test_channel_messages(cx: &mut TestAppContext) { github_login: "as-cii".into(), avatar_url: "http://avatar.com/as-cii".into(), name: None, - email: None, }], }, ); diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index c035c36258..86612bd15b 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -1887,8 +1887,16 @@ mod tests { .set_entity(&entity3, &mut cx.to_async()); drop(subscription3); - server.send(proto::JoinProject { project_id: 1 }); - server.send(proto::JoinProject { project_id: 2 }); + server.send(proto::JoinProject { + project_id: 1, + committer_name: None, + committer_email: None, + }); + server.send(proto::JoinProject { + project_id: 2, + committer_name: None, + committer_email: None, + }); done_rx1.recv().await.unwrap(); done_rx2.recv().await.unwrap(); } diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index 27120cbbac..1be8d71e85 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -49,7 +49,6 @@ pub struct User { pub github_login: String, pub avatar_uri: SharedUri, pub name: Option, - pub email: Option, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -58,6 +57,8 @@ pub struct Collaborator { pub replica_id: ReplicaId, pub user_id: UserId, pub is_host: bool, + pub committer_name: Option, + pub committer_email: Option, } impl PartialOrd for User { @@ -881,7 +882,6 @@ impl User { github_login: message.github_login, avatar_uri: message.avatar_url.into(), name: message.name, - email: message.email, }) } } @@ -912,6 +912,8 @@ impl Collaborator { replica_id: message.replica_id as ReplicaId, user_id: message.user_id as UserId, is_host: message.is_host, + committer_name: message.committer_name, + committer_email: message.committer_email, }) } } diff --git a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql index a1129bdeba..506920434e 100644 --- a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql +++ b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql @@ -185,7 +185,9 @@ CREATE TABLE "project_collaborators" ( "connection_server_id" INTEGER NOT NULL REFERENCES servers (id) ON DELETE CASCADE, "user_id" INTEGER NOT NULL, "replica_id" INTEGER NOT NULL, - "is_host" BOOLEAN NOT NULL + "is_host" BOOLEAN NOT NULL, + "committer_name" VARCHAR, + "committer_email" VARCHAR ); CREATE INDEX "index_project_collaborators_on_project_id" ON "project_collaborators" ("project_id"); diff --git a/crates/collab/migrations/20250612153105_add_collaborator_commit_email.sql b/crates/collab/migrations/20250612153105_add_collaborator_commit_email.sql new file mode 100644 index 0000000000..73876e8965 --- /dev/null +++ b/crates/collab/migrations/20250612153105_add_collaborator_commit_email.sql @@ -0,0 +1,4 @@ +alter table project_collaborators + add column committer_name varchar; +alter table project_collaborators + add column committer_email varchar; diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index b319abc5e7..bb264d5adb 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -751,6 +751,8 @@ pub struct ProjectCollaborator { pub user_id: UserId, pub replica_id: ReplicaId, pub is_host: bool, + pub committer_name: Option, + pub committer_email: Option, } impl ProjectCollaborator { @@ -760,6 +762,8 @@ impl ProjectCollaborator { replica_id: self.replica_id.0 as u32, user_id: self.user_id.to_proto(), is_host: self.is_host, + committer_name: self.committer_name.clone(), + committer_email: self.committer_email.clone(), } } } diff --git a/crates/collab/src/db/queries/buffers.rs b/crates/collab/src/db/queries/buffers.rs index cbd0dec383..a288a4e7eb 100644 --- a/crates/collab/src/db/queries/buffers.rs +++ b/crates/collab/src/db/queries/buffers.rs @@ -118,6 +118,8 @@ impl Database { user_id: collaborator.user_id.to_proto(), replica_id: collaborator.replica_id.0 as u32, is_host: false, + committer_name: None, + committer_email: None, }) .collect(), }) @@ -225,6 +227,8 @@ impl Database { user_id: collaborator.user_id.to_proto(), replica_id: collaborator.replica_id.0 as u32, is_host: false, + committer_name: None, + committer_email: None, }) .collect(), }, @@ -261,6 +265,8 @@ impl Database { replica_id: db_collaborator.replica_id.0 as u32, user_id: db_collaborator.user_id.to_proto(), is_host: false, + committer_name: None, + committer_email: None, }) } else { collaborator_ids_to_remove.push(db_collaborator.id); @@ -390,6 +396,8 @@ impl Database { replica_id: row.replica_id.0 as u32, user_id: row.user_id.to_proto(), is_host: false, + committer_name: None, + committer_email: None, }); } diff --git a/crates/collab/src/db/queries/channels.rs b/crates/collab/src/db/queries/channels.rs index f517256f55..a4899f408d 100644 --- a/crates/collab/src/db/queries/channels.rs +++ b/crates/collab/src/db/queries/channels.rs @@ -739,7 +739,6 @@ impl Database { ), github_login: user.github_login, name: user.name, - email: user.email_address, }) } proto::ChannelMember { diff --git a/crates/collab/src/db/queries/projects.rs b/crates/collab/src/db/queries/projects.rs index f57b84c41d..ae244b2516 100644 --- a/crates/collab/src/db/queries/projects.rs +++ b/crates/collab/src/db/queries/projects.rs @@ -98,7 +98,9 @@ impl Database { user_id: ActiveValue::set(participant.user_id), replica_id: ActiveValue::set(ReplicaId(replica_id)), is_host: ActiveValue::set(true), - ..Default::default() + id: ActiveValue::NotSet, + committer_name: ActiveValue::Set(None), + committer_email: ActiveValue::Set(None), } .insert(&*tx) .await?; @@ -784,13 +786,27 @@ impl Database { project_id: ProjectId, connection: ConnectionId, user_id: UserId, + committer_name: Option, + committer_email: Option, ) -> Result> { - self.project_transaction(project_id, |tx| async move { - let (project, role) = self - .access_project(project_id, connection, Capability::ReadOnly, &tx) - .await?; - self.join_project_internal(project, user_id, connection, role, &tx) + self.project_transaction(project_id, move |tx| { + let committer_name = committer_name.clone(); + let committer_email = committer_email.clone(); + async move { + let (project, role) = self + .access_project(project_id, connection, Capability::ReadOnly, &tx) + .await?; + self.join_project_internal( + project, + user_id, + committer_name, + committer_email, + connection, + role, + &tx, + ) .await + } }) .await } @@ -799,6 +815,8 @@ impl Database { &self, project: project::Model, user_id: UserId, + committer_name: Option, + committer_email: Option, connection: ConnectionId, role: ChannelRole, tx: &DatabaseTransaction, @@ -822,7 +840,9 @@ impl Database { user_id: ActiveValue::set(user_id), replica_id: ActiveValue::set(replica_id), is_host: ActiveValue::set(false), - ..Default::default() + id: ActiveValue::NotSet, + committer_name: ActiveValue::set(committer_name), + committer_email: ActiveValue::set(committer_email), } .insert(tx) .await?; @@ -1026,6 +1046,8 @@ impl Database { user_id: collaborator.user_id, replica_id: collaborator.replica_id, is_host: collaborator.is_host, + committer_name: collaborator.committer_name, + committer_email: collaborator.committer_email, }) .collect(), worktrees, diff --git a/crates/collab/src/db/queries/rooms.rs b/crates/collab/src/db/queries/rooms.rs index 0ffc46b185..33eaa95aa2 100644 --- a/crates/collab/src/db/queries/rooms.rs +++ b/crates/collab/src/db/queries/rooms.rs @@ -553,6 +553,8 @@ impl Database { user_id: collaborator.user_id, replica_id: collaborator.replica_id, is_host: collaborator.is_host, + committer_name: collaborator.committer_name.clone(), + committer_email: collaborator.committer_email.clone(), }) .collect(), worktrees: reshared_project.worktrees.clone(), @@ -857,6 +859,8 @@ impl Database { user_id: collaborator.user_id, replica_id: collaborator.replica_id, is_host: collaborator.is_host, + committer_name: collaborator.committer_name, + committer_email: collaborator.committer_email, }) .collect::>(); diff --git a/crates/collab/src/db/tables/project_collaborator.rs b/crates/collab/src/db/tables/project_collaborator.rs index ac57befa63..1564abdf46 100644 --- a/crates/collab/src/db/tables/project_collaborator.rs +++ b/crates/collab/src/db/tables/project_collaborator.rs @@ -13,6 +13,8 @@ pub struct Model { pub user_id: UserId, pub replica_id: ReplicaId, pub is_host: bool, + pub committer_name: Option, + pub committer_email: Option, } impl Model { diff --git a/crates/collab/src/db/tests/buffer_tests.rs b/crates/collab/src/db/tests/buffer_tests.rs index 13c440d437..49da0f3714 100644 --- a/crates/collab/src/db/tests/buffer_tests.rs +++ b/crates/collab/src/db/tests/buffer_tests.rs @@ -126,12 +126,16 @@ async fn test_channel_buffers(db: &Arc) { peer_id: Some(rpc::proto::PeerId { id: 1, owner_id }), replica_id: 0, is_host: false, + committer_name: None, + committer_email: None, }, rpc::proto::Collaborator { user_id: b_id.to_proto(), peer_id: Some(rpc::proto::PeerId { id: 2, owner_id }), replica_id: 1, is_host: false, + committer_name: None, + committer_email: None, } ] ); diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index c573b7e7c0..8adc40a9f7 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -14,7 +14,7 @@ use crate::{ db::{ self, BufferId, Capability, Channel, ChannelId, ChannelRole, ChannelsForUser, CreatedChannelMessage, Database, InviteMemberResult, MembershipUpdated, MessageId, - NotificationId, Project, ProjectId, RejoinedProject, RemoveChannelMemberResult, ReplicaId, + NotificationId, ProjectId, RejoinedProject, RemoveChannelMemberResult, RespondToChannelInvite, RoomId, ServerId, UpdatedChannelMessage, User, UserId, }, executor::Executor, @@ -1890,28 +1890,16 @@ async fn join_project( let db = session.db().await; let (project, replica_id) = &mut *db - .join_project(project_id, session.connection_id, session.user_id()) + .join_project( + project_id, + session.connection_id, + session.user_id(), + request.committer_name.clone(), + request.committer_email.clone(), + ) .await?; drop(db); tracing::info!(%project_id, "join remote project"); - join_project_internal(response, session, project, replica_id) -} - -trait JoinProjectInternalResponse { - fn send(self, result: proto::JoinProjectResponse) -> Result<()>; -} -impl JoinProjectInternalResponse for Response { - fn send(self, result: proto::JoinProjectResponse) -> Result<()> { - Response::::send(self, result) - } -} - -fn join_project_internal( - response: impl JoinProjectInternalResponse, - session: Session, - project: &mut Project, - replica_id: &ReplicaId, -) -> Result<()> { let collaborators = project .collaborators .iter() @@ -1939,6 +1927,8 @@ fn join_project_internal( replica_id: replica_id.0 as u32, user_id: guest_user_id.to_proto(), is_host: false, + committer_name: request.committer_name.clone(), + committer_email: request.committer_email.clone(), }), }; @@ -2567,7 +2557,6 @@ async fn get_users( id: user.id.to_proto(), avatar_url: format!("https://github.com/{}.png?size=128", user.github_login), github_login: user.github_login, - email: user.email_address, name: user.name, }) .collect(); @@ -2601,7 +2590,6 @@ async fn fuzzy_search_users( avatar_url: format!("https://github.com/{}.png?size=128", user.github_login), github_login: user.github_login, name: user.name, - email: user.email_address, }) .collect(); response.send(proto::UsersResponse { users })?; diff --git a/crates/collab/src/tests/following_tests.rs b/crates/collab/src/tests/following_tests.rs index 7b44fceb53..99f9b33505 100644 --- a/crates/collab/src/tests/following_tests.rs +++ b/crates/collab/src/tests/following_tests.rs @@ -1610,6 +1610,8 @@ async fn test_following_across_workspaces(cx_a: &mut TestAppContext, cx_b: &mut .root(cx_a) .unwrap(); + executor.run_until_parked(); + workspace_a_project_b.update(cx_a2, |workspace, cx| { assert_eq!(workspace.project().read(cx).remote_id(), Some(project_b_id)); assert!(workspace.is_being_followed(client_b.peer_id().unwrap())); diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index d00ff0baba..548fa85f63 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -1876,7 +1876,6 @@ async fn test_active_call_events( github_login: "user_a".to_string(), avatar_uri: "avatar_a".into(), name: None, - email: None, }), project_id: project_a_id, worktree_root_names: vec!["a".to_string()], @@ -1896,7 +1895,6 @@ async fn test_active_call_events( github_login: "user_b".to_string(), avatar_uri: "avatar_b".into(), name: None, - email: None, }), project_id: project_b_id, worktree_root_names: vec!["b".to_string()] diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index 55b7ade771..92f20581ae 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -1218,7 +1218,6 @@ mod tests { avatar_uri: "avatar_fgh".into(), id: 103, name: None, - email: None, }), nonce: 5, mentions: vec![(ranges[0].clone(), 101), (ranges[1].clone(), 102)], @@ -1274,7 +1273,6 @@ mod tests { avatar_uri: "avatar_fgh".into(), id: 103, name: None, - email: None, }), nonce: 5, mentions: Vec::new(), @@ -1323,7 +1321,6 @@ mod tests { avatar_uri: "avatar_fgh".into(), id: 103, name: None, - email: None, }), nonce: 5, mentions: Vec::new(), diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 165497d129..1254e451fd 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -26,8 +26,8 @@ use std::{ }; use sum_tree::MapSeekTarget; use thiserror::Error; -use util::ResultExt; use util::command::{new_smol_command, new_std_command}; +use util::{ResultExt, paths}; use uuid::Uuid; pub use askpass::{AskPassDelegate, AskPassResult, AskPassSession}; @@ -508,6 +508,50 @@ pub struct GitRepositoryCheckpoint { pub commit_sha: Oid, } +#[derive(Debug)] +pub struct GitCommitter { + pub name: Option, + pub email: Option, +} + +pub async fn get_git_committer(cx: &AsyncApp) -> GitCommitter { + if cfg!(any(feature = "test-support", test)) { + return GitCommitter { + name: None, + email: None, + }; + } + + let git_binary_path = + if cfg!(target_os = "macos") && option_env!("ZED_BUNDLE").as_deref() == Some("true") { + cx.update(|cx| { + cx.path_for_auxiliary_executable("git") + .context("could not find git binary path") + .log_err() + }) + .ok() + .flatten() + } else { + None + }; + + let git = GitBinary::new( + git_binary_path.unwrap_or(PathBuf::from("git")), + paths::home_dir().clone(), + cx.background_executor().clone(), + ); + + cx.background_spawn(async move { + let name = git.run(["config", "--global", "user.name"]).await.log_err(); + let email = git + .run(["config", "--global", "user.email"]) + .await + .log_err(); + GitCommitter { name, email } + }) + .await +} + impl GitRepository for RealGitRepository { fn reload_index(&self) { if let Ok(mut index) = self.repository.lock().index() { diff --git a/crates/git_ui/Cargo.toml b/crates/git_ui/Cargo.toml index b596b57fe0..cef6c4913f 100644 --- a/crates/git_ui/Cargo.toml +++ b/crates/git_ui/Cargo.toml @@ -21,6 +21,7 @@ agent_settings.workspace = true anyhow.workspace = true askpass.workspace = true buffer_diff.workspace = true +call.workspace = true chrono.workspace = true collections.workspace = true command_palette_hooks.workspace = true diff --git a/crates/git_ui/src/commit_modal.rs b/crates/git_ui/src/commit_modal.rs index 6f4e67ddb9..15d0bec313 100644 --- a/crates/git_ui/src/commit_modal.rs +++ b/crates/git_ui/src/commit_modal.rs @@ -148,6 +148,7 @@ impl CommitModal { } } git_panel.set_modal_open(true, cx); + git_panel.load_local_committer(cx); }); let dock = workspace.dock_at_position(git_panel.position(window, cx)); diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 33418fd483..0eca135637 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -20,8 +20,9 @@ use editor::{ use futures::StreamExt as _; use git::blame::ParsedCommitMessage; use git::repository::{ - Branch, CommitDetails, CommitOptions, CommitSummary, DiffType, FetchOptions, PushOptions, - Remote, RemoteCommandOutput, ResetMode, Upstream, UpstreamTracking, UpstreamTrackingStatus, + Branch, CommitDetails, CommitOptions, CommitSummary, DiffType, FetchOptions, GitCommitter, + PushOptions, Remote, RemoteCommandOutput, ResetMode, Upstream, UpstreamTracking, + UpstreamTrackingStatus, get_git_committer, }; use git::status::StageStatus; use git::{Amend, ToggleStaged, repository::RepoPath, status::FileStatus}; @@ -358,6 +359,8 @@ pub struct GitPanel { context_menu: Option<(Entity, Point, Subscription)>, modal_open: bool, show_placeholders: bool, + local_committer: Option, + local_committer_task: Option>, _settings_subscription: Subscription, } @@ -520,6 +523,8 @@ impl GitPanel { update_visible_entries_task: Task::ready(()), width: None, show_placeholders: false, + local_committer: None, + local_committer_task: None, context_menu: None, workspace: workspace.weak_handle(), modal_open: false, @@ -2250,6 +2255,19 @@ impl GitPanel { } } + pub fn load_local_committer(&mut self, cx: &Context) { + if self.local_committer_task.is_none() { + self.local_committer_task = Some(cx.spawn(async move |this, cx| { + let committer = get_git_committer(cx).await; + this.update(cx, |this, cx| { + this.local_committer = Some(committer); + cx.notify() + }) + .ok(); + })); + } + } + fn potential_co_authors(&self, cx: &App) -> Vec<(String, String)> { let mut new_co_authors = Vec::new(); let project = self.project.read(cx); @@ -2272,34 +2290,38 @@ impl GitPanel { let Some(participant) = room.remote_participant_for_peer_id(*peer_id) else { continue; }; - if participant.can_write() && participant.user.email.is_some() { - let email = participant.user.email.clone().unwrap(); - - new_co_authors.push(( - participant - .user - .name - .clone() - .unwrap_or_else(|| participant.user.github_login.clone()), - email, - )) + if !participant.can_write() { + continue; + } + if let Some(email) = &collaborator.committer_email { + let name = collaborator + .committer_name + .clone() + .or_else(|| participant.user.name.clone()) + .unwrap_or_else(|| participant.user.github_login.clone()); + new_co_authors.push((name.clone(), email.clone())) } } if !project.is_local() && !project.is_read_only(cx) { - if let Some(user) = room.local_participant_user(cx) { - if let Some(email) = user.email.clone() { - new_co_authors.push(( - user.name - .clone() - .unwrap_or_else(|| user.github_login.clone()), - email.clone(), - )) - } + if let Some(local_committer) = self.local_committer(room, cx) { + new_co_authors.push(local_committer); } } new_co_authors } + fn local_committer(&self, room: &call::Room, cx: &App) -> Option<(String, String)> { + let user = room.local_participant_user(cx)?; + let committer = self.local_committer.as_ref()?; + let email = committer.email.clone()?; + let name = committer + .name + .clone() + .or_else(|| user.name.clone()) + .unwrap_or_else(|| user.github_login.clone()); + Some((name, email)) + } + fn toggle_fill_co_authors( &mut self, _: &ToggleFillCoAuthors, @@ -4244,8 +4266,9 @@ impl Render for GitPanel { let has_write_access = self.has_write_access(cx); let has_co_authors = room.map_or(false, |room| { - room.read(cx) - .remote_participants() + self.load_local_committer(cx); + let room = room.read(cx); + room.remote_participants() .values() .any(|remote_participant| remote_participant.can_write()) }); diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 626e7430d3..f8db5362ff 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -26,6 +26,7 @@ mod environment; use buffer_diff::BufferDiff; use context_server_store::ContextServerStore; pub use environment::{EnvironmentErrorMessage, ProjectEnvironmentEvent}; +use git::repository::get_git_committer; use git_store::{Repository, RepositoryId}; pub mod search_history; mod yarn; @@ -1323,9 +1324,12 @@ impl Project { ), EntitySubscription::DapStore(client.subscribe_to_entity::(remote_id)?), ]; + let committer = get_git_committer(&cx).await; let response = client .request_envelope(proto::JoinProject { project_id: remote_id, + committer_email: committer.email, + committer_name: committer.name, }) .await?; Self::from_join_project_response( diff --git a/crates/proto/proto/call.proto b/crates/proto/proto/call.proto index a223f79949..5212f3b43f 100644 --- a/crates/proto/proto/call.proto +++ b/crates/proto/proto/call.proto @@ -189,6 +189,8 @@ message UpdateProject { message JoinProject { uint64 project_id = 1; + optional string committer_email = 2; + optional string committer_name = 3; } message JoinProjectResponse { diff --git a/crates/proto/proto/core.proto b/crates/proto/proto/core.proto index d44d457d09..121ea74912 100644 --- a/crates/proto/proto/core.proto +++ b/crates/proto/proto/core.proto @@ -7,10 +7,10 @@ message PeerId { } message User { + reserved 4; uint64 id = 1; string github_login = 2; string avatar_url = 3; - optional string email = 4; optional string name = 5; } @@ -24,4 +24,6 @@ message Collaborator { uint32 replica_id = 2; uint64 user_id = 3; bool is_host = 4; + optional string committer_name = 5; + optional string committer_email = 6; }