From b7ae52d124a104da2e7fb93d9369de0cec55fbae Mon Sep 17 00:00:00 2001 From: Sathiyaraman M Date: Fri, 24 Oct 2025 20:30:44 +0530 Subject: [PATCH] Support git::PullRebase action --- crates/fs/src/fake_git_repo.rs | 1 + crates/git/src/git.rs | 2 + crates/git/src/repository.rs | 3 ++ crates/git_ui/src/git_panel.rs | 3 +- crates/git_ui/src/git_ui.rs | 10 +++- crates/project/src/git_store.rs | 91 ++++++++++++++++++--------------- 6 files changed, 66 insertions(+), 44 deletions(-) diff --git a/crates/fs/src/fake_git_repo.rs b/crates/fs/src/fake_git_repo.rs index 8e9f8501dbcd4858f709dd5bd08f7f4d65aab986..1dca4f6552286d1488854b386e2e99dde9b1f3ff 100644 --- a/crates/fs/src/fake_git_repo.rs +++ b/crates/fs/src/fake_git_repo.rs @@ -530,6 +530,7 @@ impl GitRepository for FakeGitRepository { &self, _branch: String, _remote: String, + _rebase: bool, _askpass: AskPassDelegate, _env: Arc>, _cx: AsyncApp, diff --git a/crates/git/src/git.rs b/crates/git/src/git.rs index 29fa50ddd2bc2a2ae32a60b1b95dd66ca503d9de..50a1e1234ba3caeff729d37b6fa3022336b54e96 100644 --- a/crates/git/src/git.rs +++ b/crates/git/src/git.rs @@ -72,6 +72,8 @@ actions!( ForcePush, /// Pulls changes from the remote repository. Pull, + /// Pulls changes from the remote repository with rebase. + PullRebase, /// Fetches changes from the remote repository. Fetch, /// Fetches changes from a specific remote. diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 06bc5ec4114af01ae4c90f12d676ad027d0c5cc0..221b03d41f1838aef8f4695dd844206ecffddb5d 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -480,6 +480,7 @@ pub trait GitRepository: Send + Sync { &self, branch_name: String, upstream_name: String, + rebase: bool, askpass: AskPassDelegate, env: Arc>, // This method takes an AsyncApp to ensure it's invoked on the main thread, @@ -1578,6 +1579,7 @@ impl GitRepository for RealGitRepository { &self, branch_name: String, remote_name: String, + rebase: bool, ask_pass: AskPassDelegate, env: Arc>, cx: AsyncApp, @@ -1592,6 +1594,7 @@ impl GitRepository for RealGitRepository { .envs(env.iter()) .current_dir(&working_directory?) .args(["pull"]) + .arg(if rebase { "--rebase" } else { "--no-rebase" }) .arg(remote_name) .arg(branch_name) .stdout(smol::process::Stdio::piped()) diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 9ff8602a18fd1a7eec5804deecee5c21921c6eee..6891a46ce2bc503187ffab2371bb7feceed01882 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -2211,7 +2211,7 @@ impl GitPanel { .detach(); } - pub(crate) fn pull(&mut self, window: &mut Window, cx: &mut Context) { + pub(crate) fn pull(&mut self, rebase: bool, window: &mut Window, cx: &mut Context) { if !self.can_push_and_pull(cx) { return; } @@ -2246,6 +2246,7 @@ impl GitPanel { repo.pull( branch.name().to_owned().into(), remote.name.clone(), + rebase, askpass, cx, ) diff --git a/crates/git_ui/src/git_ui.rs b/crates/git_ui/src/git_ui.rs index 919cdf154d438e8ee5b38422032aa150edc5dd34..cf5334e3fe7b575b9b5c7972851bebff993a21f1 100644 --- a/crates/git_ui/src/git_ui.rs +++ b/crates/git_ui/src/git_ui.rs @@ -124,7 +124,15 @@ pub fn init(cx: &mut App) { return; }; panel.update(cx, |panel, cx| { - panel.pull(window, cx); + panel.pull(false, window, cx); + }); + }); + workspace.register_action(|workspace, _: &git::PullRebase, window, cx| { + let Some(panel) = workspace.panel::(cx) else { + return; + }; + panel.update(cx, |panel, cx| { + panel.pull(true, window, cx); }); }); } diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index 736c96f34e171c4fde83c2db032484456144ae5a..6b37a535724dae9c9f5a26514528fcd44d3d3ae9 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -1716,10 +1716,11 @@ impl GitStore { let branch_name = envelope.payload.branch_name.into(); let remote_name = envelope.payload.remote_name.into(); + let rebase = envelope.payload.rebase.into(); let remote_message = repository_handle .update(&mut cx, |repository_handle, cx| { - repository_handle.pull(branch_name, remote_name, askpass, cx) + repository_handle.pull(branch_name, remote_name, rebase, askpass, cx) })? .await??; @@ -4226,6 +4227,7 @@ impl Repository { &mut self, branch: SharedString, remote: SharedString, + rebase: bool, askpass: AskPassDelegate, _cx: &mut App, ) -> oneshot::Receiver> { @@ -4233,50 +4235,55 @@ impl Repository { let askpass_id = util::post_inc(&mut self.latest_askpass_id); let id = self.id; - self.send_job( - Some(format!("git pull {} {}", remote, branch).into()), - move |git_repo, cx| async move { - match git_repo { - RepositoryState::Local { - backend, - environment, - .. - } => { - backend - .pull( - branch.to_string(), - remote.to_string(), - askpass, - environment.clone(), - cx, - ) - .await - } - RepositoryState::Remote { project_id, client } => { - askpass_delegates.lock().insert(askpass_id, askpass); - let _defer = util::defer(|| { - let askpass_delegate = askpass_delegates.lock().remove(&askpass_id); - debug_assert!(askpass_delegate.is_some()); - }); - let response = client - .request(proto::Pull { - project_id: project_id.0, - repository_id: id.to_proto(), - askpass_id, - branch_name: branch.to_string(), - remote_name: remote.to_string(), - }) - .await - .context("sending pull request")?; + let status = if rebase { + Some(format!("git pull --rebase {} {}", remote, branch).into()) + } else { + Some(format!("git pull {} {}", remote, branch).into()) + }; - Ok(RemoteCommandOutput { - stdout: response.stdout, - stderr: response.stderr, + self.send_job(status, move |git_repo, cx| async move { + match git_repo { + RepositoryState::Local { + backend, + environment, + .. + } => { + backend + .pull( + branch.to_string(), + remote.to_string(), + rebase, + askpass, + environment.clone(), + cx, + ) + .await + } + RepositoryState::Remote { project_id, client } => { + askpass_delegates.lock().insert(askpass_id, askpass); + let _defer = util::defer(|| { + let askpass_delegate = askpass_delegates.lock().remove(&askpass_id); + debug_assert!(askpass_delegate.is_some()); + }); + let response = client + .request(proto::Pull { + project_id: project_id.0, + repository_id: id.to_proto(), + askpass_id, + rebase, + branch_name: branch.to_string(), + remote_name: remote.to_string(), }) - } + .await + .context("sending pull request")?; + + Ok(RemoteCommandOutput { + stdout: response.stdout, + stderr: response.stderr, + }) } - }, - ) + } + }) } fn spawn_set_index_text_job(