@@ -157,6 +157,7 @@ pub(crate) mod function {
157
157
repo,
158
158
checkout:: Options {
159
159
uncommitted_changes,
160
+ skip_head_update : false ,
160
161
} ,
161
162
) ?;
162
163
let graph = workspace. graph . redo_traversal_with_overlay (
@@ -262,7 +263,39 @@ pub(crate) mod function {
262
263
{
263
264
let ws_mut: & mut Workspace = & mut ws_md;
264
265
for rn in & branches_to_apply {
265
- ws_mut. add_or_insert_new_stack_if_not_present ( rn, order) ;
266
+ // Here we have to check if the new ref would be able to become its own stack,
267
+ // or if it has to be a dependent branch. Stacks only work if the ref rests on a base
268
+ // outside the workspace, so if we find it in the workspace (in an ambiguous spot) it must be
269
+ // a dependent branch
270
+ if let Some ( segment_to_insert_above) = workspace
271
+ . stacks
272
+ . iter ( )
273
+ . flat_map ( |stack| stack. segments . iter ( ) )
274
+ . find_map ( |segment| {
275
+ segment. commits . iter ( ) . flat_map ( |c| c. refs . iter ( ) ) . find_map (
276
+ |ambiguous_rn| {
277
+ ( ambiguous_rn. as_ref ( ) == * rn)
278
+ . then_some ( segment. ref_name . as_ref ( ) )
279
+ . flatten ( )
280
+ } ,
281
+ )
282
+ } )
283
+ {
284
+ if ws_mut
285
+ . insert_new_segment_above_anchor_if_not_present (
286
+ rn,
287
+ segment_to_insert_above. as_ref ( ) ,
288
+ )
289
+ . is_none ( )
290
+ {
291
+ // For now bail, until we know it's worth fixing this case automatically.
292
+ bail ! (
293
+ "Missing reference {segment_to_insert_above} which should be known to workspace metadata to serve as insertion position for {rn}"
294
+ ) ;
295
+ }
296
+ } else {
297
+ ws_mut. add_or_insert_new_stack_if_not_present ( rn, order) ;
298
+ }
266
299
}
267
300
}
268
301
let ws_md_override = Some ( ( workspace_ref_name_to_update. clone ( ) , ( * ws_md) . clone ( ) ) ) ;
@@ -353,31 +386,55 @@ pub(crate) mod function {
353
386
} ) ;
354
387
}
355
388
356
- // All work is done, persist and exit.
357
- // Note that it could be that some stacks aren't merged in,
358
- // while being present in the workspace metadata.
359
- // This is OK for us. We also trust that the hero-branch was merged in, no matter what.
360
- if let Some ( storage) = in_memory_repo. objects . take_object_memory ( ) {
361
- storage. persist ( repo) ?;
362
- drop ( in_memory_repo) ;
363
- }
364
389
let prev_head_id = graph
365
390
. entrypoint_commit ( )
366
391
. context ( "BUG: how is it possible that there is no head commit?" ) ?
367
392
. id ;
368
393
let new_head_id = merge_result. workspace_commit_id ;
369
394
let graph = graph. redo_traversal_with_overlay (
370
- repo ,
395
+ & in_memory_repo ,
371
396
meta,
372
397
overlay. with_entrypoint ( new_head_id, Some ( workspace_ref_name_to_update. clone ( ) ) ) ,
373
398
) ?;
399
+
400
+ let workspace = graph. to_workspace ( ) ?;
401
+ let unapplied_branches: Vec < _ > = branches_to_apply
402
+ . iter ( )
403
+ . filter_map ( |rn| {
404
+ if workspace. refname_is_segment ( rn) {
405
+ None
406
+ } else {
407
+ Some ( rn)
408
+ }
409
+ } )
410
+ . collect ( ) ;
411
+ if !unapplied_branches. is_empty ( ) {
412
+ bail ! (
413
+ "Unexpectedly failed to apply {branches} which is/are still not in the workspace" ,
414
+ branches = unapplied_branches
415
+ . iter( )
416
+ . map( |rn| rn. shorten( ) . to_string( ) )
417
+ . collect:: <Vec <_>>( )
418
+ . join( ", " )
419
+ )
420
+ }
421
+
422
+ // All work is done, persist and exit.
423
+ // Note that it could be that some stacks aren't merged in,
424
+ // while being present in the workspace metadata.
425
+ // This is OK for us. We also trust that the hero-branch was merged in, no matter what.
426
+ if let Some ( storage) = in_memory_repo. objects . take_object_memory ( ) {
427
+ storage. persist ( repo) ?;
428
+ drop ( in_memory_repo) ;
429
+ }
374
430
persist_metadata ( meta, & branches_to_apply, & ws_md) ?;
375
431
crate :: branch:: safe_checkout (
376
432
prev_head_id,
377
433
new_head_id,
378
434
repo,
379
435
checkout:: Options {
380
436
uncommitted_changes,
437
+ skip_head_update : true ,
381
438
} ,
382
439
) ?;
383
440
@@ -416,10 +473,9 @@ pub(crate) mod function {
416
473
new_ref_target : gix:: ObjectId ,
417
474
new_ref : Option < & gix:: refs:: FullNameRef > ,
418
475
) -> anyhow:: Result < ( ) > {
419
- // This also means we want HEAD to point to it.
420
- let head_message = "GitButler switch to workspace during apply-branch" . into ( ) ;
421
476
let edits = match new_ref {
422
477
None => {
478
+ let head_message = "GitButler checkout workspace during apply-branch" . into ( ) ;
423
479
vec ! [ RefEdit {
424
480
change: Change :: Update {
425
481
log: LogChange {
@@ -435,6 +491,8 @@ pub(crate) mod function {
435
491
} ]
436
492
}
437
493
Some ( new_ref) => {
494
+ // This also means we want HEAD to point to it.
495
+ let head_message = "GitButler switch to workspace during apply-branch" . into ( ) ;
438
496
vec ! [
439
497
RefEdit {
440
498
change: Change :: Update {
0 commit comments