Skip to content

Commit fe26460

Browse files
committed
doc: Describe algorithm for graph layout (close #6)
1 parent 95d5c6f commit fe26460

3 files changed

Lines changed: 60 additions & 0 deletions

File tree

‎src/branch_assignment.md‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
# Overview
3+
4+
To generate a graph, [GitGraph::new()] will read the repository
5+
and assign every commit to a single branch.
6+
7+
It takes the following steps to generate the graph
8+
9+
- Identify branches
10+
- Sort branches by persistence
11+
- Trace branches to commits
12+
- Filtering and indexing
13+
14+
## Identify branches
15+
Local and remote git-branches and tags are used as candidates for branches.
16+
A branch can be identified by a merge commit, even though no current git-branch
17+
refers to it.
18+
19+
## Sort branches by persistence
20+
Each branch is assigned a persistence which can be configured by settings.
21+
Think of persistence as z-order where lower values take preceedence.
22+
**TODO** Merge branch
23+
24+
## Trace branches to commits
25+
The branches now get to pick their commits, in order of persistence. Each
26+
branch starts with a head, and follow the primary parent while it is
27+
available. It stops when the parent is a commit already assigned to a branch.
28+
**TODO** Duplicate branch names
29+
**TODO** Handle visual artifacts on merge
30+
31+
## Filtering and indexing
32+
Commits that have not been assigned a branch is filtered out.
33+
An *index_map* is created to map from original commit index, to filtered
34+
commit index.
35+
**TODO** what? why? Would it not be better to track from child/heads instead of every single commit in repo?
36+
37+
38+
39+
40+
# Branch sorting
41+
The goal of this algorithm is to assign a column number to each tracked branch so that they can be visualized linearly without overlapping in the graph. It uses a shortest-first scheduling strategy (optionally longest-first and with forward/backward start sorting).
42+
43+
## Initialization
44+
- occupied: A vector of vectors of vectors of tuples.
45+
The outer vector is indexed by the branch's order_group (determined by branch_order based on the settings.branches.order).
46+
Each inner vector represents a column within that order group,
47+
and the tuples (start, end) store the range of commits occupied by a branch in that column.
48+
49+
## Preparing Branches for Sorting
50+
- It creates branches_sort, a vector of tuples containing the branch index, its start commit index (range.0), its end commit index (range.1), its source order group, and its target order group.
51+
- It filters out branches that don't have a defined range (meaning they weren't associated with any commits).
52+
## Sorting Branches
53+
- The branches_sort vector is sorted based on a key that prioritizes:
54+
1. The maximum of the source and target order groups. This likely aims to keep related branches (e.g., those involved in merges) closer together.
55+
2. The length of the branch's lifespan (end - start commit index), either shortest-first or longest-first based on the shortest_first setting.
56+
3. The starting commit index, either forward or backward based on the forward setting.

‎src/graph.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ pub struct GitGraph {
4444
}
4545

4646
impl GitGraph {
47+
/// Generate a branch graph for a repository
4748
pub fn new(
4849
mut repository: Repository,
4950
settings: &Settings,
5051
max_count: Option<usize>,
5152
) -> Result<Self, String> {
53+
#![doc = include_str!("branch_assignment.md")]
5254
let mut stashes = HashSet::new();
5355
repository
5456
.stash_foreach(|_, _, oid| {

‎src/print/unicode.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub fn print_unicode(graph: &GitGraph, settings: &Settings) -> Result<UnicodeGra
8383
None
8484
};
8585

86+
// Compute commit text into text_lines
8687
let mut index_map = vec![];
8788
let mut text_lines = vec![];
8889
let mut offset = 0;
@@ -133,6 +134,7 @@ pub fn print_unicode(graph: &GitGraph, settings: &Settings) -> Result<UnicodeGra
133134
[SPACE, WHITE, settings.branches.persistence.len() as u8 + 2],
134135
);
135136

137+
// Compute branch lines in grid
136138
for (idx, info) in graph.commits.iter().enumerate() {
137139
if let Some(trace) = info.branch_trace {
138140
let branch = &graph.all_branches[trace];

0 commit comments

Comments
 (0)