Round commit graph connections

This commit is contained in:
Georg Bauer
2026-07-31 17:44:09 +02:00
parent dba6359d30
commit eadbadd3cb
6 changed files with 144 additions and 49 deletions

View File

@@ -177,7 +177,8 @@ pub struct CommitRow {
pub top_lanes: Vec<u32>,
pub bottom_lanes: Vec<u32>,
pub node_lane: Option<u32>,
pub connections: Vec<u32>,
pub top_connections: Vec<u32>,
pub bottom_connections: Vec<u32>,
}
#[derive(Clone, uniffi::Record)]
@@ -477,7 +478,8 @@ pub fn commit_page(
.top_lanes
.iter()
.chain(commit.bottom_lanes.iter())
.chain(commit.connections.iter())
.chain(commit.top_connections.iter())
.chain(commit.bottom_connections.iter())
.chain(commit.node_lane.iter())
})
.max()
@@ -525,7 +527,8 @@ pub fn commit_page(
top_lanes: indices(&row.top_lanes),
bottom_lanes: indices(&row.bottom_lanes),
node_lane: row.node_lane.map(|lane| lane as u32),
connections: indices(&row.connections),
top_connections: indices(&row.top_connections),
bottom_connections: indices(&row.bottom_connections),
})
})
.collect();

View File

@@ -156,7 +156,8 @@ pub struct HistoryCommit {
pub top_lanes: Vec<usize>,
pub bottom_lanes: Vec<usize>,
pub node_lane: Option<usize>,
pub connections: Vec<usize>,
pub top_connections: Vec<usize>,
pub bottom_connections: Vec<usize>,
pub refs: Vec<String>,
}

View File

@@ -144,7 +144,8 @@ impl Client {
top_lanes: Vec::new(),
bottom_lanes: Vec::new(),
node_lane: None,
connections: Vec::new(),
top_connections: Vec::new(),
bottom_connections: Vec::new(),
refs: Vec::new(),
})
.collect(),
@@ -346,7 +347,8 @@ fn build_graph(
top_lanes: Vec::new(),
bottom_lanes: Vec::new(),
node_lane: None,
connections: Vec::new(),
top_connections: Vec::new(),
bottom_connections: Vec::new(),
refs: refs.remove(&sha).unwrap_or_default(),
});
}
@@ -373,11 +375,12 @@ fn layout_graph(commits: &mut [HistoryCommit]) {
.filter_map(|(index, lane)| lane.as_ref().map(|_| index))
.filter(|index| existing_node.is_some() || *index != node)
.collect();
let mut connections = BTreeSet::new();
let mut top_connections = BTreeSet::new();
for duplicate in matching_lanes.into_iter().skip(1) {
lanes[duplicate] = None;
connect(node, duplicate, &mut connections);
top_connections.insert(duplicate);
}
let mut bottom_connections = BTreeSet::new();
let parents: Vec<_> = commit_parents(&row.commit).map(str::to_string).collect();
lanes[node] = None;
for (index, parent) in parents.into_iter().enumerate() {
@@ -387,14 +390,17 @@ fn layout_graph(commits: &mut [HistoryCommit]) {
.iter()
.position(|next| next.as_deref() == Some(&parent))
{
connect(node, existing, &mut connections);
if node != existing {
bottom_connections.insert(existing);
}
} else {
let branch = allocate_lane(&mut lanes, &parent);
connect(node, branch, &mut connections);
bottom_connections.insert(branch);
}
}
row.node_lane = Some(node);
row.connections = connections.into_iter().collect();
row.top_connections = top_connections.into_iter().collect();
row.bottom_connections = bottom_connections.into_iter().collect();
row.bottom_lanes = lanes
.iter()
.enumerate()
@@ -413,12 +419,6 @@ fn allocate_lane(lanes: &mut Vec<Option<String>>, sha: &str) -> usize {
}
}
fn connect(left: usize, right: usize, connections: &mut BTreeSet<usize>) {
for lane in left.min(right) + 1..=left.max(right) {
connections.insert(lane);
}
}
fn commit_parents(commit: &models::Commit) -> impl Iterator<Item = &str> {
commit
.parents
@@ -464,15 +464,39 @@ mod tests {
(
0,
"main".into(),
vec![commit("merge", &["left", "right"]), commit("left", &[])],
vec![
commit("merge", &["left", "right"]),
commit("left", &["base"]),
commit("base", &[]),
],
),
(
1,
"feature".into(),
vec![commit("right", &["base"]), commit("base", &[])],
),
(1, "feature".into(), vec![commit("right", &[])]),
],
HashMap::new(),
);
assert_eq!(rows.len(), 3);
assert_eq!(rows.len(), 4);
assert!(rows.iter().any(|row| row.refs == ["main"]));
assert!(rows.iter().any(|row| row.refs == ["feature"]));
assert!(rows.iter().any(|row| !row.connections.is_empty()));
let merge = rows
.iter()
.find(|row| row.commit.sha.as_deref() == Some("merge"))
.unwrap();
assert_eq!(merge.node_lane, Some(0));
assert_eq!(merge.bottom_connections, [1]);
let right = rows
.iter()
.find(|row| row.commit.sha.as_deref() == Some("right"))
.unwrap();
assert_eq!(right.node_lane, Some(1));
let base = rows
.iter()
.find(|row| row.commit.sha.as_deref() == Some("base"))
.unwrap();
assert_eq!(base.node_lane, Some(0));
assert_eq!(base.top_connections, [1]);
}
}