git: Handle git pre-commit hooks separately (#43285)
We now run git pre-commit hooks before we commit. This ensures we don't run into timeout issues with askpass delegate and report invalid error to the user. Closes #43157 Release Notes: - Fixed long running pre-commit hooks causing committing from Zed to fail. Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
co-authored by
Cole Miller
parent
279b76d440
commit
d07193cdf2
@@ -25,7 +25,7 @@ use futures::{
|
||||
stream::FuturesOrdered,
|
||||
};
|
||||
use git::{
|
||||
BuildPermalinkParams, GitHostingProviderRegistry, Oid,
|
||||
BuildPermalinkParams, GitHostingProviderRegistry, Oid, RunHook,
|
||||
blame::Blame,
|
||||
parse_git_remote_url,
|
||||
repository::{
|
||||
@@ -433,6 +433,7 @@ impl GitStore {
|
||||
client.add_entity_request_handler(Self::handle_stash_apply);
|
||||
client.add_entity_request_handler(Self::handle_stash_drop);
|
||||
client.add_entity_request_handler(Self::handle_commit);
|
||||
client.add_entity_request_handler(Self::handle_run_hook);
|
||||
client.add_entity_request_handler(Self::handle_reset);
|
||||
client.add_entity_request_handler(Self::handle_show);
|
||||
client.add_entity_request_handler(Self::handle_load_commit_diff);
|
||||
@@ -1982,6 +1983,22 @@ impl GitStore {
|
||||
Ok(proto::Ack {})
|
||||
}
|
||||
|
||||
async fn handle_run_hook(
|
||||
this: Entity<Self>,
|
||||
envelope: TypedEnvelope<proto::RunGitHook>,
|
||||
mut cx: AsyncApp,
|
||||
) -> Result<proto::Ack> {
|
||||
let repository_id = RepositoryId::from_proto(envelope.payload.repository_id);
|
||||
let repository_handle = Self::repository_for_request(&this, repository_id, &mut cx)?;
|
||||
let hook = RunHook::from_proto(envelope.payload.hook).context("invalid hook")?;
|
||||
repository_handle
|
||||
.update(&mut cx, |repository_handle, cx| {
|
||||
repository_handle.run_hook(hook, cx)
|
||||
})?
|
||||
.await??;
|
||||
Ok(proto::Ack {})
|
||||
}
|
||||
|
||||
async fn handle_commit(
|
||||
this: Entity<Self>,
|
||||
envelope: TypedEnvelope<proto::Commit>,
|
||||
@@ -4262,19 +4279,49 @@ impl Repository {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn run_hook(&mut self, hook: RunHook, _cx: &mut App) -> oneshot::Receiver<Result<()>> {
|
||||
let id = self.id;
|
||||
self.send_job(
|
||||
Some(format!("git hook {}", hook.as_str()).into()),
|
||||
move |git_repo, _cx| async move {
|
||||
match git_repo {
|
||||
RepositoryState::Local {
|
||||
backend,
|
||||
environment,
|
||||
} => backend.run_hook(hook, environment.clone()).await,
|
||||
RepositoryState::Remote { project_id, client } => {
|
||||
client
|
||||
.request(proto::RunGitHook {
|
||||
project_id: project_id.0,
|
||||
repository_id: id.to_proto(),
|
||||
hook: hook.to_proto(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn commit(
|
||||
&mut self,
|
||||
message: SharedString,
|
||||
name_and_email: Option<(SharedString, SharedString)>,
|
||||
options: CommitOptions,
|
||||
askpass: AskPassDelegate,
|
||||
_cx: &mut App,
|
||||
cx: &mut App,
|
||||
) -> oneshot::Receiver<Result<()>> {
|
||||
let id = self.id;
|
||||
let askpass_delegates = self.askpass_delegates.clone();
|
||||
let askpass_id = util::post_inc(&mut self.latest_askpass_id);
|
||||
|
||||
let rx = self.run_hook(RunHook::PreCommit, cx);
|
||||
|
||||
self.send_job(Some("git commit".into()), move |git_repo, _cx| async move {
|
||||
rx.await??;
|
||||
|
||||
match git_repo {
|
||||
RepositoryState::Local {
|
||||
backend,
|
||||
|
||||
Reference in New Issue
Block a user