From ce3bd1521cad7dd9c2d6c6961d76ebc1e4ca0bd2 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Wed, 11 Oct 2023 15:09:04 +0200 Subject: [PATCH] use force push when needed --- .../src/project_repository/repository.rs | 9 +++++++- .../tauri/src/virtual_branches/commands.rs | 3 ++- .../tauri/src/virtual_branches/controller.rs | 16 +++++++++----- packages/tauri/src/virtual_branches/tests.rs | 21 ++++++++++++++++++- .../tauri/src/virtual_branches/virtual.rs | 3 ++- .../ui/src/lib/vbranches/branchController.ts | 4 ++-- .../routes/repo/[projectId]/BranchLane.svelte | 4 +++- 7 files changed, 48 insertions(+), 12 deletions(-) diff --git a/packages/tauri/src/project_repository/repository.rs b/packages/tauri/src/project_repository/repository.rs index 00a423a55..ad56efb9f 100644 --- a/packages/tauri/src/project_repository/repository.rs +++ b/packages/tauri/src/project_repository/repository.rs @@ -236,16 +236,23 @@ impl Repository { &self, head: &git::Oid, branch: &git::RemoteBranchName, + with_force: bool, key: &keys::Key, ) -> Result<(), RemoteError> { let mut remote = self.get_remote(branch.remote())?; + let refspec = if with_force { + format!("+{}:refs/heads/{}", head, branch.branch()) + } else { + format!("{}:refs/heads/{}", head, branch.branch()) + }; + for credential_callback in git::credentials::for_key(key) { let mut remote_callbacks = git2::RemoteCallbacks::new(); remote_callbacks.credentials(credential_callback); match remote.push( - &[&format!("{}:refs/heads/{}", head, branch.branch())], + &[refspec.as_str()], Some(&mut git2::PushOptions::new().remote_callbacks(remote_callbacks)), ) { Ok(()) => { diff --git a/packages/tauri/src/virtual_branches/commands.rs b/packages/tauri/src/virtual_branches/commands.rs index 054658ed2..312bc1005 100644 --- a/packages/tauri/src/virtual_branches/commands.rs +++ b/packages/tauri/src/virtual_branches/commands.rs @@ -220,10 +220,11 @@ pub async fn push_virtual_branch( handle: AppHandle, project_id: &str, branch_id: &str, + with_force: bool, ) -> Result<(), Error> { handle .state::() - .push_virtual_branch(project_id, branch_id) + .push_virtual_branch(project_id, branch_id, with_force) .await .map_err(Into::into) } diff --git a/packages/tauri/src/virtual_branches/controller.rs b/packages/tauri/src/virtual_branches/controller.rs index 583a88541..9db337d4c 100644 --- a/packages/tauri/src/virtual_branches/controller.rs +++ b/packages/tauri/src/virtual_branches/controller.rs @@ -431,6 +431,7 @@ impl Controller { &self, project_id: &str, branch_id: &str, + with_force: bool, ) -> Result<(), Error> { self.with_lock(project_id, || { self.with_verify_branch(project_id, |gb_repository, project_repository, _| { @@ -451,12 +452,17 @@ impl Controller { } }; - super::push(project_repository, gb_repository, branch_id, &private_key).map_err( - |e| match e { - super::PushError::Remote(error) => Error::ProjectRemote(error), - other => Error::Other(anyhow::Error::from(other)), - }, + super::push( + project_repository, + gb_repository, + branch_id, + with_force, + &private_key, ) + .map_err(|e| match e { + super::PushError::Remote(error) => Error::ProjectRemote(error), + other => Error::Other(anyhow::Error::from(other)), + }) }) }) .await diff --git a/packages/tauri/src/virtual_branches/tests.rs b/packages/tauri/src/virtual_branches/tests.rs index 7a65989c9..453d40a14 100644 --- a/packages/tauri/src/virtual_branches/tests.rs +++ b/packages/tauri/src/virtual_branches/tests.rs @@ -4090,7 +4090,7 @@ fn test_reset_to_target() { } #[test] -fn test_requires_force() { +fn test_force_push() { let suite = Suite::default(); let Case { project_repository, @@ -4132,6 +4132,7 @@ fn test_requires_force() { &project_repository, &gb_repository, &branch_id, + false, &keys::Key::from(suite.keys.get_or_create().unwrap()), ) .unwrap(); @@ -4149,4 +4150,22 @@ fn test_requires_force() { let statuses = list_virtual_branches(&gb_repository, &project_repository).unwrap(); assert!(statuses[0].requires_force); + + assert!(push( + &project_repository, + &gb_repository, + &branch_id, + false, + &keys::Key::from(suite.keys.get_or_create().unwrap()), + ) + .is_err()); + + assert!(push( + &project_repository, + &gb_repository, + &branch_id, + true, + &keys::Key::from(suite.keys.get_or_create().unwrap()), + ) + .is_ok()); } diff --git a/packages/tauri/src/virtual_branches/virtual.rs b/packages/tauri/src/virtual_branches/virtual.rs index 737aa3f43..9968f3c1e 100644 --- a/packages/tauri/src/virtual_branches/virtual.rs +++ b/packages/tauri/src/virtual_branches/virtual.rs @@ -2004,6 +2004,7 @@ pub fn push( project_repository: &project_repository::Repository, gb_repository: &gb_repository::Repository, branch_id: &str, + with_force: bool, key: &Key, ) -> Result<(), PushError> { let current_session = gb_repository @@ -2048,7 +2049,7 @@ pub fn push( ))) }; - project_repository.push(&vbranch.head, &remote_branch, key)?; + project_repository.push(&vbranch.head, &remote_branch, with_force, key)?; vbranch.upstream = Some(remote_branch.clone()); vbranch.upstream_head = Some(vbranch.head); diff --git a/packages/ui/src/lib/vbranches/branchController.ts b/packages/ui/src/lib/vbranches/branchController.ts index b3458f72e..ec57efb55 100644 --- a/packages/ui/src/lib/vbranches/branchController.ts +++ b/packages/ui/src/lib/vbranches/branchController.ts @@ -154,9 +154,9 @@ export class BranchController { await this.virtualBranchStore.reload(); } - async pushBranch(branchId: string) { + async pushBranch(params: { branchId: string; withForce: boolean }) { try { - await invoke('push_virtual_branch', { projectId: this.projectId, branchId }); + await invoke('push_virtual_branch', { projectId: this.projectId, ...params }); await this.virtualBranchStore.reload(); } catch (err: any) { if (err.code === 'errors.git.authentication') { diff --git a/packages/ui/src/routes/repo/[projectId]/BranchLane.svelte b/packages/ui/src/routes/repo/[projectId]/BranchLane.svelte index 264b754e0..8d531fb22 100644 --- a/packages/ui/src/routes/repo/[projectId]/BranchLane.svelte +++ b/packages/ui/src/routes/repo/[projectId]/BranchLane.svelte @@ -86,7 +86,9 @@ function push() { if (localCommits[0]?.id) { isPushing = true; - branchController.pushBranch(branch.id).finally(() => (isPushing = false)); + branchController + .pushBranch({ branchId: branch.id, withForce: branch.requiresForce }) + .finally(() => (isPushing = false)); } }