Skip to content

Commit 25e8829

Browse files
committed
safe-checkout for 'update_uncommitted_changes()'
1 parent 0a2a280 commit 25e8829

File tree

6 files changed

+55
-52
lines changed

6 files changed

+55
-52
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/desktop/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ This builds the **web** target, points it to the but-server on `http://localhost
3737

3838
Open Chrome (let's not kid ourselves) and got to `http://localhost:1420` and enjoy
3939

40-
4140
### Development
4241

4342
#### Auto-build the server on Rust changes

crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{checkout_remerged_head, BranchManager};
1+
use super::BranchManager;
22
use crate::r#virtual as vbranch;
33
use crate::{hunk::VirtualBranchHunk, integration::update_workspace_commit, VirtualBranchesExt};
44
use anyhow::{anyhow, bail, Context, Result};
@@ -139,7 +139,9 @@ impl BranchManager<'_> {
139139
pr_number: Option<usize>,
140140
perm: &mut WorktreeWritePermission,
141141
) -> Result<(StackId, Vec<StackId>)> {
142-
let old_cwd = self.ctx.repo().create_wd_tree(0)?.id();
142+
let old_cwd = (!self.ctx.app_settings().feature_flags.cv3)
143+
.then(|| self.ctx.repo().create_wd_tree(0).map(|tree| tree.id()))
144+
.transpose()?;
143145
let old_workspace = WorkspaceState::create(self.ctx, perm.read_permission())?;
144146
// only set upstream if it's not the default target
145147
let upstream_branch = match upstream_branch {
@@ -270,13 +272,7 @@ impl BranchManager<'_> {
270272
)?;
271273
self.ctx.add_branch_reference(&branch)?;
272274

273-
match self.apply_branch(
274-
branch.id,
275-
perm,
276-
old_workspace,
277-
old_cwd,
278-
self.ctx.app_settings().feature_flags.cv3,
279-
) {
275+
match self.apply_branch(branch.id, perm, old_workspace, old_cwd) {
280276
Ok((_, unapplied_stacks)) => Ok((branch.id, unapplied_stacks)),
281277
Err(err)
282278
if err
@@ -299,8 +295,7 @@ impl BranchManager<'_> {
299295
stack_id: StackId,
300296
perm: &mut WorktreeWritePermission,
301297
workspace_state: WorkspaceState,
302-
old_cwd: git2::Oid,
303-
safe_checkout: bool,
298+
old_cwd: Option<git2::Oid>,
304299
) -> Result<(String, Vec<StackId>)> {
305300
let repo = self.ctx.repo();
306301

@@ -351,6 +346,7 @@ impl BranchManager<'_> {
351346
.filter(|branch| branch.id != stack_id)
352347
{
353348
unapplied_stacks.push(stack_to_unapply.id);
349+
let safe_checkout = old_cwd.is_none();
354350
let res =
355351
self.unapply(stack_to_unapply.id, perm, false, Vec::new(), safe_checkout);
356352
if res.is_err() {
@@ -437,23 +433,19 @@ impl BranchManager<'_> {
437433

438434
// Permissions here might be wonky, just go with it though.
439435
let new_workspace = WorkspaceState::create(self.ctx, perm.read_permission())?;
440-
if safe_checkout {
441-
let res = checkout_remerged_head(self.ctx, &gix_repo);
442-
if res.is_err() {
443-
stack.in_workspace = false;
444-
vb_state.set_stack(stack.clone())?;
445-
}
446-
res?;
447-
} else {
448-
update_uncommited_changes_with_tree(
449-
self.ctx,
450-
workspace_state,
451-
new_workspace,
452-
old_cwd,
453-
Some(true),
454-
perm,
455-
)?;
436+
let res = update_uncommited_changes_with_tree(
437+
self.ctx,
438+
workspace_state,
439+
new_workspace,
440+
old_cwd,
441+
Some(true),
442+
perm,
443+
);
444+
if res.is_err() {
445+
stack.in_workspace = false;
446+
vb_state.set_stack(stack.clone())?;
456447
}
448+
res?;
457449

458450
update_workspace_commit(&vb_state, self.ctx)?;
459451

crates/gitbutler-edit-mode/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ pub(crate) fn save_and_return_to_workspace(
289289
ctx,
290290
old_workspace,
291291
new_workspace,
292-
uncommtied_changes,
292+
Some(uncommtied_changes),
293293
Some(true),
294294
perm,
295295
)?;

crates/gitbutler-workspace/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ gitbutler-commit.workspace = true
1818
gitbutler-oxidize.workspace = true
1919
gitbutler-command-context.workspace = true
2020
gitbutler-cherry-pick.workspace = true
21+
but-workspace.workspace = true
2122
but-rebase.workspace = true

crates/gitbutler-workspace/src/branch_trees.rs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,42 +53,52 @@ pub fn update_uncommited_changes(
5353
perm: &mut WorktreeWritePermission,
5454
) -> Result<()> {
5555
let repo = ctx.repo();
56-
let uncommited_changes = repo.create_wd_tree(0)?;
56+
let uncommited_changes = (!ctx.app_settings().feature_flags.cv3)
57+
.then(|| repo.create_wd_tree(0).map(|tree| tree.id()))
58+
.transpose()?;
5759

58-
update_uncommited_changes_with_tree(ctx, old, new, uncommited_changes.id(), None, perm)
60+
update_uncommited_changes_with_tree(ctx, old, new, uncommited_changes, None, perm)
5961
}
6062

63+
/// `old_uncommitted_changes` is `None` if the `safe_checkout` feature is toggled on in `ctx`
6164
pub fn update_uncommited_changes_with_tree(
6265
ctx: &CommandContext,
6366
old: WorkspaceState,
6467
new: WorkspaceState,
65-
old_uncommited_changes: git2::Oid,
68+
old_uncommited_changes: Option<git2::Oid>,
6669
always_checkout: Option<bool>,
6770
_perm: &mut WorktreeWritePermission,
6871
) -> Result<()> {
6972
let repo = ctx.repo();
70-
71-
let mut new_uncommited_changes =
72-
move_tree_between_workspaces(repo, old_uncommited_changes, old, new)?;
73-
74-
// If the new tree and old tree are the same, then we don't need to do anything
75-
if !new_uncommited_changes.has_conflicts() && !always_checkout.unwrap_or(false) {
76-
let tree = new_uncommited_changes.write_tree_to(repo)?;
77-
if tree == old_uncommited_changes {
78-
return Ok(());
73+
if let Some(worktree_id) = old_uncommited_changes {
74+
let mut new_uncommited_changes = move_tree_between_workspaces(repo, worktree_id, old, new)?;
75+
76+
// If the new tree and old tree are the same, then we don't need to do anything
77+
if !new_uncommited_changes.has_conflicts() && !always_checkout.unwrap_or(false) {
78+
let tree = new_uncommited_changes.write_tree_to(repo)?;
79+
if tree == worktree_id {
80+
return Ok(());
81+
}
7982
}
80-
}
81-
82-
repo.checkout_index(
83-
Some(&mut new_uncommited_changes),
84-
Some(
85-
git2::build::CheckoutBuilder::new()
86-
.force()
87-
.remove_untracked(true)
88-
.conflict_style_diff3(true),
89-
),
90-
)?;
9183

84+
repo.checkout_index(
85+
Some(&mut new_uncommited_changes),
86+
Some(
87+
git2::build::CheckoutBuilder::new()
88+
.force()
89+
.remove_untracked(true)
90+
.conflict_style_diff3(true),
91+
),
92+
)?;
93+
} else {
94+
let new_tree_id = merge_workspace(repo, new)?.to_gix();
95+
let gix_repo = ctx.gix_repo_for_merging()?;
96+
but_workspace::branch::safe_checkout_from_head(
97+
new_tree_id,
98+
&gix_repo,
99+
but_workspace::branch::checkout::Options::default(),
100+
)?;
101+
}
92102
Ok(())
93103
}
94104

0 commit comments

Comments
 (0)