2
2
use anyhow:: { Context , Result } ;
3
3
use gitbutler_cherry_pick:: RepositoryExt as _;
4
4
use gitbutler_command_context:: CommandContext ;
5
- use gitbutler_oxidize:: { GixRepositoryExt , ObjectIdExt , OidExt , RepoExt } ;
5
+ use gitbutler_oxidize:: { GixRepositoryExt , ObjectIdExt , OidExt } ;
6
6
use gitbutler_repo:: { RepositoryExt , SignaturePurpose } ;
7
7
use gitbutler_stack:: { Stack , VirtualBranchesHandle } ;
8
8
use gix:: merge:: tree:: TreatAsUnresolved ;
@@ -22,7 +22,7 @@ pub fn merge_worktree_with_workspace<'a>(
22
22
23
23
// The tree of where the gitbutler workspace is at
24
24
let workspace_tree = gix_repo
25
- . find_commit ( super :: remerged_head_commit ( ctx) ?. to_gix ( ) ) ?
25
+ . find_commit ( super :: remerged_workspace_commit_v2 ( ctx) ?. to_gix ( ) ) ?
26
26
. tree_id ( ) ?
27
27
. detach ( ) ;
28
28
@@ -40,16 +40,12 @@ pub fn merge_worktree_with_workspace<'a>(
40
40
Ok ( ( outcome, conflict_kind) )
41
41
}
42
42
43
- /// Creates and returns a merge commit of all active branch heads.
44
- ///
45
- /// This is the base against which we diff the working directory to understand
46
- /// what files have been modified.
47
- ///
48
- /// This should be used to update the `gitbutler/workspace` ref with, which is usually
49
- /// done from [`update_workspace_commit()`], after any of its input changes.
50
- /// This is namely the conflicting state, or any head of the virtual branches.
51
- #[ instrument( level = tracing:: Level :: DEBUG , skip( ctx) ) ]
52
- pub fn remerged_head_commit ( ctx : & CommandContext ) -> Result < git2:: Oid > {
43
+ /// Merge all currently stored stacks together into a new tree and return `(merged_tree, stacks, target_commit)` id accordingly.
44
+ /// `gix_repo` should be optimised for merging.
45
+ pub fn remerged_workspace_tree_v2 < ' git2_repo > (
46
+ ctx : & ' git2_repo CommandContext ,
47
+ gix_repo : & gix:: Repository ,
48
+ ) -> Result < ( git2:: Oid , Vec < Stack > , git2:: Commit < ' git2_repo > ) > {
53
49
let vb_state = VirtualBranchesHandle :: new ( ctx. project ( ) . gb_dir ( ) ) ;
54
50
let target = vb_state
55
51
. get_default_target ( )
@@ -58,15 +54,14 @@ pub fn remerged_head_commit(ctx: &CommandContext) -> Result<git2::Oid> {
58
54
let mut stacks: Vec < Stack > = vb_state. list_stacks_in_workspace ( ) ?;
59
55
60
56
let target_commit = repo. find_commit ( target. sha ) ?;
61
- let mut workspace_tree = repo. find_real_tree ( & target_commit, Default :: default ( ) ) ?;
57
+ let workspace_tree = repo. find_real_tree ( & target_commit, Default :: default ( ) ) ?;
62
58
let mut workspace_tree_id = workspace_tree. id ( ) . to_gix ( ) ;
63
59
64
- let gix_repo = ctx. gix_repo_for_merging ( ) ?;
65
60
let ( merge_options_fail_fast, conflict_kind) = gix_repo. merge_options_fail_fast ( ) ?;
66
61
let merge_tree_id = repo. find_commit ( target. sha ) ?. tree_id ( ) . to_gix ( ) ;
67
62
for stack in stacks. iter_mut ( ) {
68
63
stack. migrate_change_ids ( ctx) . ok ( ) ; // If it fails that's ok - best effort migration
69
- let branch_head = repo. find_commit ( stack. head_oid ( & gix_repo) ?. to_git2 ( ) ) ?;
64
+ let branch_head = repo. find_commit ( stack. head_oid ( gix_repo) ?. to_git2 ( ) ) ?;
70
65
let branch_tree_id = repo
71
66
. find_real_tree ( & branch_head, Default :: default ( ) ) ?
72
67
. id ( )
@@ -89,11 +84,26 @@ pub fn remerged_head_commit(ctx: &CommandContext) -> Result<git2::Oid> {
89
84
vb_state. set_stack ( stack. clone ( ) ) ?;
90
85
}
91
86
}
92
- workspace_tree = repo. find_tree ( workspace_tree_id. to_git2 ( ) ) ?;
87
+ Ok ( ( workspace_tree_id. to_git2 ( ) , stacks, target_commit) )
88
+ }
89
+
90
+ /// Creates and returns a merge commit of all active branch heads.
91
+ ///
92
+ /// This is the base against which we diff the working directory to understand
93
+ /// what files have been modified.
94
+ ///
95
+ /// This should be used to update the `gitbutler/workspace` ref with, which is usually
96
+ /// done from [`update_workspace_commit()`], after any of its input changes.
97
+ /// This is namely the conflicting state, or any head of the virtual branches.
98
+ #[ instrument( level = tracing:: Level :: DEBUG , skip( ctx) ) ]
99
+ pub fn remerged_workspace_commit_v2 ( ctx : & CommandContext ) -> Result < git2:: Oid > {
100
+ let repo = ctx. repo ( ) ;
101
+ let gix_repo = ctx. gix_repo_for_merging ( ) ?;
102
+ let ( workspace_tree_id, stacks, target_commit) = remerged_workspace_tree_v2 ( ctx, & gix_repo) ?;
103
+ let workspace_tree = repo. find_tree ( workspace_tree_id) ?;
93
104
94
105
let committer = gitbutler_repo:: signature ( SignaturePurpose :: Committer ) ?;
95
106
let author = gitbutler_repo:: signature ( SignaturePurpose :: Author ) ?;
96
- let gix_repo = repo. to_gix ( ) ?;
97
107
let mut heads: Vec < git2:: Commit < ' _ > > = stacks
98
108
. iter ( )
99
109
. filter_map ( |stack| stack. head_oid ( & gix_repo) . ok ( ) )
0 commit comments