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 <conrad.irwin@gmail.com>
Co-authored-by: Conrad <conrad@zed.dev>
This commit is contained in:
Michael Sloan 2025-06-12 13:39:08 -06:00 committed by GitHub
parent e56a027bea
commit 7d708c14e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 188 additions and 69 deletions

View file

@ -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");

View file

@ -0,0 +1,4 @@
alter table project_collaborators
add column committer_name varchar;
alter table project_collaborators
add column committer_email varchar;

View file

@ -751,6 +751,8 @@ pub struct ProjectCollaborator {
pub user_id: UserId,
pub replica_id: ReplicaId,
pub is_host: bool,
pub committer_name: Option<String>,
pub committer_email: Option<String>,
}
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(),
}
}
}

View file

@ -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,
});
}

View file

@ -739,7 +739,6 @@ impl Database {
),
github_login: user.github_login,
name: user.name,
email: user.email_address,
})
}
proto::ChannelMember {

View file

@ -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<String>,
committer_email: Option<String>,
) -> Result<TransactionGuard<(Project, ReplicaId)>> {
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<String>,
committer_email: Option<String>,
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,

View file

@ -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::<Vec<_>>();

View file

@ -13,6 +13,8 @@ pub struct Model {
pub user_id: UserId,
pub replica_id: ReplicaId,
pub is_host: bool,
pub committer_name: Option<String>,
pub committer_email: Option<String>,
}
impl Model {

View file

@ -126,12 +126,16 @@ async fn test_channel_buffers(db: &Arc<Database>) {
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,
}
]
);

View file

@ -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<proto::JoinProject> {
fn send(self, result: proto::JoinProjectResponse) -> Result<()> {
Response::<proto::JoinProject>::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 })?;

View file

@ -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()));

View file

@ -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()]