Skip to content

Commit 5a84f11

Browse files
committed
SQUASH ME
1 parent a21d8d0 commit 5a84f11

File tree

8 files changed

+102
-55
lines changed

8 files changed

+102
-55
lines changed

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub struct Overlay {
3636
overriding_references: Vec<gix::refs::Reference>,
3737
meta_branches: Vec<(gix::refs::FullName, ref_metadata::Branch)>,
3838
workspace: Option<(gix::refs::FullName, ref_metadata::Workspace)>,
39+
skip_out_of_workspace_stack_tracking_once: bool,
3940
}
4041

4142
pub(super) type PetGraph = petgraph::stable_graph::StableGraph<Segment, Edge>;
@@ -81,6 +82,12 @@ pub struct Options {
8182
/// the workspace.
8283
/// Typically, it's a past position of an existing target, or a target chosen by the user.
8384
pub extra_target_commit_id: Option<gix::ObjectId>,
85+
/// If `true`, we will not be able to find stacks that have advanced outside the workspace, along with their out-of-workspace commits.
86+
///
87+
/// This is useful if you want to check for the presence of stacks in the workspace, for the purpose of adding them if they are not.
88+
/// Otherwise, if `false`, otherwise anonymous segments might appear like they are part of a stack, one that is known in the workspace
89+
/// metadata and reachable towards the descendants of these anonymous stacks.
90+
pub skip_out_of_workspace_stack_tracking: bool,
8491
/// Enabling this will prevent the postprocessing step to run which is what makes the graph useful through clean-up
8592
/// and to make it more amenable to a workspace project.
8693
///
@@ -155,7 +162,8 @@ impl Graph {
155162
let mut graph = Graph::default();
156163
// It's OK to default-initialise this here as overlays are only used when redoing
157164
// the traversal.
158-
let (_repo, meta, _entrypoint) = Overlay::default().into_parts(repo, meta);
165+
let (_repo, meta, _entrypoint, _skip_stack_tracking) =
166+
Overlay::default().into_parts(repo, meta);
159167
let wt_by_branch = {
160168
// Assume linked worktrees are never unborn!
161169
let mut m = BTreeMap::new();
@@ -249,7 +257,8 @@ impl Graph {
249257
meta: &impl RefMetadata,
250258
options: Options,
251259
) -> anyhow::Result<Self> {
252-
let (repo, meta, _entrypoint) = Overlay::default().into_parts(tip.repo, meta);
260+
let (repo, meta, _entrypoint, _skip_stack_tracking) =
261+
Overlay::default().into_parts(tip.repo, meta);
253262
Graph::from_commit_traversal_inner(tip.detach(), &repo, ref_name.into(), &meta, options)
254263
}
255264

@@ -277,6 +286,7 @@ impl Graph {
277286
commits_limit_hint: limit,
278287
commits_limit_recharge_location: mut max_commits_recharge_location,
279288
hard_limit,
289+
skip_out_of_workspace_stack_tracking: _,
280290
dangerously_skip_postprocessing_for_debugging,
281291
} = options;
282292

@@ -752,7 +762,8 @@ impl Graph {
752762
meta: &impl RefMetadata,
753763
overlay: Overlay,
754764
) -> anyhow::Result<Self> {
755-
let (repo, meta, entrypoint) = overlay.into_parts(repo, meta);
765+
let (repo, meta, entrypoint, skip_out_of_workspace_stack_tracking_once) =
766+
overlay.into_parts(repo, meta);
756767
let (tip, ref_name) = match entrypoint {
757768
Some(t) => t,
758769
None => {
@@ -768,7 +779,15 @@ impl Graph {
768779
(tip, ref_name)
769780
}
770781
};
771-
Graph::from_commit_traversal_inner(tip, &repo, ref_name, &meta, self.options.clone())
782+
let mut opts = self.options.clone();
783+
if skip_out_of_workspace_stack_tracking_once {
784+
opts.skip_out_of_workspace_stack_tracking = true;
785+
}
786+
let mut graph = Graph::from_commit_traversal_inner(tip, &repo, ref_name, &meta, opts)?;
787+
if skip_out_of_workspace_stack_tracking_once {
788+
graph.options.skip_out_of_workspace_stack_tracking = false;
789+
}
790+
Ok(graph)
772791
}
773792

774793
/// Like [`Self::redo_traversal_with_overlay()`], but replaces this instance, without overlay, and returns

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ impl Overlay {
2727
self
2828
}
2929

30+
/// Call this and will not be able to find stacks that have advanced outside the workspace, along with their out-of-workspace commits
31+
/// just this once.
32+
///
33+
/// This is useful if you want to check for the presence of stacks in the workspace, for the purpose of adding them if they are not.
34+
/// Since this may be undesirable unless it's used in specific situations, it's turned on only once when used here.
35+
pub fn without_stack_tracking_once(mut self) -> Self {
36+
self.skip_out_of_workspace_stack_tracking_once = true;
37+
self
38+
}
39+
3040
/// Override the starting position of the traversal by setting it to `id`,
3141
/// and optionally, by providing the `ref_name` that points to `id`.
3242
pub fn with_entrypoint(
@@ -71,7 +81,12 @@ impl Overlay {
7181
self,
7282
repo: &'repo gix::Repository,
7383
meta: &'meta T,
74-
) -> (OverlayRepo<'repo>, OverlayMetadata<'meta, T>, Entrypoint)
84+
) -> (
85+
OverlayRepo<'repo>,
86+
OverlayMetadata<'meta, T>,
87+
Entrypoint,
88+
bool,
89+
)
7590
where
7691
T: RefMetadata,
7792
{
@@ -81,6 +96,7 @@ impl Overlay {
8196
meta_branches,
8297
workspace,
8398
entrypoint,
99+
skip_out_of_workspace_stack_tracking_once: skip_out_of_workspace_stack_tracking,
84100
} = self;
85101
(
86102
OverlayRepo {
@@ -100,6 +116,7 @@ impl Overlay {
100116
workspace,
101117
},
102118
entrypoint,
119+
skip_out_of_workspace_stack_tracking,
103120
)
104121
}
105122
}

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

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -848,51 +848,53 @@ impl Graph {
848848
}
849849

850850
// Setup sibling IDs for all unnamed segments with a known segment ref in its future.
851-
for sidx in ws_stacks.iter().flat_map(|s| {
852-
s.segments
853-
.iter()
854-
.flat_map(|s| s.commits_by_segment.iter().map(|(sidx, _)| *sidx))
855-
}) {
856-
// The workspace might be stale by now as we delete empty segments.
857-
// Thus be careful, and ignore non-existing ones - after all our workspace
858-
// is temporary, nothing to worry about.
859-
let Some(s) = self.inner.node_weight(sidx) else {
860-
continue;
861-
};
862-
if s.ref_info.is_some() || s.sibling_segment_id.is_some() {
863-
continue;
864-
}
865-
866-
let num_outgoing = self
867-
.inner
868-
.neighbors_directed(sidx, Direction::Incoming)
869-
.count();
870-
if num_outgoing < 2 {
871-
continue;
872-
}
851+
if !self.options.skip_out_of_workspace_stack_tracking {
852+
for sidx in ws_stacks.iter().flat_map(|s| {
853+
s.segments
854+
.iter()
855+
.flat_map(|s| s.commits_by_segment.iter().map(|(sidx, _)| *sidx))
856+
}) {
857+
// The workspace might be stale by now as we delete empty segments.
858+
// Thus, be careful, and ignore non-existing ones - after all our workspace
859+
// is temporary, nothing to worry about.
860+
let Some(s) = self.inner.node_weight(sidx) else {
861+
continue;
862+
};
863+
if s.ref_info.is_some() || s.sibling_segment_id.is_some() {
864+
continue;
865+
}
873866

874-
let mut named_segment_id = None;
875-
self.visit_all_segments_excluding_start_until(sidx, Direction::Incoming, |s| {
876-
let prune = true;
877-
if named_segment_id.is_some()
878-
|| s.commits
879-
.first()
880-
.is_some_and(|c| c.flags.contains(CommitFlags::InWorkspace))
881-
{
882-
return prune;
867+
let num_outgoing = self
868+
.inner
869+
.neighbors_directed(sidx, Direction::Incoming)
870+
.count();
871+
if num_outgoing < 2 {
872+
continue;
883873
}
884874

885-
s.ref_info.as_ref().is_some_and(|ri| {
886-
let is_known_to_workspace = ws_data
887-
.stacks(AppliedAndUnapplied)
888-
.any(|s| s.branches.iter().any(|b| b.ref_name == ri.ref_name));
889-
if is_known_to_workspace {
890-
named_segment_id = Some(s.id);
875+
let mut named_segment_id = None;
876+
self.visit_all_segments_excluding_start_until(sidx, Direction::Incoming, |s| {
877+
let prune = true;
878+
if named_segment_id.is_some()
879+
|| s.commits
880+
.first()
881+
.is_some_and(|c| c.flags.contains(CommitFlags::InWorkspace))
882+
{
883+
return prune;
891884
}
892-
is_known_to_workspace
893-
})
894-
});
895-
self[sidx].sibling_segment_id = named_segment_id;
885+
886+
s.ref_info.as_ref().is_some_and(|ri| {
887+
let is_known_to_workspace = ws_data
888+
.stacks(AppliedAndUnapplied)
889+
.any(|s| s.branches.iter().any(|b| b.ref_name == ri.ref_name));
890+
if is_known_to_workspace {
891+
named_segment_id = Some(s.id);
892+
}
893+
is_known_to_workspace
894+
})
895+
});
896+
self[sidx].sibling_segment_id = named_segment_id;
897+
}
896898
}
897899

898900
// The named-segment check is needed as we don't want to double-split unnamed segments.

crates/but-graph/src/projection/stack.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ impl std::fmt::Debug for StackSegment {
245245
f.debug_struct(&format!("StackSegment({})", self.debug_string()))
246246
.field("commits", &self.commits)
247247
.field("commits_on_remote", &self.commits_on_remote)
248+
.field("commits_outside", &self.commits_outside)
248249
.finish()
249250
}
250251
}
@@ -258,7 +259,7 @@ impl StackSegment {
258259
/// is an unambiguous ref pointing to a commit, or when it splits a segment by incoming connection.
259260
///
260261
/// `graph` is used to look up the remote segment and find its commits.
261-
pub fn from_graph_segments(
262+
pub(crate) fn from_graph_segments(
262263
segments: &[&crate::Segment],
263264
graph: &Graph,
264265
) -> anyhow::Result<Self> {

crates/but-graph/tests/graph/init/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn unborn() -> anyhow::Result<()> {
4343
commits_limit_recharge_location: [],
4444
hard_limit: None,
4545
extra_target_commit_id: None,
46+
skip_out_of_workspace_stack_tracking: false,
4647
dangerously_skip_postprocessing_for_debugging: false,
4748
},
4849
}
@@ -148,6 +149,7 @@ fn detached() -> anyhow::Result<()> {
148149
commits_limit_recharge_location: [],
149150
hard_limit: None,
150151
extra_target_commit_id: None,
152+
skip_out_of_workspace_stack_tracking: false,
151153
dangerously_skip_postprocessing_for_debugging: false,
152154
},
153155
}

crates/but-graph/tests/graph/init/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ pub fn standard_options() -> but_graph::init::Options {
151151
commits_limit_recharge_location: vec![],
152152
hard_limit: None,
153153
extra_target_commit_id: None,
154+
skip_out_of_workspace_stack_tracking: false,
154155
dangerously_skip_postprocessing_for_debugging: false,
155156
}
156157
}

crates/but-workspace/src/branch/apply.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ pub(crate) mod function {
388388
.redo_traversal_with_overlay(repo, meta, overlay.clone())?;
389389

390390
let workspace = graph.to_workspace()?;
391+
dbg!(&graph);
392+
dbg!(&workspace);
391393
let all_applied_branches_are_already_visible = branches_to_apply
392394
.iter()
393395
.all(|rn| workspace.refname_is_segment(rn));

crates/but-workspace/tests/workspace/branch/apply_unapply_commit_uncommit.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -619,8 +619,8 @@ fn new_workspace_exists_elsewhere_and_to_be_applied_branch_exists_there() -> any
619619
}
620620

621621
#[test]
622-
fn apply_multiple_without_target_or_metadata() -> anyhow::Result<()> {
623-
let (_tmp, graph, repo, mut meta, _description) =
622+
fn apply_multiple_without_target_or_metadata_or_base() -> anyhow::Result<()> {
623+
let (_tmp, mut graph, repo, mut meta, _description) =
624624
named_writable_scenario_with_description_and_graph("one-fork", |meta| {
625625
meta.data_mut().default_target = None;
626626
})?;
@@ -634,6 +634,8 @@ fn apply_multiple_without_target_or_metadata() -> anyhow::Result<()> {
634634
* e31e6ca (origin/main, origin/HEAD) add init
635635
");
636636

637+
graph.options.extra_target_commit_id = None;
638+
let graph = graph.redo_traversal_with_overlay(&repo, &meta, Overlay::default())?;
637639
let ws = graph.to_workspace()?;
638640
insta::assert_snapshot!(graph_workspace(&ws), @r"
639641
⌂:0:main[🌳] <> ✓!
@@ -660,9 +662,9 @@ fn apply_multiple_without_target_or_metadata() -> anyhow::Result<()> {
660662
├── ≡📙:2:A on e31e6ca {41}
661663
│ └── 📙:2:A
662664
│ └── ·bf53300 (🏘️)
663-
└── ≡📙:4:main on e31e6ca {1a5}
664-
└── 📙:4:main
665-
└── ·b1540e5 (🏘️|✓)
665+
└── ≡📙:1:main on e31e6ca {1a5}
666+
└── 📙:1:main
667+
└── ·b1540e5 (🏘️)
666668
");
667669

668670
insta::assert_snapshot!(visualize_commit_graph_all(&repo)?, @r"
@@ -701,9 +703,9 @@ fn apply_multiple_without_target_or_metadata() -> anyhow::Result<()> {
701703
├── ≡📙:2:A on e31e6ca {41}
702704
│ └── 📙:2:A
703705
│ └── ·bf53300 (🏘️)
704-
└── ≡📙:5:main on e31e6ca {1a5}
705-
└── 📙:5:main
706-
└── ·b1540e5 (🏘️|✓)
706+
└── ≡📙:1:main on e31e6ca {1a5}
707+
└── 📙:1:main
708+
└── ·b1540e5 (🏘️)
707709
");
708710

709711
insta::assert_snapshot!(visualize_commit_graph_all(&repo)?, @r"
@@ -1890,6 +1892,7 @@ mod utils {
18901892
commits_limit_recharge_location: vec![],
18911893
hard_limit: None,
18921894
extra_target_commit_id: None,
1895+
skip_out_of_workspace_stack_tracking: false,
18931896
dangerously_skip_postprocessing_for_debugging: false,
18941897
}
18951898
}

0 commit comments

Comments
 (0)