@@ -30,6 +30,9 @@ pub(super) mod function {
3030
3131 /// Move a branch between stacks in the `workspace`.
3232 ///
33+ /// `editor` is assumed to have been generated from the given `workspace`
34+ /// and therefore aligned.
35+ ///
3336 /// `subject_branch_name` is the full reference name of the branch to move.
3437 ///
3538 /// `target_branch_name` is the full reference name of the branch to move the subject
@@ -43,18 +46,8 @@ pub(super) mod function {
4346 subject_branch_name : & FullNameRef ,
4447 target_branch_name : & FullNameRef ,
4548 ) -> anyhow:: Result < Outcome > {
46- let Some ( source) = workspace. find_segment_and_stack_by_refname ( subject_branch_name) else {
47- bail ! (
48- "Couldn't find branch to move in workspace with reference name: {subject_branch_name}"
49- ) ;
50- } ;
51-
52- let Some ( destination) = workspace. find_segment_and_stack_by_refname ( target_branch_name)
53- else {
54- bail ! (
55- "Couldn't find target branch to move in workspace with reference name: {target_branch_name}"
56- ) ;
57- } ;
49+ let ( source, destination) =
50+ retrieve_branches_and_containers ( workspace, subject_branch_name, target_branch_name) ?;
5851
5952 let Some ( workspace_head) = workspace. tip_commit ( ) . map ( |commit| commit. id ) else {
6053 bail ! ( "Couldn't find workspace head." )
@@ -123,6 +116,56 @@ pub(super) mod function {
123116 ws_meta,
124117 } )
125118 }
119+
120+ /// A segment and its container stack.
121+ type WorkspaceSegmentContext < ' a > = (
122+ & ' a but_graph:: projection:: Stack ,
123+ & ' a but_graph:: projection:: StackSegment ,
124+ ) ;
125+
126+ /// Determine the surrounding context of the subject and target branches.
127+ ///
128+ /// Currently, this looks into the workspace projection in order to determine **where to take the branch from and to**.
129+ ///
130+ /// ### The issue
131+ /// It's impossible to know for sure what is the exact intention of 'moving a branch' inside a complex git graph.
132+ /// Any commit, can have N children and M parents. 'Moving' it somewhere else can imply:
133+ /// - Disconnecting all parents and children, and inserting it somewhere else.
134+ /// - Disconnecting the first parent and all children, and then inserting.
135+ /// - Disconnecting *some* parents and *some* children, and then inserting it.
136+ ///
137+ /// This condition holds for every commit in a branch.
138+ ///
139+ /// ### The GitButler assumption
140+ /// In the context of a GitButler workspace (as of this writting), we want to disconnect the branch (segment) from
141+ /// the stack, and insert it on top of another. In graph terms, this means that we:
142+ /// - Disconnect the reference node from the base segment (the branch under the subject or the target base)
143+ /// - Disconnect the last commit node of the child segment (the branch over the subject or the workspace commit)
144+ /// - Nothing else. Other parentage and childrent are kept, since this is what we care about in a GB workspace world.
145+ ///
146+ /// ### What the future holds
147+ /// In the future, where we're not afraid of complex graphs, we've figured out UX and data wrangling,
148+ /// the concept of a segment might not hold, and hence we'll have to figure out a better way of dermining
149+ /// what to cut (e.g. letting the clients decide what to cut).
150+ fn retrieve_branches_and_containers < ' a > (
151+ workspace : & ' a but_graph:: projection:: Workspace ,
152+ subject_branch_name : & FullNameRef ,
153+ target_branch_name : & FullNameRef ,
154+ ) -> anyhow:: Result < ( WorkspaceSegmentContext < ' a > , WorkspaceSegmentContext < ' a > ) > {
155+ let Some ( source) = workspace. find_segment_and_stack_by_refname ( subject_branch_name) else {
156+ bail ! (
157+ "Couldn't find branch to move in workspace with reference name: {subject_branch_name}"
158+ ) ;
159+ } ;
160+
161+ let Some ( destination) = workspace. find_segment_and_stack_by_refname ( target_branch_name)
162+ else {
163+ bail ! (
164+ "Couldn't find target branch to move in workspace with reference name: {target_branch_name}"
165+ ) ;
166+ } ;
167+ Ok ( ( source, destination) )
168+ }
126169}
127170
128171/// Get the right disconnect parameters for the given subject segment and source stack.
0 commit comments