Merge pull request #4908 from gitbutlerapp/Unapplying-rename

Rename unapplying
This commit is contained in:
Caleb Owens 2024-09-13 17:04:07 +02:00 committed by GitHub
commit 56fb839eee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 66 additions and 62 deletions

View File

@ -59,8 +59,8 @@
aiConfigurationValid = await aiService.validateConfiguration(user?.access_token); aiConfigurationValid = await aiService.validateConfiguration(user?.access_token);
} }
function unapplyBranch() { function saveAndUnapply() {
branchController.convertToRealBranch(branch.id); branchController.saveAndUnapply(branch.id);
} }
let normalizedBranchName: string; let normalizedBranchName: string;
@ -93,20 +93,20 @@
<ContextMenuItem <ContextMenuItem
label="Unapply" label="Unapply"
on:click={() => { on:click={() => {
unapplyBranch(); saveAndUnapply();
contextMenuEl?.close(); contextMenuEl?.close();
}} }}
/> />
<ContextMenuItem <ContextMenuItem
label="Delete" label="Drop changes and unapply"
on:click={async () => { on:click={async () => {
if ( if (
branch.name.toLowerCase().includes('virtual branch') && branch.name.toLowerCase().includes('virtual branch') &&
commits.length === 0 && commits.length === 0 &&
branch.files?.length === 0 branch.files?.length === 0
) { ) {
await branchController.deleteBranch(branch.id); await branchController.unapplyWithoutSaving(branch.id);
} else { } else {
deleteBranchModal.show(branch); deleteBranchModal.show(branch);
} }
@ -185,7 +185,7 @@
onSubmit={async (close) => { onSubmit={async (close) => {
try { try {
isDeleting = true; isDeleting = true;
await branchController.deleteBranch(branch.id); await branchController.unapplyWithoutSaving(branch.id);
close(); close();
} finally { } finally {
isDeleting = false; isDeleting = false;

View File

@ -238,9 +238,9 @@ export class BranchController {
} }
} }
async convertToRealBranch(branchId: string) { async saveAndUnapply(branchId: string) {
try { try {
await invoke<void>('convert_to_real_branch', { await invoke<void>('save_and_unapply_virtual_branch', {
projectId: this.projectId, projectId: this.projectId,
branch: branchId branch: branchId
}); });
@ -303,13 +303,16 @@ export class BranchController {
} }
} }
async deleteBranch(branchId: string) { async unapplyWithoutSaving(branchId: string) {
try { try {
// TODO: make this optimistic again. // TODO: make this optimistic again.
await invoke<void>('delete_virtual_branch', { projectId: this.projectId, branchId }); await invoke<void>('unapply_without_saving_virtual_branch', {
toasts.success('Branch deleted successfully'); projectId: this.projectId,
branchId
});
toasts.success('Branch unapplied successfully');
} catch (err) { } catch (err) {
showError('Failed to delete branch', err); showError('Failed to unapply branch', err);
} finally { } finally {
this.remoteBranchService.refresh(); this.remoteBranchService.refresh();
} }

View File

@ -225,7 +225,7 @@ pub fn update_branch_order(
Ok(()) Ok(())
} }
pub fn delete_virtual_branch(project: &Project, branch_id: BranchId) -> Result<()> { pub fn unapply_without_saving_virtual_branch(project: &Project, branch_id: BranchId) -> Result<()> {
let ctx = open_with_verify(project)?; let ctx = open_with_verify(project)?;
assure_open_workspace_mode(&ctx) assure_open_workspace_mode(&ctx)
.context("Deleting a branch order requires open workspace mode")?; .context("Deleting a branch order requires open workspace mode")?;
@ -233,7 +233,7 @@ pub fn delete_virtual_branch(project: &Project, branch_id: BranchId) -> Result<(
let mut guard = project.exclusive_worktree_access(); let mut guard = project.exclusive_worktree_access();
let default_target = ctx.project().virtual_branches().get_default_target()?; let default_target = ctx.project().virtual_branches().get_default_target()?;
let target_commit = ctx.repository().find_commit(default_target.sha)?; let target_commit = ctx.repository().find_commit(default_target.sha)?;
branch_manager.delete_branch(branch_id, guard.write_permission(), &target_commit) branch_manager.unapply_without_saving(branch_id, guard.write_permission(), &target_commit)
} }
pub fn unapply_ownership(project: &Project, ownership: &BranchOwnershipClaims) -> Result<()> { pub fn unapply_ownership(project: &Project, ownership: &BranchOwnershipClaims) -> Result<()> {
@ -388,14 +388,17 @@ pub fn reset_virtual_branch(
vbranch::reset_branch(&ctx, branch_id, target_commit_oid).map_err(Into::into) vbranch::reset_branch(&ctx, branch_id, target_commit_oid).map_err(Into::into)
} }
pub fn convert_to_real_branch(project: &Project, branch_id: BranchId) -> Result<ReferenceName> { pub fn save_and_unapply_virutal_branch(
project: &Project,
branch_id: BranchId,
) -> Result<ReferenceName> {
let ctx = open_with_verify(project)?; let ctx = open_with_verify(project)?;
assure_open_workspace_mode(&ctx) assure_open_workspace_mode(&ctx)
.context("Converting branch to a real branch requires open workspace mode")?; .context("Converting branch to a real branch requires open workspace mode")?;
let mut guard = project.exclusive_worktree_access(); let mut guard = project.exclusive_worktree_access();
let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission()); let snapshot_tree = ctx.project().prepare_snapshot(guard.read_permission());
let branch_manager = ctx.branch_manager(); let branch_manager = ctx.branch_manager();
let result = branch_manager.convert_to_real_branch(branch_id, guard.write_permission()); let result = branch_manager.save_and_unapply(branch_id, guard.write_permission());
let _ = snapshot_tree.and_then(|snapshot_tree| { let _ = snapshot_tree.and_then(|snapshot_tree| {
ctx.project().snapshot_branch_unapplied( ctx.project().snapshot_branch_unapplied(

View File

@ -409,8 +409,7 @@ pub(crate) fn update_base_branch(
if branch_tree_merge_index.has_conflicts() { if branch_tree_merge_index.has_conflicts() {
// branch tree conflicts with new target, unapply branch for now. we'll handle it later, when user applies it back. // branch tree conflicts with new target, unapply branch for now. we'll handle it later, when user applies it back.
let branch_manager = ctx.branch_manager(); let branch_manager = ctx.branch_manager();
let unapplied_real_branch = let unapplied_real_branch = branch_manager.save_and_unapply(branch.id, perm)?;
branch_manager.convert_to_real_branch(branch.id, perm)?;
unapplied_branch_names.push(unapplied_real_branch); unapplied_branch_names.push(unapplied_real_branch);
@ -443,8 +442,7 @@ pub(crate) fn update_base_branch(
// branch commits conflict with new target, make sure the branch is // branch commits conflict with new target, make sure the branch is
// unapplied. conflicts witll be dealt with when applying it back. // unapplied. conflicts witll be dealt with when applying it back.
let branch_manager = ctx.branch_manager(); let branch_manager = ctx.branch_manager();
let unapplied_real_branch = let unapplied_real_branch = branch_manager.save_and_unapply(branch.id, perm)?;
branch_manager.convert_to_real_branch(branch.id, perm)?;
unapplied_branch_names.push(unapplied_real_branch); unapplied_branch_names.push(unapplied_real_branch);
return Ok(None); return Ok(None);

View File

@ -334,7 +334,7 @@ impl BranchManager<'_> {
.iter() .iter()
.filter(|branch| branch.id != branch_id) .filter(|branch| branch.id != branch_id)
{ {
self.convert_to_real_branch(branch.id, perm)?; self.save_and_unapply(branch.id, perm)?;
} }
// apply the branch // apply the branch

View File

@ -22,7 +22,7 @@ use crate::{
impl BranchManager<'_> { impl BranchManager<'_> {
// to unapply a branch, we need to write the current tree out, then remove those file changes from the wd // to unapply a branch, we need to write the current tree out, then remove those file changes from the wd
#[instrument(level = tracing::Level::DEBUG, skip(self, perm), err(Debug))] #[instrument(level = tracing::Level::DEBUG, skip(self, perm), err(Debug))]
pub fn convert_to_real_branch( pub fn save_and_unapply(
&self, &self,
branch_id: BranchId, branch_id: BranchId,
perm: &mut WorktreeWritePermission, perm: &mut WorktreeWritePermission,
@ -38,7 +38,7 @@ impl BranchManager<'_> {
// Convert the vbranch to a real branch // Convert the vbranch to a real branch
let real_branch = self.build_real_branch(&mut target_branch)?; let real_branch = self.build_real_branch(&mut target_branch)?;
self.delete_branch(branch_id, perm, &target_commit)?; self.unapply_without_saving(branch_id, perm, &target_commit)?;
vb_state.update_ordering()?; vb_state.update_ordering()?;
@ -52,7 +52,7 @@ impl BranchManager<'_> {
} }
#[instrument(level = tracing::Level::DEBUG, skip(self, perm), err(Debug))] #[instrument(level = tracing::Level::DEBUG, skip(self, perm), err(Debug))]
pub(crate) fn delete_branch( pub(crate) fn unapply_without_saving(
&self, &self,
branch_id: BranchId, branch_id: BranchId,
perm: &mut WorktreeWritePermission, perm: &mut WorktreeWritePermission,

View File

@ -2,16 +2,17 @@
mod actions; mod actions;
// This is our API // This is our API
pub use actions::{ pub use actions::{
amend, can_apply_remote_branch, convert_to_real_branch, create_change_reference, create_commit, amend, can_apply_remote_branch, create_change_reference, create_commit, create_virtual_branch,
create_virtual_branch, create_virtual_branch_from_branch, delete_local_branch, create_virtual_branch_from_branch, delete_local_branch, fetch_from_remotes,
delete_virtual_branch, fetch_from_remotes, get_base_branch_data, get_remote_branch_data, get_base_branch_data, get_remote_branch_data, get_uncommited_files,
get_uncommited_files, get_uncommited_files_reusable, insert_blank_commit, integrate_upstream, get_uncommited_files_reusable, insert_blank_commit, integrate_upstream,
integrate_upstream_commits, list_local_branches, list_remote_commit_files, integrate_upstream_commits, list_local_branches, list_remote_commit_files,
list_virtual_branches, list_virtual_branches_cached, move_commit, move_commit_file, list_virtual_branches, list_virtual_branches_cached, move_commit, move_commit_file,
push_change_reference, push_virtual_branch, reorder_commit, reset_files, reset_virtual_branch, push_change_reference, push_virtual_branch, reorder_commit, reset_files, reset_virtual_branch,
set_base_branch, set_target_push_remote, squash, unapply_ownership, undo_commit, save_and_unapply_virutal_branch, set_base_branch, set_target_push_remote, squash,
update_base_branch, update_branch_order, update_change_reference, update_commit_message, unapply_ownership, unapply_without_saving_virtual_branch, undo_commit, update_base_branch,
update_virtual_branch, upstream_integration_statuses, update_branch_order, update_change_reference, update_commit_message, update_virtual_branch,
upstream_integration_statuses,
}; };
mod r#virtual; mod r#virtual;

View File

@ -277,7 +277,7 @@ pub(crate) fn integrate_upstream(
command_context command_context
.branch_manager() .branch_manager()
.convert_to_real_branch(*branch_id, permission)?; .save_and_unapply(*branch_id, permission)?;
} }
let mut branches = virtual_branches_state.list_branches_in_workspace()?; let mut branches = virtual_branches_state.list_branches_in_workspace()?;

View File

@ -1099,8 +1099,7 @@ fn unapply_branch() -> Result<()> {
assert!(branch.active); assert!(branch.active);
let branch_manager = ctx.branch_manager(); let branch_manager = ctx.branch_manager();
let real_branch = let real_branch = branch_manager.save_and_unapply(branch1_id, guard.write_permission())?;
branch_manager.convert_to_real_branch(branch1_id, guard.write_permission())?;
let contents = std::fs::read(Path::new(&project.path).join(file_path))?; let contents = std::fs::read(Path::new(&project.path).join(file_path))?;
assert_eq!("line1\nline2\nline3\nline4\n", String::from_utf8(contents)?); assert_eq!("line1\nline2\nline3\nline4\n", String::from_utf8(contents)?);
@ -1183,15 +1182,13 @@ fn apply_unapply_added_deleted_files() -> Result<()> {
internal::list_virtual_branches(ctx, guard.write_permission()).unwrap(); internal::list_virtual_branches(ctx, guard.write_permission()).unwrap();
let branch_manager = ctx.branch_manager(); let branch_manager = ctx.branch_manager();
let real_branch_2 = let real_branch_2 = branch_manager.save_and_unapply(branch2_id, guard.write_permission())?;
branch_manager.convert_to_real_branch(branch2_id, guard.write_permission())?;
// check that file2 is back // check that file2 is back
let contents = std::fs::read(Path::new(&project.path).join(file_path2))?; let contents = std::fs::read(Path::new(&project.path).join(file_path2))?;
assert_eq!("file2\n", String::from_utf8(contents)?); assert_eq!("file2\n", String::from_utf8(contents)?);
let real_branch_3 = let real_branch_3 = branch_manager.save_and_unapply(branch3_id, guard.write_permission())?;
branch_manager.convert_to_real_branch(branch3_id, guard.write_permission())?;
// check that file3 is gone // check that file3 is gone
assert!(!Path::new(&project.path).join(file_path3).exists()); assert!(!Path::new(&project.path).join(file_path3).exists());
@ -1267,8 +1264,8 @@ fn detect_mergeable_branch() -> Result<()> {
// unapply both branches and create some conflicting ones // unapply both branches and create some conflicting ones
let branch_manager = ctx.branch_manager(); let branch_manager = ctx.branch_manager();
branch_manager.convert_to_real_branch(branch1_id, guard.write_permission())?; branch_manager.save_and_unapply(branch1_id, guard.write_permission())?;
branch_manager.convert_to_real_branch(branch2_id, guard.write_permission())?; branch_manager.save_and_unapply(branch2_id, guard.write_permission())?;
ctx.repository().set_head("refs/heads/master")?; ctx.repository().set_head("refs/heads/master")?;
ctx.repository() ctx.repository()

View File

@ -53,7 +53,7 @@ fn rebase_commit() {
let unapplied_branch = { let unapplied_branch = {
// unapply first vbranch // unapply first vbranch
let unapplied_branch = let unapplied_branch =
gitbutler_branch_actions::convert_to_real_branch(project, branch1_id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branch1_id).unwrap();
assert_eq!( assert_eq!(
fs::read_to_string(repository.path().join("another_file.txt")).unwrap(), fs::read_to_string(repository.path().join("another_file.txt")).unwrap(),
@ -163,7 +163,7 @@ fn rebase_work() {
let unapplied_branch = { let unapplied_branch = {
// unapply first vbranch // unapply first vbranch
let unapplied_branch = let unapplied_branch =
gitbutler_branch_actions::convert_to_real_branch(project, branch1_id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branch1_id).unwrap();
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0); assert_eq!(branches.len(), 0);

View File

@ -39,7 +39,8 @@ fn integration() {
let name = branch.upstream.unwrap().name; let name = branch.upstream.unwrap().name;
gitbutler_branch_actions::delete_virtual_branch(project, branch_id).unwrap(); gitbutler_branch_actions::unapply_without_saving_virtual_branch(project, branch_id)
.unwrap();
name name
}; };

View File

@ -57,10 +57,8 @@ impl Test {
mod amend; mod amend;
mod apply_virtual_branch; mod apply_virtual_branch;
mod convert_to_real_branch;
mod create_commit; mod create_commit;
mod create_virtual_branch_from_branch; mod create_virtual_branch_from_branch;
mod delete_virtual_branch;
mod init; mod init;
mod insert_blank_commit; mod insert_blank_commit;
mod list; mod list;
@ -71,10 +69,12 @@ mod oplog;
mod references; mod references;
mod reorder_commit; mod reorder_commit;
mod reset_virtual_branch; mod reset_virtual_branch;
mod save_and_unapply_virtual_branch;
mod selected_for_changes; mod selected_for_changes;
mod set_base_branch; mod set_base_branch;
mod squash; mod squash;
mod unapply_ownership; mod unapply_ownership;
mod unapply_without_saving_virtual_branch;
mod undo_commit; mod undo_commit;
mod update_base_branch; mod update_base_branch;
mod update_commit_message; mod update_commit_message;

View File

@ -19,7 +19,7 @@ fn unapply_with_data() {
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1); assert_eq!(branches.len(), 1);
gitbutler_branch_actions::convert_to_real_branch(project, branches[0].id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branches[0].id).unwrap();
assert!(!repository.path().join("file.txt").exists()); assert!(!repository.path().join("file.txt").exists());
@ -71,7 +71,7 @@ fn conflicting() {
); );
let unapplied_branch = let unapplied_branch =
gitbutler_branch_actions::convert_to_real_branch(project, branch.id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branch.id).unwrap();
Refname::from_str(&unapplied_branch).unwrap() Refname::from_str(&unapplied_branch).unwrap()
}; };
@ -118,7 +118,7 @@ fn conflicting() {
{ {
// Converting the branch to a real branch should put us back in an unconflicted state // Converting the branch to a real branch should put us back in an unconflicted state
gitbutler_branch_actions::convert_to_real_branch(project, branch_id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branch_id).unwrap();
assert_eq!( assert_eq!(
std::fs::read_to_string(repository.path().join("file.txt")).unwrap(), std::fs::read_to_string(repository.path().join("file.txt")).unwrap(),
@ -143,7 +143,7 @@ fn delete_if_empty() {
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 1); assert_eq!(branches.len(), 1);
gitbutler_branch_actions::convert_to_real_branch(project, branches[0].id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branches[0].id).unwrap();
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0); assert_eq!(branches.len(), 0);

View File

@ -37,7 +37,7 @@ fn unapplying_selected_branch_selects_anther() {
assert!(b.selected_for_changes); assert!(b.selected_for_changes);
assert!(!b2.selected_for_changes); assert!(!b2.selected_for_changes);
gitbutler_branch_actions::convert_to_real_branch(project, b_id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, b_id).unwrap();
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
@ -76,7 +76,7 @@ fn deleting_selected_branch_selects_anther() {
assert!(b.selected_for_changes); assert!(b.selected_for_changes);
assert!(!b2.selected_for_changes); assert!(!b2.selected_for_changes);
gitbutler_branch_actions::delete_virtual_branch(project, b_id).unwrap(); gitbutler_branch_actions::unapply_without_saving_virtual_branch(project, b_id).unwrap();
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
@ -252,7 +252,7 @@ fn unapply_virtual_branch_should_reset_selected_for_changes() {
.unwrap(); .unwrap();
assert!(!b2.selected_for_changes); assert!(!b2.selected_for_changes);
gitbutler_branch_actions::convert_to_real_branch(project, b1_id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, b1_id).unwrap();
assert!(gitbutler_branch_actions::list_virtual_branches(project) assert!(gitbutler_branch_actions::list_virtual_branches(project)
.unwrap() .unwrap()
@ -314,7 +314,7 @@ fn applying_first_branch() {
assert_eq!(branches.len(), 1); assert_eq!(branches.len(), 1);
let unapplied_branch = let unapplied_branch =
gitbutler_branch_actions::convert_to_real_branch(project, branches[0].id).unwrap(); gitbutler_branch_actions::save_and_unapply_virutal_branch(project, branches[0].id).unwrap();
let unapplied_branch = Refname::from_str(&unapplied_branch).unwrap(); let unapplied_branch = Refname::from_str(&unapplied_branch).unwrap();
gitbutler_branch_actions::create_virtual_branch_from_branch(project, &unapplied_branch, None) gitbutler_branch_actions::create_virtual_branch_from_branch(project, &unapplied_branch, None)
.unwrap(); .unwrap();

View File

@ -29,7 +29,8 @@ fn should_unapply_diff() {
); );
assert!(c.is_ok()); assert!(c.is_ok());
gitbutler_branch_actions::delete_virtual_branch(project, branches[0].id).unwrap(); gitbutler_branch_actions::unapply_without_saving_virtual_branch(project, branches[0].id)
.unwrap();
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0); assert_eq!(branches.len(), 0);
@ -74,7 +75,7 @@ fn should_remove_reference() {
) )
.unwrap(); .unwrap();
gitbutler_branch_actions::delete_virtual_branch(project, id).unwrap(); gitbutler_branch_actions::unapply_without_saving_virtual_branch(project, id).unwrap();
let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap(); let (branches, _) = gitbutler_branch_actions::list_virtual_branches(project).unwrap();
assert_eq!(branches.len(), 0); assert_eq!(branches.len(), 0);

View File

@ -54,7 +54,7 @@ pub fn status(project: Project) -> Result<()> {
pub fn unapply(project: Project, branch_name: String) -> Result<()> { pub fn unapply(project: Project, branch_name: String) -> Result<()> {
let branch = branch_by_name(&project, &branch_name)?; let branch = branch_by_name(&project, &branch_name)?;
debug_print(gitbutler_branch_actions::convert_to_real_branch( debug_print(gitbutler_branch_actions::save_and_unapply_virutal_branch(
&project, branch.id, &project, branch.id,
)?) )?)
} }

View File

@ -161,8 +161,8 @@ fn main() {
virtual_branches::commands::integrate_upstream_commits, virtual_branches::commands::integrate_upstream_commits,
virtual_branches::commands::update_virtual_branch, virtual_branches::commands::update_virtual_branch,
virtual_branches::commands::update_branch_order, virtual_branches::commands::update_branch_order,
virtual_branches::commands::delete_virtual_branch, virtual_branches::commands::unapply_without_saving_virtual_branch,
virtual_branches::commands::convert_to_real_branch, virtual_branches::commands::save_and_unapply_virtual_branch,
virtual_branches::commands::unapply_ownership, virtual_branches::commands::unapply_ownership,
virtual_branches::commands::reset_files, virtual_branches::commands::reset_files,
virtual_branches::commands::push_virtual_branch, virtual_branches::commands::push_virtual_branch,

View File

@ -205,28 +205,28 @@ pub mod commands {
#[tauri::command(async)] #[tauri::command(async)]
#[instrument(skip(projects, windows), err(Debug))] #[instrument(skip(projects, windows), err(Debug))]
pub fn delete_virtual_branch( pub fn unapply_without_saving_virtual_branch(
windows: State<'_, WindowState>, windows: State<'_, WindowState>,
projects: State<'_, projects::Controller>, projects: State<'_, projects::Controller>,
project_id: ProjectId, project_id: ProjectId,
branch_id: BranchId, branch_id: BranchId,
) -> Result<(), Error> { ) -> Result<(), Error> {
let project = projects.get(project_id)?; let project = projects.get(project_id)?;
gitbutler_branch_actions::delete_virtual_branch(&project, branch_id)?; gitbutler_branch_actions::unapply_without_saving_virtual_branch(&project, branch_id)?;
emit_vbranches(&windows, project_id); emit_vbranches(&windows, project_id);
Ok(()) Ok(())
} }
#[tauri::command(async)] #[tauri::command(async)]
#[instrument(skip(projects, windows), err(Debug))] #[instrument(skip(projects, windows), err(Debug))]
pub fn convert_to_real_branch( pub fn save_and_unapply_virtual_branch(
windows: State<'_, WindowState>, windows: State<'_, WindowState>,
projects: State<'_, projects::Controller>, projects: State<'_, projects::Controller>,
project_id: ProjectId, project_id: ProjectId,
branch: BranchId, branch: BranchId,
) -> Result<(), Error> { ) -> Result<(), Error> {
let project = projects.get(project_id)?; let project = projects.get(project_id)?;
gitbutler_branch_actions::convert_to_real_branch(&project, branch)?; gitbutler_branch_actions::save_and_unapply_virutal_branch(&project, branch)?;
emit_vbranches(&windows, project_id); emit_vbranches(&windows, project_id);
Ok(()) Ok(())
} }