Skip to content

Commit f396b7c

Browse files
authored
Merge pull request #10468 from Byron/other-fix
entrypoint-consistency
2 parents 520158b + d509594 commit f396b7c

File tree

18 files changed

+522
-236
lines changed

18 files changed

+522
-236
lines changed

Cargo.lock

Lines changed: 55 additions & 55 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/but-graph/src/api.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,24 @@ use std::ops::{Deref, Index, IndexMut};
1111
/// Mutation
1212
impl Graph {
1313
/// Insert `segment` to the graph so that it's not connected to any other segment, and return its index.
14-
pub fn insert_root(&mut self, segment: Segment) -> SegmentIndex {
15-
let index = self.inner.add_node(segment);
16-
self.inner[index].id = index;
14+
///
15+
/// Note that as a side effect, the [entrypoint](Self::lookup_entrypoint()) will also be set if it's not
16+
/// set yet.
17+
pub fn insert_segment_set_entrypoint(&mut self, segment: Segment) -> SegmentIndex {
18+
let index = self.insert_segment(segment);
1719
if self.entrypoint.is_none() {
1820
self.entrypoint = Some((index, None))
1921
}
2022
index
2123
}
2224

25+
/// Insert `segment` to the graph so that it's not connected to any other segment, and return its index.
26+
pub fn insert_segment(&mut self, segment: Segment) -> SegmentIndex {
27+
let index = self.inner.add_node(segment);
28+
self.inner[index].id = index;
29+
index
30+
}
31+
2332
/// Put `dst` on top of `src`, connecting it from the `src_commit` specifically,
2433
/// an index valid for [`Segment::commits_unique_from_tip`] in `src` to the commit at `dst_commit` in `dst`.
2534
///

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

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl Graph {
145145
// It's OK to default-initialise this here as overlays are only used when redoing
146146
// the traversal.
147147
let (_repo, meta, _entrypoint) = Overlay::default().into_parts(repo, meta);
148-
graph.insert_root(branch_segment_from_name_and_meta(
148+
graph.insert_segment_set_entrypoint(branch_segment_from_name_and_meta(
149149
Some((ref_name, None)),
150150
&meta,
151151
None,
@@ -242,8 +242,10 @@ impl Graph {
242242
meta: &OverlayMetadata<'_, T>,
243243
options: Options,
244244
) -> anyhow::Result<Self> {
245+
let ref_name = ref_name.into();
245246
let mut graph = Graph {
246247
options: options.clone(),
248+
entrypoint_ref: ref_name.clone(),
247249
..Graph::default()
248250
};
249251
let Options {
@@ -256,7 +258,6 @@ impl Graph {
256258
} = options;
257259

258260
let max_limit = Limit::new(limit);
259-
let ref_name = ref_name.into();
260261
if ref_name
261262
.as_ref()
262263
.is_some_and(|name| name.category() == Some(Category::RemoteBranch))
@@ -271,6 +272,8 @@ impl Graph {
271272

272273
let configured_remote_tracking_branches =
273274
remotes::configured_remote_tracking_branches(repo)?;
275+
let (workspaces, target_refs) =
276+
obtain_workspace_infos(repo, ref_name.as_ref().map(|rn| rn.as_ref()), meta)?;
274277
let refs_by_id = repo.collect_ref_mapping_by_prefix(
275278
[
276279
"refs/heads/",
@@ -287,9 +290,11 @@ impl Graph {
287290
} else {
288291
None
289292
}),
293+
&workspaces
294+
.iter()
295+
.map(|(_, ref_name, _)| ref_name.as_ref())
296+
.collect::<Vec<_>>(),
290297
)?;
291-
let (workspaces, target_refs) =
292-
obtain_workspace_infos(repo, ref_name.as_ref().map(|rn| rn.as_ref()), meta)?;
293298
let mut seen = gix::revwalk::graph::IdMap::<SegmentIndex>::default();
294299
let mut goals = Goals::default();
295300
// The tip transports itself.
@@ -332,8 +337,8 @@ impl Graph {
332337
dangerously_skip_postprocessing_for_debugging,
333338
};
334339
if tip_is_not_workspace_commit {
335-
let current = graph.insert_root(branch_segment_from_name_and_meta(
336-
ref_name.clone().map(|rn| (rn, None)),
340+
let current = graph.insert_segment_set_entrypoint(branch_segment_from_name_and_meta(
341+
None,
337342
meta,
338343
Some((&ctx.refs_by_id, tip)),
339344
)?);
@@ -352,10 +357,7 @@ impl Graph {
352357
let target = ws_meta.target_ref.as_ref().and_then(|trn| {
353358
let tid = try_refname_to_id(repo, trn.as_ref())
354359
.map_err(|err| {
355-
tracing::warn!(
356-
"Ignoring non-existing target branch {trn}: {err}",
357-
trn = trn.as_bstr()
358-
);
360+
tracing::warn!("Ignoring non-existing target branch {trn}: {err}");
359361
err
360362
})
361363
.ok()??;
@@ -386,7 +388,16 @@ impl Graph {
386388
// The limits for the target ref and the worktree ref are synced so they can always find each other,
387389
// while being able to stop when the entrypoint is included.
388390
ws_segment.metadata = Some(SegmentMetadata::Workspace(ws_meta));
389-
let ws_segment = graph.insert_root(ws_segment);
391+
let ws_segment = graph.insert_segment(ws_segment);
392+
if graph.entrypoint.is_none()
393+
&& graph
394+
.entrypoint_ref
395+
.as_ref()
396+
.zip(ref_name.as_ref())
397+
.is_some_and(|(a, b)| a == b)
398+
{
399+
graph.entrypoint = Some((ws_segment, None));
400+
}
390401
// As workspaces typically have integration branches which can help us to stop the traversal,
391402
// pick these up first.
392403
_ = next.push_front_exhausted((
@@ -401,45 +412,45 @@ impl Graph {
401412
));
402413

403414
if let Some((target_ref, target_ref_id, local_tip_info)) = target {
404-
let target_segment = graph.insert_root(branch_segment_from_name_and_meta(
415+
let target_segment = graph.insert_segment(branch_segment_from_name_and_meta(
405416
Some((target_ref, None)),
406417
meta,
407418
None,
408419
)?);
409-
let (local_sidx, local_goal) = if let Some((local_ref_name, target_local_tip)) =
410-
local_tip_info
411-
{
412-
let local_sidx = graph.insert_root(branch_segment_from_name_and_meta_sibling(
413-
None,
414-
Some(target_segment),
415-
meta,
416-
Some((&ctx.refs_by_id, target_local_tip)),
417-
)?);
418-
// We use auto-naming based on ambiguity - if the name ends up something else,
419-
// remove the nodes sibling link.
420-
let has_sibling_link = {
421-
let s = &mut graph[local_sidx];
422-
if s.ref_name.as_ref().is_none_or(|rn| rn != &local_ref_name) {
423-
s.sibling_segment_id = None;
424-
false
425-
} else {
426-
true
427-
}
420+
let (local_sidx, local_goal) =
421+
if let Some((local_ref_name, target_local_tip)) = local_tip_info {
422+
let local_sidx =
423+
graph.insert_segment(branch_segment_from_name_and_meta_sibling(
424+
None,
425+
Some(target_segment),
426+
meta,
427+
Some((&ctx.refs_by_id, target_local_tip)),
428+
)?);
429+
// We use auto-naming based on ambiguity - if the name ends up something else,
430+
// remove the nodes sibling link.
431+
let has_sibling_link = {
432+
let s = &mut graph[local_sidx];
433+
if s.ref_name.as_ref().is_none_or(|rn| rn != &local_ref_name) {
434+
s.sibling_segment_id = None;
435+
false
436+
} else {
437+
true
438+
}
439+
};
440+
let goal = goals.flag_for(target_local_tip).unwrap_or_default();
441+
_ = next.push_front_exhausted((
442+
target_local_tip,
443+
CommitFlags::NotInRemote | goal,
444+
Instruction::CollectCommit { into: local_sidx },
445+
max_limit
446+
.with_indirect_goal(tip, &mut goals)
447+
.without_allowance(),
448+
));
449+
next.add_goal_to(tip, goal);
450+
(has_sibling_link.then_some(local_sidx), goal)
451+
} else {
452+
(None, CommitFlags::empty())
428453
};
429-
let goal = goals.flag_for(target_local_tip).unwrap_or_default();
430-
_ = next.push_front_exhausted((
431-
target_local_tip,
432-
CommitFlags::NotInRemote | goal,
433-
Instruction::CollectCommit { into: local_sidx },
434-
max_limit
435-
.with_indirect_goal(tip, &mut goals)
436-
.without_allowance(),
437-
));
438-
next.add_goal_to(tip, goal);
439-
(has_sibling_link.then_some(local_sidx), goal)
440-
} else {
441-
(None, CommitFlags::empty())
442-
};
443454
_ = next.push_front_exhausted((
444455
target_ref_id,
445456
CommitFlags::Integrated,
@@ -466,7 +477,7 @@ impl Graph {
466477
// have to adjust the existing queue item.
467478
existing_segment
468479
} else {
469-
let extra_target_sidx = graph.insert_root(branch_segment_from_name_and_meta(
480+
let extra_target_sidx = graph.insert_segment(branch_segment_from_name_and_meta(
470481
None,
471482
meta,
472483
Some((&ctx.refs_by_id, extra_target)),
@@ -515,7 +526,7 @@ impl Graph {
515526
meta,
516527
Some((&ctx.refs_by_id, segment_tip.detach())),
517528
)?;
518-
let segment = graph.insert_root(segment);
529+
let segment = graph.insert_segment(segment);
519530
_ = next.push_back_exhausted((
520531
segment_tip.detach(),
521532
CommitFlags::NotInRemote,

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::init::walk::RefsById;
22
use crate::init::{Entrypoint, Overlay};
3-
use crate::is_workspace_ref_name;
43
use but_core::{RefMetadata, ref_metadata};
54
use gix::prelude::ReferenceExt;
65
use std::borrow::Cow;
@@ -173,15 +172,17 @@ impl<'repo> OverlayRepo<'repo> {
173172
.upstream_branch_and_remote_for_tracking_branch(name)?)
174173
}
175174

176-
// Create a mapping of all heads to the object ids they point to.
175+
/// Create a mapping of all heads to the object ids they point to.
176+
/// `workspace_ref_names` is the names of all known workspace references.
177177
pub fn collect_ref_mapping_by_prefix<'a>(
178178
&self,
179179
prefixes: impl Iterator<Item = &'a str>,
180+
workspace_ref_names: &[&gix::refs::FullNameRef],
180181
) -> anyhow::Result<RefsById> {
181182
let mut seen = (!self.nonoverriding_references.is_empty()).then(BTreeSet::new);
182183
let mut ref_filter =
183184
|r: gix::Reference<'_>| -> Option<(gix::ObjectId, gix::refs::FullName)> {
184-
if is_workspace_ref_name(r.name()) {
185+
if workspace_ref_names.contains(&r.name()) {
185186
return None;
186187
}
187188
let id = r.try_id()?;

0 commit comments

Comments
 (0)