Allow filling co-authors in the git panel's commit input (#23329)
https://github.com/user-attachments/assets/78db908e-cfe5-4803-b0dc-4f33bc457840 * starts to extract usernames out of `users/` GitHub API responses, and pass those along with e-mails in the collab sessions as part of the `User` data * adjusts various prefill and seed test methods so that the new data can be retrieved from GitHub properly * if there's an active call, where guests have write permissions and e-mails, allow to trigger `FillCoAuthors` action in the context of the git panel, that will fill in `co-authored-by:` lines, using e-mail and names (or GitHub handle names if name is absent) * the action tries to not duplicate such entries, if any are present already, and adds those below the rest of the commit input's text Concerns: * users with write permissions and no e-mails will be silently omitted — adding odd entries that try to indicate this or raising pop-ups is very intrusive (maybe, we can add `#`-prefixed comments?), logging seems pointless * it's not clear whether the data prefill will run properly on the existing users — seems tolerable now, as it seems that we get e-mails properly already, so we'll see GitHub handles instead of names in the worst case. This can be prefilled better later. * e-mails and names for a particular project may be not what the user wants. E.g. my `.gitconfig` has ``` [user] email = mail4score@gmail.com # .....snip [includeif "gitdir:**/work/zed/**/.git"] path = ~/.gitconfig.work ``` and that one has ``` [user] email = kirill@zed.dev ``` while my GitHub profile is configured so, that `mail4score@gmail.com` is the public, commit e-mail. So, when I'm a participant in a Zed session, wrong e-mail will be picked. The problem is, it's impossible for a host to get remote's collaborator git metadata for a particular project, as that might not even exist on disk for the client. Seems that we might want to add some "project git URL <-> user name and email" mapping in the settings(?). The design of this is not very clear, so the PR concentrates on the basics for now. When https://github.com/zed-industries/zed/pull/23308 lands, most of the issues can be solved by collaborators manually, before committing. Release Notes: - N/A
This commit is contained in:
parent
ac214c52c9
commit
0199eca289
32 changed files with 215 additions and 14 deletions
|
@ -726,6 +726,8 @@ impl Database {
|
|||
user.github_login
|
||||
),
|
||||
github_login: user.github_login,
|
||||
name: user.name,
|
||||
email: user.email_address,
|
||||
})
|
||||
}
|
||||
proto::ChannelMember {
|
||||
|
|
|
@ -65,6 +65,7 @@ impl Database {
|
|||
github_login: &str,
|
||||
github_user_id: i32,
|
||||
github_email: Option<&str>,
|
||||
github_name: Option<&str>,
|
||||
github_user_created_at: DateTimeUtc,
|
||||
initial_channel_id: Option<ChannelId>,
|
||||
) -> Result<()> {
|
||||
|
@ -74,6 +75,7 @@ impl Database {
|
|||
github_login,
|
||||
github_user_id,
|
||||
github_email,
|
||||
github_name,
|
||||
github_user_created_at.naive_utc(),
|
||||
initial_channel_id,
|
||||
&tx,
|
||||
|
|
|
@ -7,6 +7,7 @@ impl Database {
|
|||
pub async fn create_user(
|
||||
&self,
|
||||
email_address: &str,
|
||||
name: Option<&str>,
|
||||
admin: bool,
|
||||
params: NewUserParams,
|
||||
) -> Result<NewUserResult> {
|
||||
|
@ -14,6 +15,7 @@ impl Database {
|
|||
let tx = tx;
|
||||
let user = user::Entity::insert(user::ActiveModel {
|
||||
email_address: ActiveValue::set(Some(email_address.into())),
|
||||
name: ActiveValue::set(name.map(|s| s.into())),
|
||||
github_login: ActiveValue::set(params.github_login.clone()),
|
||||
github_user_id: ActiveValue::set(params.github_user_id),
|
||||
admin: ActiveValue::set(admin),
|
||||
|
@ -101,6 +103,7 @@ impl Database {
|
|||
github_login: &str,
|
||||
github_user_id: i32,
|
||||
github_email: Option<&str>,
|
||||
github_name: Option<&str>,
|
||||
github_user_created_at: DateTimeUtc,
|
||||
initial_channel_id: Option<ChannelId>,
|
||||
) -> Result<User> {
|
||||
|
@ -109,6 +112,7 @@ impl Database {
|
|||
github_login,
|
||||
github_user_id,
|
||||
github_email,
|
||||
github_name,
|
||||
github_user_created_at.naive_utc(),
|
||||
initial_channel_id,
|
||||
&tx,
|
||||
|
@ -118,11 +122,13 @@ impl Database {
|
|||
.await
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn get_or_create_user_by_github_account_tx(
|
||||
&self,
|
||||
github_login: &str,
|
||||
github_user_id: i32,
|
||||
github_email: Option<&str>,
|
||||
github_name: Option<&str>,
|
||||
github_user_created_at: NaiveDateTime,
|
||||
initial_channel_id: Option<ChannelId>,
|
||||
tx: &DatabaseTransaction,
|
||||
|
@ -150,6 +156,7 @@ impl Database {
|
|||
} else {
|
||||
let user = user::Entity::insert(user::ActiveModel {
|
||||
email_address: ActiveValue::set(github_email.map(|email| email.into())),
|
||||
name: ActiveValue::set(github_name.map(|name| name.into())),
|
||||
github_login: ActiveValue::set(github_login.into()),
|
||||
github_user_id: ActiveValue::set(github_user_id),
|
||||
github_user_created_at: ActiveValue::set(Some(github_user_created_at)),
|
||||
|
|
|
@ -13,6 +13,7 @@ pub struct Model {
|
|||
pub github_user_id: i32,
|
||||
pub github_user_created_at: Option<NaiveDateTime>,
|
||||
pub email_address: Option<String>,
|
||||
pub name: Option<String>,
|
||||
pub admin: bool,
|
||||
pub invite_code: Option<String>,
|
||||
pub invite_count: i32,
|
||||
|
|
|
@ -177,6 +177,7 @@ static GITHUB_USER_ID: AtomicI32 = AtomicI32::new(5);
|
|||
async fn new_test_user(db: &Arc<Database>, email: &str) -> UserId {
|
||||
db.create_user(
|
||||
email,
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: email[0..email.find('@').unwrap()].to_string(),
|
||||
|
|
|
@ -13,6 +13,7 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
let a_id = db
|
||||
.create_user(
|
||||
"user_a@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_a".into(),
|
||||
|
@ -25,6 +26,7 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
let b_id = db
|
||||
.create_user(
|
||||
"user_b@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_b".into(),
|
||||
|
@ -39,6 +41,7 @@ async fn test_channel_buffers(db: &Arc<Database>) {
|
|||
let c_id = db
|
||||
.create_user(
|
||||
"user_c@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_c".into(),
|
||||
|
@ -176,6 +179,7 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||
let user_id = db
|
||||
.create_user(
|
||||
"user_a@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_a".into(),
|
||||
|
@ -188,6 +192,7 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||
let observer_id = db
|
||||
.create_user(
|
||||
"user_b@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user_b".into(),
|
||||
|
|
|
@ -269,6 +269,7 @@ async fn test_channel_renames(db: &Arc<Database>) {
|
|||
let user_1 = db
|
||||
.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".into(),
|
||||
|
@ -282,6 +283,7 @@ async fn test_channel_renames(db: &Arc<Database>) {
|
|||
let user_2 = db
|
||||
.create_user(
|
||||
"user2@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user2".into(),
|
||||
|
@ -318,6 +320,7 @@ async fn test_db_channel_moving(db: &Arc<Database>) {
|
|||
let a_id = db
|
||||
.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".into(),
|
||||
|
@ -372,6 +375,7 @@ async fn test_db_channel_moving_bugs(db: &Arc<Database>) {
|
|||
let user_id = db
|
||||
.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".into(),
|
||||
|
|
|
@ -13,6 +13,7 @@ test_both_dbs!(
|
|||
async fn test_contributors(db: &Arc<Database>) {
|
||||
db.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".to_string(),
|
||||
|
@ -25,7 +26,7 @@ async fn test_contributors(db: &Arc<Database>) {
|
|||
assert_eq!(db.get_contributors().await.unwrap(), Vec::<String>::new());
|
||||
|
||||
let user1_created_at = Utc::now();
|
||||
db.add_contributor("user1", 1, None, user1_created_at, None)
|
||||
db.add_contributor("user1", 1, None, None, user1_created_at, None)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
|
@ -34,7 +35,7 @@ async fn test_contributors(db: &Arc<Database>) {
|
|||
);
|
||||
|
||||
let user2_created_at = Utc::now();
|
||||
db.add_contributor("user2", 2, None, user2_created_at, None)
|
||||
db.add_contributor("user2", 2, None, None, user2_created_at, None)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
|
|
|
@ -17,6 +17,7 @@ async fn test_get_users(db: &Arc<Database>) {
|
|||
let user = db
|
||||
.create_user(
|
||||
&format!("user{i}@example.com"),
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: format!("user{i}"),
|
||||
|
@ -79,6 +80,7 @@ test_both_dbs!(
|
|||
async fn test_get_or_create_user_by_github_account(db: &Arc<Database>) {
|
||||
db.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "login1".into(),
|
||||
|
@ -90,6 +92,7 @@ async fn test_get_or_create_user_by_github_account(db: &Arc<Database>) {
|
|||
let user_id2 = db
|
||||
.create_user(
|
||||
"user2@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "login2".into(),
|
||||
|
@ -101,7 +104,7 @@ async fn test_get_or_create_user_by_github_account(db: &Arc<Database>) {
|
|||
.user_id;
|
||||
|
||||
let user = db
|
||||
.get_or_create_user_by_github_account("the-new-login2", 102, None, Utc::now(), None)
|
||||
.get_or_create_user_by_github_account("the-new-login2", 102, None, None, Utc::now(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(user.id, user_id2);
|
||||
|
@ -113,6 +116,7 @@ async fn test_get_or_create_user_by_github_account(db: &Arc<Database>) {
|
|||
"login3",
|
||||
103,
|
||||
Some("user3@example.com"),
|
||||
None,
|
||||
Utc::now(),
|
||||
None,
|
||||
)
|
||||
|
@ -133,6 +137,7 @@ async fn test_create_access_tokens(db: &Arc<Database>) {
|
|||
let user_1 = db
|
||||
.create_user(
|
||||
"u1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "u1".into(),
|
||||
|
@ -145,6 +150,7 @@ async fn test_create_access_tokens(db: &Arc<Database>) {
|
|||
let user_2 = db
|
||||
.create_user(
|
||||
"u2@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "u2".into(),
|
||||
|
@ -296,6 +302,7 @@ async fn test_add_contacts(db: &Arc<Database>) {
|
|||
user_ids.push(
|
||||
db.create_user(
|
||||
&format!("user{i}@example.com"),
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: format!("user{i}"),
|
||||
|
@ -457,6 +464,7 @@ async fn test_metrics_id(db: &Arc<Database>) {
|
|||
} = db
|
||||
.create_user(
|
||||
"person1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "person1".into(),
|
||||
|
@ -472,6 +480,7 @@ async fn test_metrics_id(db: &Arc<Database>) {
|
|||
} = db
|
||||
.create_user(
|
||||
"person2@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "person2".into(),
|
||||
|
@ -500,6 +509,7 @@ async fn test_project_count(db: &Arc<Database>) {
|
|||
let user1 = db
|
||||
.create_user(
|
||||
"admin@example.com",
|
||||
None,
|
||||
true,
|
||||
NewUserParams {
|
||||
github_login: "admin".into(),
|
||||
|
@ -511,6 +521,7 @@ async fn test_project_count(db: &Arc<Database>) {
|
|||
let user2 = db
|
||||
.create_user(
|
||||
"user@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user".into(),
|
||||
|
@ -588,6 +599,7 @@ async fn test_fuzzy_search_users(cx: &mut gpui::TestAppContext) {
|
|||
{
|
||||
db.create_user(
|
||||
&format!("{github_login}@example.com"),
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: github_login.into(),
|
||||
|
|
|
@ -15,6 +15,7 @@ async fn test_get_user_flags(db: &Arc<Database>) {
|
|||
let user_1 = db
|
||||
.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".to_string(),
|
||||
|
@ -28,6 +29,7 @@ async fn test_get_user_flags(db: &Arc<Database>) {
|
|||
let user_2 = db
|
||||
.create_user(
|
||||
"user2@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user2".to_string(),
|
||||
|
|
|
@ -16,6 +16,7 @@ async fn test_accepted_tos(db: &Arc<Database>) {
|
|||
let user_id = db
|
||||
.create_user(
|
||||
"user1@example.com",
|
||||
None,
|
||||
false,
|
||||
NewUserParams {
|
||||
github_login: "user1".to_string(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue