@@ -88,14 +88,36 @@ pub fn list_branches(
88
88
}
89
89
90
90
let vb_handle = ctx. project ( ) . virtual_branches ( ) ;
91
- let stacks = vb_handle. list_all_stacks ( ) ?;
92
91
let remote_names = repo. remote_names ( ) ;
93
- branches. extend (
94
- stacks
92
+ let stacks = if ctx. app_settings ( ) . feature_flags . ws3 {
93
+ if let Some ( workspace_ref) = repo. try_find_reference ( "refs/heads/gitbutler/workspace" ) ? {
94
+ // Let's get this here for convenience, and hope this isn't ever called by a writer (or there will be a deadlock).
95
+ let read_guard = ctx. project ( ) . shared_worktree_access ( ) ;
96
+ let meta = ctx. meta ( read_guard. read_permission ( ) ) ?;
97
+ let info = but_workspace:: ref_info (
98
+ workspace_ref,
99
+ & * meta,
100
+ but_workspace:: ref_info:: Options {
101
+ traversal : but_graph:: init:: Options :: limited ( ) ,
102
+ expensive_commit_info : false ,
103
+ } ,
104
+ ) ?;
105
+ info. stacks
106
+ . into_iter ( )
107
+ . map ( |s| GitButlerStack :: new ( s, & remote_names) )
108
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?
109
+ } else {
110
+ Vec :: new ( )
111
+ }
112
+ } else {
113
+ vb_handle
114
+ . list_all_stacks ( ) ?
95
115
. iter ( )
96
- . map ( |s| GitButlerStack :: new ( s, & remote_names) . map ( GroupBranch :: Virtual ) )
97
- . collect :: < Result < Vec < _ > , _ > > ( ) ?,
98
- ) ;
116
+ . map ( |s| GitButlerStack :: new_from_old ( s, & remote_names) )
117
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?
118
+ } ;
119
+
120
+ branches. extend ( stacks. iter ( ) . map ( |s| GroupBranch :: Virtual ( s. clone ( ) ) ) ) ;
99
121
let mut branches = combine_branches ( branches, & repo, vb_handle. get_default_target ( ) ?) ?;
100
122
101
123
// Apply the filter
@@ -135,13 +157,13 @@ pub fn list_branches(
135
157
// To do this, we build up a list of all the branch identities that are
136
158
// part of a stack and then filter out any branches that have been grouped
137
159
// without a stack and match one of these identities.
138
- let branch_identities_to_exclude = stacks
139
- . iter ( )
160
+ let branch_identities_to_exclude: HashSet < BString > = stacks
161
+ . into_iter ( )
140
162
. flat_map ( |s| {
141
- s. branches ( )
163
+ s. unarchived_segments
142
164
. into_iter ( )
143
- . map ( |b| BString :: from ( b . name ( ) . to_owned ( ) ) )
144
- . chain ( [ BString :: from ( s. name . to_owned ( ) ) ] )
165
+ . map ( |b| b . short_name ( ) . into ( ) )
166
+ . chain ( Some ( s. name . into ( ) ) )
145
167
} )
146
168
. collect :: < HashSet < _ > > ( ) ;
147
169
@@ -337,7 +359,7 @@ enum GroupBranch<'a> {
337
359
}
338
360
339
361
/// A type to just keep the parts we currently need.
340
- #[ derive( Debug ) ]
362
+ #[ derive( Debug , Clone ) ]
341
363
struct GitButlerStack {
342
364
id : StackId ,
343
365
/// `true` if the stack is applied to the workspace.
@@ -355,7 +377,7 @@ struct GitButlerStack {
355
377
unarchived_segments : Vec < GitbutlerStackSegment > ,
356
378
}
357
379
358
- #[ derive( Debug ) ]
380
+ #[ derive( Debug , Clone ) ]
359
381
struct GitbutlerStackSegment {
360
382
/// The name of the segment, without support for these to be anonymous (which is a problem).
361
383
tip : gix:: refs:: FullName ,
@@ -370,16 +392,62 @@ impl GitbutlerStackSegment {
370
392
}
371
393
372
394
impl GitButlerStack {
373
- fn new ( s : & Stack , names : & gix:: remote:: Names ) -> anyhow:: Result < Self > {
395
+ fn new (
396
+ stack : but_workspace:: branch:: Stack ,
397
+ names : & gix:: remote:: Names ,
398
+ ) -> anyhow:: Result < Self > {
399
+ let first_segment = stack. segments . first ( ) ;
374
400
Ok ( GitButlerStack {
375
- id : s. id ,
376
- in_workspace : s. in_workspace ,
377
- name : s. name . clone ( ) ,
378
- source_refname : s
401
+ id : stack. id . context ( "Can't handle stacks without ID yet" ) ?,
402
+ // The ones we have reachable are never
403
+ in_workspace : true ,
404
+ name : stack
405
+ . name ( )
406
+ . map ( |rn| rn. shorten ( ) . to_string ( ) )
407
+ // Hack it - the datastructure isn't suitable and this needs a `gitbutler->but` port.
408
+ . unwrap_or_default ( ) ,
409
+ source_refname : stack. ref_name ( ) . map ( |rn| rn. to_owned ( ) ) ,
410
+ upstream : first_segment
411
+ . and_then ( |s| {
412
+ s. remote_tracking_ref_name . as_ref ( ) . map ( |rn| {
413
+ but_workspace:: ui:: ref_info:: RemoteTrackingReference :: for_ui (
414
+ rn. clone ( ) ,
415
+ names,
416
+ )
417
+ } )
418
+ } )
419
+ . transpose ( ) ?,
420
+ updated_timestamp_ms : first_segment
421
+ . and_then ( |s| {
422
+ let md = s. metadata . as_ref ( ) ?;
423
+ Some ( md. ref_info . updated_at ?. seconds as u128 * 1_000 )
424
+ } )
425
+ . unwrap_or_default ( ) ,
426
+ unarchived_segments : stack
427
+ . segments
428
+ . iter ( )
429
+ . map ( |s| GitbutlerStackSegment {
430
+ tip : s. ref_name . clone ( ) . unwrap_or_else ( || {
431
+ gix:: refs:: FullName :: try_from (
432
+ "refs/heads/unnamed-ref-and-we-fake-a-name-fix-me" ,
433
+ )
434
+ . expect ( "known to be valid statically" )
435
+ } ) ,
436
+ pr_or_mr : s. metadata . as_ref ( ) . and_then ( |md| md. review . pull_request ) ,
437
+ } )
438
+ . collect ( ) ,
439
+ } )
440
+ }
441
+ fn new_from_old ( stack : & Stack , names : & gix:: remote:: Names ) -> anyhow:: Result < Self > {
442
+ Ok ( GitButlerStack {
443
+ id : stack. id ,
444
+ in_workspace : stack. in_workspace ,
445
+ name : stack. name . clone ( ) ,
446
+ source_refname : stack
379
447
. source_refname
380
448
. as_ref ( )
381
449
. and_then ( |r| r. to_string ( ) . try_into ( ) . ok ( ) ) ,
382
- upstream : s
450
+ upstream : stack
383
451
. upstream
384
452
. as_ref ( )
385
453
. and_then ( |r| {
@@ -388,8 +456,8 @@ impl GitButlerStack {
388
456
} )
389
457
} )
390
458
. transpose ( ) ?,
391
- updated_timestamp_ms : s . updated_timestamp_ms ,
392
- unarchived_segments : s
459
+ updated_timestamp_ms : stack . updated_timestamp_ms ,
460
+ unarchived_segments : stack
393
461
. branches ( )
394
462
. iter ( )
395
463
// The tip is at the bottom here.
0 commit comments