use force push when needed

This commit is contained in:
Nikita Galaiko 2023-10-11 15:09:04 +02:00 committed by GitButler
parent b834a6ef01
commit ce3bd1521c
7 changed files with 48 additions and 12 deletions

View File

@ -236,16 +236,23 @@ impl Repository {
&self, &self,
head: &git::Oid, head: &git::Oid,
branch: &git::RemoteBranchName, branch: &git::RemoteBranchName,
with_force: bool,
key: &keys::Key, key: &keys::Key,
) -> Result<(), RemoteError> { ) -> Result<(), RemoteError> {
let mut remote = self.get_remote(branch.remote())?; 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) { for credential_callback in git::credentials::for_key(key) {
let mut remote_callbacks = git2::RemoteCallbacks::new(); let mut remote_callbacks = git2::RemoteCallbacks::new();
remote_callbacks.credentials(credential_callback); remote_callbacks.credentials(credential_callback);
match remote.push( match remote.push(
&[&format!("{}:refs/heads/{}", head, branch.branch())], &[refspec.as_str()],
Some(&mut git2::PushOptions::new().remote_callbacks(remote_callbacks)), Some(&mut git2::PushOptions::new().remote_callbacks(remote_callbacks)),
) { ) {
Ok(()) => { Ok(()) => {

View File

@ -220,10 +220,11 @@ pub async fn push_virtual_branch(
handle: AppHandle, handle: AppHandle,
project_id: &str, project_id: &str,
branch_id: &str, branch_id: &str,
with_force: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
handle handle
.state::<Controller>() .state::<Controller>()
.push_virtual_branch(project_id, branch_id) .push_virtual_branch(project_id, branch_id, with_force)
.await .await
.map_err(Into::into) .map_err(Into::into)
} }

View File

@ -431,6 +431,7 @@ impl Controller {
&self, &self,
project_id: &str, project_id: &str,
branch_id: &str, branch_id: &str,
with_force: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.with_lock(project_id, || { self.with_lock(project_id, || {
self.with_verify_branch(project_id, |gb_repository, project_repository, _| { 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( super::push(
|e| match e { project_repository,
super::PushError::Remote(error) => Error::ProjectRemote(error), gb_repository,
other => Error::Other(anyhow::Error::from(other)), 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 .await

View File

@ -4090,7 +4090,7 @@ fn test_reset_to_target() {
} }
#[test] #[test]
fn test_requires_force() { fn test_force_push() {
let suite = Suite::default(); let suite = Suite::default();
let Case { let Case {
project_repository, project_repository,
@ -4132,6 +4132,7 @@ fn test_requires_force() {
&project_repository, &project_repository,
&gb_repository, &gb_repository,
&branch_id, &branch_id,
false,
&keys::Key::from(suite.keys.get_or_create().unwrap()), &keys::Key::from(suite.keys.get_or_create().unwrap()),
) )
.unwrap(); .unwrap();
@ -4149,4 +4150,22 @@ fn test_requires_force() {
let statuses = list_virtual_branches(&gb_repository, &project_repository).unwrap(); let statuses = list_virtual_branches(&gb_repository, &project_repository).unwrap();
assert!(statuses[0].requires_force); 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());
} }

View File

@ -2004,6 +2004,7 @@ pub fn push(
project_repository: &project_repository::Repository, project_repository: &project_repository::Repository,
gb_repository: &gb_repository::Repository, gb_repository: &gb_repository::Repository,
branch_id: &str, branch_id: &str,
with_force: bool,
key: &Key, key: &Key,
) -> Result<(), PushError> { ) -> Result<(), PushError> {
let current_session = gb_repository 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 = Some(remote_branch.clone());
vbranch.upstream_head = Some(vbranch.head); vbranch.upstream_head = Some(vbranch.head);

View File

@ -154,9 +154,9 @@ export class BranchController {
await this.virtualBranchStore.reload(); await this.virtualBranchStore.reload();
} }
async pushBranch(branchId: string) { async pushBranch(params: { branchId: string; withForce: boolean }) {
try { try {
await invoke<void>('push_virtual_branch', { projectId: this.projectId, branchId }); await invoke<void>('push_virtual_branch', { projectId: this.projectId, ...params });
await this.virtualBranchStore.reload(); await this.virtualBranchStore.reload();
} catch (err: any) { } catch (err: any) {
if (err.code === 'errors.git.authentication') { if (err.code === 'errors.git.authentication') {

View File

@ -86,7 +86,9 @@
function push() { function push() {
if (localCommits[0]?.id) { if (localCommits[0]?.id) {
isPushing = true; isPushing = true;
branchController.pushBranch(branch.id).finally(() => (isPushing = false)); branchController
.pushBranch({ branchId: branch.id, withForce: branch.requiresForce })
.finally(() => (isPushing = false));
} }
} }