Skip to content

Commit ec33a5a

Browse files
committed
Don't blindly delete important parts of the graph to make dot not hang.
The graph now is still somewhat confusing, but it will keep important nodes, always.
1 parent 9b049ea commit ec33a5a

File tree

2 files changed

+30
-17
lines changed

2 files changed

+30
-17
lines changed

crates/but-api/src/commands/workspace.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use std::collections::HashSet;
1+
use std::collections::{BTreeSet, HashSet, VecDeque};
22

33
use crate::error::Error;
44
use crate::hex_hash::HexHash;
55
use anyhow::Context;
66
use but_api_macros::api_cmd;
77
use but_graph::VirtualBranchesTomlMetadata;
8+
use but_graph::petgraph::Direction;
89
use but_hunk_assignment::HunkAssignmentRequest;
910
use but_settings::AppSettings;
1011
use but_workspace::MoveChangesResult;
@@ -19,6 +20,7 @@ use gitbutler_reference::{LocalRefname, Refname};
1920
use gitbutler_stack::{StackId, VirtualBranchesHandle};
2021
use serde::Serialize;
2122
use tracing::instrument;
23+
2224
fn ref_metadata_toml(project: &Project) -> anyhow::Result<VirtualBranchesTomlMetadata> {
2325
VirtualBranchesTomlMetadata::from_path(project.gb_dir().join("virtual_branches.toml"))
2426
}
@@ -62,24 +64,35 @@ pub fn show_graph_svg(project_id: ProjectId) -> Result<(), Error> {
6264
..but_graph::init::Options::limited()
6365
},
6466
)?;
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 {
7771
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",
8073
);
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+
);
8291
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");
8396
}
8497
graph.set_hard_limit_hit();
8598
}

crates/but-workspace/src/changeset.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl RefInfo {
124124
// This happens when the identity match with the remote didn't work.
125125
LocalCommitRelation::LocalOnly |
126126
// This would be expected to be a remote-match by identity (we don't check for this),
127-
// something that is determined during graph traversal time. But we want ot see
127+
// something that is determined during graph traversal time. But we want to see
128128
// if any of these is also integrated.
129129
LocalCommitRelation::LocalAndRemote(_)
130130
)

0 commit comments

Comments
 (0)