1
- use std:: collections:: HashSet ;
1
+ use std:: collections:: { BTreeSet , HashSet , VecDeque } ;
2
2
3
3
use crate :: error:: Error ;
4
4
use crate :: hex_hash:: HexHash ;
5
5
use anyhow:: Context ;
6
6
use but_api_macros:: api_cmd;
7
7
use but_graph:: VirtualBranchesTomlMetadata ;
8
+ use but_graph:: petgraph:: Direction ;
8
9
use but_hunk_assignment:: HunkAssignmentRequest ;
9
10
use but_settings:: AppSettings ;
10
11
use but_workspace:: MoveChangesResult ;
@@ -19,6 +20,7 @@ use gitbutler_reference::{LocalRefname, Refname};
19
20
use gitbutler_stack:: { StackId , VirtualBranchesHandle } ;
20
21
use serde:: Serialize ;
21
22
use tracing:: instrument;
23
+
22
24
fn ref_metadata_toml ( project : & Project ) -> anyhow:: Result < VirtualBranchesTomlMetadata > {
23
25
VirtualBranchesTomlMetadata :: from_path ( project. gb_dir ( ) . join ( "virtual_branches.toml" ) )
24
26
}
@@ -62,24 +64,35 @@ pub fn show_graph_svg(project_id: ProjectId) -> Result<(), Error> {
62
64
..but_graph:: init:: Options :: limited ( )
63
65
} ,
64
66
) ?;
65
- const LIMIT : usize = 3000 ;
66
- if graph. num_segments ( ) > LIMIT {
67
- let mut topo = graph. topo_walk ( ) ;
68
- let mut count = 0 ;
69
-
70
- let mut remove = Vec :: new ( ) ;
71
- while let Some ( sidx) = topo. next ( & * graph) {
72
- count += 1 ;
73
- if count > LIMIT {
74
- remove. push ( sidx) ;
75
- }
76
- }
67
+ // It's OK if it takes a while, prefer complete graphs.
68
+ const LIMIT : usize = 5000 ;
69
+ let mut to_remove = graph. num_segments ( ) . saturating_sub ( LIMIT ) ;
70
+ if to_remove > 0 {
77
71
tracing:: warn!(
78
- "Pruning {nodes} to assure 'dot' won't hang" ,
79
- nodes = remove. len( )
72
+ "Pruning at most {to_remove} nodes from the bottom to assure 'dot' won't hang" ,
80
73
) ;
81
- for sidx in remove {
74
+ let mut next = VecDeque :: new ( ) ;
75
+ next. extend ( graph. base_segments ( ) ) ;
76
+ let mut seen = BTreeSet :: new ( ) ;
77
+ while let Some ( sidx) = next. pop_front ( ) {
78
+ if to_remove == 0 {
79
+ break ;
80
+ }
81
+ if let Some ( s) = graph. node_weight ( sidx)
82
+ && ( s. metadata . is_some ( ) || s. sibling_segment_id . is_some ( ) )
83
+ {
84
+ continue ;
85
+ }
86
+ next. extend (
87
+ graph
88
+ . neighbors_directed ( sidx, Direction :: Incoming )
89
+ . filter ( |n| seen. insert ( * n) ) ,
90
+ ) ;
82
91
graph. remove_node ( sidx) ;
92
+ to_remove -= 1 ;
93
+ }
94
+ if to_remove != 0 {
95
+ tracing:: warn!( "{to_remove} extra nodes were kept to keep vital portions of the graph" ) ;
83
96
}
84
97
graph. set_hard_limit_hit ( ) ;
85
98
}
0 commit comments