Skip to content

Commit 08a1ef8

Browse files
committed
A first shot at producing stacks from a graph
1 parent 091661f commit 08a1ef8

File tree

14 files changed

+804
-197
lines changed

14 files changed

+804
-197
lines changed

crates/but-graph/src/api.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,25 @@ impl Graph {
9494
/// aren't fully defined as traversal stopped due to some abort condition being met.
9595
/// Valid partial segments always have at least one commit.
9696
pub fn partial_segments(&self) -> impl Iterator<Item = SegmentIndex> {
97-
self.base_segments().filter(|s| {
98-
let has_outgoing = self
99-
.inner
100-
.edges_directed(*s, Direction::Outgoing)
101-
.next()
102-
.is_some();
103-
if has_outgoing {
104-
return false;
105-
}
106-
self[*s]
107-
.commits
108-
.first()
109-
.is_none_or(|c| !c.parent_ids.is_empty())
110-
})
97+
self.base_segments().filter(|s| self.is_partial_segment(*s))
98+
}
99+
100+
/// Return `true` if the segment behind `sidx`
101+
/// isn't fully defined as traversal stopped due to some abort condition.
102+
/// Valid partial segments always have at least one commit.
103+
pub fn is_partial_segment(&self, sidx: SegmentIndex) -> bool {
104+
let has_outgoing = self
105+
.inner
106+
.edges_directed(sidx, Direction::Outgoing)
107+
.next()
108+
.is_some();
109+
if has_outgoing {
110+
return false;
111+
}
112+
self[sidx]
113+
.commits
114+
.first()
115+
.is_none_or(|c| !c.parent_ids.is_empty())
111116
}
112117

113118
/// Return all segments that sit on top of the `sidx` segment as `(source_commit_index(of sidx), destination_segment_index)`,

crates/but-graph/src/debug.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::init::PetGraph;
2-
use crate::{CommitFlags, Edge, Graph, Segment, SegmentIndex};
2+
use crate::{Edge, Graph, Segment, SegmentIndex};
33
use bstr::ByteSlice;
44
use gix::reference::Category;
55
use petgraph::graph::EdgeReference;
@@ -10,26 +10,24 @@ impl Graph {
1010
/// Produce a string that concisely represents `commit`, adding `extra` information as needed.
1111
pub fn commit_debug_string(
1212
commit: &crate::Commit,
13-
has_conflicts: bool,
1413
is_entrypoint: bool,
1514
show_message: bool,
1615
is_early_end: bool,
1716
hard_limit: bool,
1817
) -> String {
1918
format!(
20-
"{ep}{end}{kind}{conflict}{hex}{flags}{msg}{refs}",
19+
"{ep}{end}{kind}{hex}{flags}{msg}{refs}",
2120
ep = if is_entrypoint { "👉" } else { "" },
2221
end = if is_early_end {
2322
if hard_limit { "❌" } else { "✂️" }
2423
} else {
2524
""
2625
},
27-
kind = if commit.flags.contains(CommitFlags::NotInRemote) {
28-
"·"
29-
} else {
26+
kind = if commit.flags.is_remote() {
3027
"🟣"
28+
} else {
29+
"·"
3130
},
32-
conflict = if has_conflicts { "💥" } else { "" },
3331
flags = if !commit.flags.is_empty() {
3432
format!(" ({})", commit.flags.debug_string())
3533
} else {
@@ -173,10 +171,6 @@ impl Graph {
173171
.map(|(cidx, c)| {
174172
Self::commit_debug_string(
175173
c,
176-
c.details
177-
.as_ref()
178-
.map(|d| d.has_conflicts)
179-
.unwrap_or_default(),
180174
!show_segment_entrypoint && Some((sidx, Some(cidx))) == entrypoint,
181175
false,
182176
self.is_early_end_of_traversal(sidx, cidx),

crates/but-graph/src/init/walk.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,6 @@ pub fn find(
451451
details: Some(CommitDetails {
452452
message: message.context("Every valid commit must have a message")?,
453453
author: author.context("Every valid commit must have an author signature")?,
454-
// TODO: make it clear that this is optionally computed as well, maybe `Option<bool>`?
455-
has_conflicts: false,
456454
}),
457455
})
458456
}

crates/but-graph/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub use segment::{Commit, CommitDetails, CommitFlags, Segment, SegmentMetadata};
4343
mod api;
4444
/// Produce a graph from a Git repository.
4545
pub mod init;
46+
pub mod projection;
4647

4748
mod ref_metadata_legacy;
4849
pub use ref_metadata_legacy::{VirtualBranchesTomlMetadata, is_workspace_ref_name};
@@ -80,6 +81,9 @@ pub struct EntryPoint<'graph> {
8081
/// The segment that served starting point for the traversal into this graph.
8182
pub segment: &'graph Segment,
8283
/// If present, the commit that started the traversal in the `segment`.
84+
///
85+
/// It's usually the first commit of the segment due to the way we split segments, and even though
86+
/// downstream code relies on this properly, the graph itself does not.
8387
pub commit: Option<&'graph Commit>,
8488
}
8589

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//! A way to represent the graph in a simplified (but more usable) form.
2+
//!
3+
//! This is the current default way of GitButler to perceive its world, but most inexpensively generated to stay
4+
//! close to the source of truth, [The Graph](crate::Graph).
5+
//!
6+
//! These types are not for direct consumption, but should be processed further for consumption by the user.
7+
8+
/// Types related to the stack representation for graphs.
9+
///
10+
/// Note that these are always a simplification, degenerating information, while maintaining a link back to the graph.
11+
mod stack;
12+
pub use stack::{Stack, StackCommit, StackCommitDebugFlags, StackCommitFlags, StackSegment};
13+
14+
mod workspace;
15+
pub use workspace::{HeadLocation, Target, Workspace};

0 commit comments

Comments
 (0)