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,
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(()) => {

View File

@ -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::<Controller>()
.push_virtual_branch(project_id, branch_id)
.push_virtual_branch(project_id, branch_id, with_force)
.await
.map_err(Into::into)
}

View File

@ -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

View File

@ -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());
}

View File

@ -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);

View File

@ -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<void>('push_virtual_branch', { projectId: this.projectId, branchId });
await invoke<void>('push_virtual_branch', { projectId: this.projectId, ...params });
await this.virtualBranchStore.reload();
} catch (err: any) {
if (err.code === 'errors.git.authentication') {

View File

@ -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));
}
}