Use different commit author for collab project clients (#24058)
Follow-up of https://github.com/zed-industries/zed/pull/23869 * Retrieves user + email for collab project clients and use these when such users commit Same as in https://github.com/zed-industries/zed/pull/23329, "is it the right user name and e-mail" and "how to override these" questions apply. * If this data is unavailable, forbid committing to the remote client * Forbid running related actions in git panel, if committing/writing is not permitted Release Notes: - N/A
This commit is contained in:
parent
93c7b54caa
commit
9a6b9e3124
8 changed files with 182 additions and 50 deletions
|
@ -67,8 +67,17 @@ impl PartialEq<RepositoryEntry> for RepositoryHandle {
|
|||
}
|
||||
|
||||
enum Message {
|
||||
StageAndCommit(GitRepo, Rope, Vec<RepoPath>),
|
||||
Commit(GitRepo, Rope),
|
||||
StageAndCommit {
|
||||
git_repo: GitRepo,
|
||||
paths: Vec<RepoPath>,
|
||||
message: Rope,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
},
|
||||
Commit {
|
||||
git_repo: GitRepo,
|
||||
message: Rope,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
},
|
||||
Stage(GitRepo, Vec<RepoPath>),
|
||||
Unstage(GitRepo, Vec<RepoPath>),
|
||||
}
|
||||
|
@ -95,11 +104,21 @@ impl GitState {
|
|||
.background_executor()
|
||||
.spawn(async move {
|
||||
match msg {
|
||||
Message::StageAndCommit(repo, message, paths) => {
|
||||
match repo {
|
||||
Message::StageAndCommit {
|
||||
git_repo,
|
||||
message,
|
||||
name_and_email,
|
||||
paths,
|
||||
} => {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => {
|
||||
repo.stage_paths(&paths)?;
|
||||
repo.commit(&message.to_string())?;
|
||||
repo.commit(
|
||||
&message.to_string(),
|
||||
name_and_email.as_ref().map(|(name, email)| {
|
||||
(name.as_ref(), email.as_ref())
|
||||
}),
|
||||
)?;
|
||||
}
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
|
@ -119,12 +138,15 @@ impl GitState {
|
|||
})
|
||||
.await
|
||||
.context("sending stage request")?;
|
||||
let (name, email) = name_and_email.unzip();
|
||||
client
|
||||
.request(proto::Commit {
|
||||
project_id: project_id.0,
|
||||
worktree_id: worktree_id.to_proto(),
|
||||
work_directory_id: work_directory_id.to_proto(),
|
||||
message: message.to_string(),
|
||||
name: name.map(String::from),
|
||||
email: email.map(String::from),
|
||||
})
|
||||
.await
|
||||
.context("sending commit request")?;
|
||||
|
@ -183,15 +205,25 @@ impl GitState {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
Message::Commit(repo, message) => {
|
||||
match repo {
|
||||
GitRepo::Local(repo) => repo.commit(&message.to_string())?,
|
||||
Message::Commit {
|
||||
git_repo,
|
||||
message,
|
||||
name_and_email,
|
||||
} => {
|
||||
match git_repo {
|
||||
GitRepo::Local(repo) => repo.commit(
|
||||
&message.to_string(),
|
||||
name_and_email
|
||||
.as_ref()
|
||||
.map(|(name, email)| (name.as_ref(), email.as_ref())),
|
||||
)?,
|
||||
GitRepo::Remote {
|
||||
project_id,
|
||||
client,
|
||||
worktree_id,
|
||||
work_directory_id,
|
||||
} => {
|
||||
let (name, email) = name_and_email.unzip();
|
||||
client
|
||||
.request(proto::Commit {
|
||||
project_id: project_id.0,
|
||||
|
@ -200,6 +232,8 @@ impl GitState {
|
|||
// TODO implement collaborative commit message buffer instead and use it
|
||||
// If it works, remove `commit_with_message` method.
|
||||
message: message.to_string(),
|
||||
name: name.map(String::from),
|
||||
email: email.map(String::from),
|
||||
})
|
||||
.await
|
||||
.context("sending commit request")?;
|
||||
|
@ -453,14 +487,24 @@ impl RepositoryHandle {
|
|||
&& (commit_all || self.have_staged_changes());
|
||||
}
|
||||
|
||||
pub fn commit(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) {
|
||||
pub fn commit(
|
||||
&self,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
mut err_sender: mpsc::Sender<anyhow::Error>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let Some(git_repo) = self.git_repo.clone() else {
|
||||
return;
|
||||
};
|
||||
let message = self.commit_message.read(cx).as_rope().clone();
|
||||
let result = self
|
||||
.update_sender
|
||||
.unbounded_send((Message::Commit(git_repo, message), err_sender.clone()));
|
||||
let result = self.update_sender.unbounded_send((
|
||||
Message::Commit {
|
||||
git_repo,
|
||||
message,
|
||||
name_and_email,
|
||||
},
|
||||
err_sender.clone(),
|
||||
));
|
||||
if result.is_err() {
|
||||
cx.spawn(|_| async move {
|
||||
err_sender
|
||||
|
@ -479,19 +523,30 @@ impl RepositoryHandle {
|
|||
pub fn commit_with_message(
|
||||
&self,
|
||||
message: String,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
err_sender: mpsc::Sender<anyhow::Error>,
|
||||
) -> anyhow::Result<()> {
|
||||
let Some(git_repo) = self.git_repo.clone() else {
|
||||
return Ok(());
|
||||
};
|
||||
let result = self
|
||||
.update_sender
|
||||
.unbounded_send((Message::Commit(git_repo, message.into()), err_sender));
|
||||
let result = self.update_sender.unbounded_send((
|
||||
Message::Commit {
|
||||
git_repo,
|
||||
message: message.into(),
|
||||
name_and_email,
|
||||
},
|
||||
err_sender,
|
||||
));
|
||||
anyhow::ensure!(result.is_ok(), "Failed to submit commit operation");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn commit_all(&self, mut err_sender: mpsc::Sender<anyhow::Error>, cx: &mut App) {
|
||||
pub fn commit_all(
|
||||
&self,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
mut err_sender: mpsc::Sender<anyhow::Error>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let Some(git_repo) = self.git_repo.clone() else {
|
||||
return;
|
||||
};
|
||||
|
@ -500,10 +555,15 @@ impl RepositoryHandle {
|
|||
.status()
|
||||
.filter(|entry| !entry.status.is_staged().unwrap_or(false))
|
||||
.map(|entry| entry.repo_path.clone())
|
||||
.collect::<Vec<_>>();
|
||||
.collect();
|
||||
let message = self.commit_message.read(cx).as_rope().clone();
|
||||
let result = self.update_sender.unbounded_send((
|
||||
Message::StageAndCommit(git_repo, message, to_stage),
|
||||
Message::StageAndCommit {
|
||||
git_repo,
|
||||
paths: to_stage,
|
||||
message,
|
||||
name_and_email,
|
||||
},
|
||||
err_sender.clone(),
|
||||
));
|
||||
if result.is_err() {
|
||||
|
|
|
@ -4073,9 +4073,11 @@ impl Project {
|
|||
})??;
|
||||
|
||||
let commit_message = envelope.payload.message;
|
||||
let name = envelope.payload.name.map(SharedString::from);
|
||||
let email = envelope.payload.email.map(SharedString::from);
|
||||
let (err_sender, mut err_receiver) = mpsc::channel(1);
|
||||
repository_handle
|
||||
.commit_with_message(commit_message, err_sender)
|
||||
.commit_with_message(commit_message, name.zip(email), err_sender)
|
||||
.context("unstaging entries")?;
|
||||
if let Some(error) = err_receiver.next().await {
|
||||
Err(error.context("error during unstaging"))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue