Skip to content

Commit 219c4d7

Browse files
committed
the final stretch to make GitLab work
It doesn't currently manage to traverse enough commits to connect a far-away integration branch with the entrypoint, simply master.
1 parent 53f9577 commit 219c4d7

File tree

7 files changed

+778
-266
lines changed

7 files changed

+778
-266
lines changed

crates/but-graph/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ publish = false
88

99
[lib]
1010
doctest = false
11-
test = false
11+
test = true
1212

1313
[dependencies]
1414
but-core.workspace = true

crates/but-graph/src/api.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,7 @@ impl Graph {
232232
.tip_segments()
233233
.map(|s| {
234234
let s = &self[s];
235-
(
236-
s.ref_name.as_ref().map(|rn| rn.clone()),
237-
s.id,
238-
s.flags_of_first_commit(),
239-
)
235+
(s.ref_name.clone(), s.id, s.flags_of_first_commit())
240236
})
241237
.collect();
242238
*segments_at_bottom = self.base_segments().count();

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

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,8 @@ pub struct Options {
3939
/// is nothing interesting left to traverse.
4040
///
4141
/// Also note: This is a hint and not an exact measure, and it's always possible to receive a more commits
42-
/// for various reasons, for instance the need to let remote branches find their local brnach independently
42+
/// for various reasons, for instance the need to let remote branches find their local branch independently
4343
/// of the limit.
44-
///
45-
/// ### Tip Configuration
46-
///
47-
/// * HEAD - uses the limit
48-
/// * workspaces with target branch - no limit, but auto-stop if workspace is exhausted as everything is integrated.
49-
/// - The target branch: no limit
50-
/// - Integrated workspace branches: use the limit
51-
/// * workspace without target branch - uses the limit
52-
/// * remotes tracking branches - use the limit, but only once they have reached a local branch.
5344
pub commits_limit_hint: Option<usize>,
5445
/// A list of the last commits of partial segments previously returned that reset the amount of available
5546
/// commits to traverse back to `commit_limit_hint`.
@@ -107,7 +98,7 @@ impl Graph {
10798
gix::head::Kind::Unborn(ref_name) => {
10899
let mut graph = Graph::default();
109100
graph.insert_root(branch_segment_from_name_and_meta(
110-
Some(ref_name),
101+
Some((ref_name, None)),
111102
meta,
112103
None,
113104
)?);
@@ -165,6 +156,8 @@ impl Graph {
165156
/// * The traversal is cut short when there is only tips which are integrated, even though named segments that are
166157
/// supposed to be in the workspace will be fully traversed (implying they will stop at the first anon segment
167158
/// as will happen at merge commits).
159+
/// * The traversal is always as long as it needs to be to fully reconcile possibly disjoint branches, despite
160+
/// this sometimes costing some time when the remote is far ahead in a huge repository.
168161
#[instrument(skip(meta, ref_name), err(Debug))]
169162
pub fn from_commit_traversal(
170163
tip: gix::Id<'_>,
@@ -177,10 +170,10 @@ impl Graph {
177170
hard_limit,
178171
}: Options,
179172
) -> anyhow::Result<Self> {
180-
let limit = Limit::from(limit);
173+
let repo = tip.repo;
174+
let max_limit = Limit::new(limit);
181175
// TODO: also traverse (outside)-branches that ought to be in the workspace. That way we have the desired ones
182176
// automatically and just have to find a way to prune the undesired ones.
183-
let repo = tip.repo;
184177
let ref_name = ref_name.into();
185178
if ref_name
186179
.as_ref()
@@ -205,13 +198,15 @@ impl Graph {
205198
None
206199
}),
207200
)?;
208-
let (workspaces, target_refs, desired_refs) =
201+
let (workspaces, target_refs) =
209202
obtain_workspace_infos(repo, ref_name.as_ref().map(|rn| rn.as_ref()), meta)?;
210203
let mut seen = gix::revwalk::graph::IdMap::<SegmentIndex>::default();
211204
let mut goals = Goals::default();
212-
let tip_limit_with_goal = limit.with_goal(tip.detach(), &mut goals);
213205
// The tip transports itself.
214-
let tip_flags = CommitFlags::NotInRemote | tip_limit_with_goal.goal;
206+
let tip_flags = CommitFlags::NotInRemote
207+
| goals
208+
.flag_for(tip.detach())
209+
.expect("we more than one bitflags for this");
215210

216211
let target_symbolic_remote_names = {
217212
let remote_names = repo.remote_names();
@@ -233,15 +228,15 @@ impl Graph {
233228
.any(|(_, wsrn, _)| Some(wsrn) == ref_name.as_ref())
234229
{
235230
let current = graph.insert_root(branch_segment_from_name_and_meta(
236-
ref_name.clone(),
231+
ref_name.clone().map(|rn| (rn, None)),
237232
meta,
238233
Some((&refs_by_id, tip.detach())),
239234
)?);
240235
if next.push_back_exhausted((
241236
tip.detach(),
242237
tip_flags,
243238
Instruction::CollectCommit { into: current },
244-
limit,
239+
max_limit,
245240
)) {
246241
return Ok(graph.with_hard_limit());
247242
}
@@ -261,12 +256,16 @@ impl Graph {
261256
.map(|tid| (trn.clone(), tid))
262257
});
263258

264-
let (ws_flags, ws_limit) = if Some(&ws_ref) == ref_name.as_ref() {
265-
(tip_flags, limit)
259+
let (ws_extra_flags, ws_limit) = if Some(&ws_ref) == ref_name.as_ref() {
260+
(tip_flags, max_limit)
266261
} else {
267-
(CommitFlags::empty(), tip_limit_with_goal)
262+
(
263+
CommitFlags::empty(),
264+
max_limit.with_indirect_goal(tip.detach(), &mut goals),
265+
)
268266
};
269-
let mut ws_segment = branch_segment_from_name_and_meta(Some(ws_ref), meta, None)?;
267+
let mut ws_segment =
268+
branch_segment_from_name_and_meta(Some((ws_ref, None)), meta, None)?;
270269
// The limits for the target ref and the worktree ref are synced so they can always find each other,
271270
// while being able to stop when the entrypoint is included.
272271
ws_segment.metadata = Some(SegmentMetadata::Workspace(workspace_info));
@@ -279,15 +278,15 @@ impl Graph {
279278
// We only allow workspaces that are not remote, and that are not target refs.
280279
// Theoretically they can still cross-reference each other, but then we'd simply ignore
281280
// their status for now.
282-
CommitFlags::NotInRemote | ws_flags,
281+
CommitFlags::NotInRemote | ws_extra_flags,
283282
Instruction::CollectCommit { into: ws_segment },
284283
ws_limit,
285284
)) {
286285
return Ok(graph.with_hard_limit());
287286
}
288287
if let Some((target_ref, target_ref_id)) = target {
289288
let target_segment = graph.insert_root(branch_segment_from_name_and_meta(
290-
Some(target_ref),
289+
Some((target_ref, None)),
291290
meta,
292291
None,
293292
)?);
@@ -297,17 +296,18 @@ impl Graph {
297296
Instruction::CollectCommit {
298297
into: target_segment,
299298
},
300-
tip_limit_with_goal,
299+
// Once the goal was found, be done immediately,
300+
// we are not interested in these.
301+
max_limit
302+
.with_indirect_goal(tip.detach(), &mut goals)
303+
.without_allowance(),
301304
)) {
302305
return Ok(graph.with_hard_limit());
303306
}
304307
}
305308
}
306309

307310
max_commits_recharge_location.sort();
308-
// Set max-limit so that we compensate for the way this is counted.
309-
// let max_limit = limit.incremented();
310-
let max_limit = limit;
311311
while let Some((id, mut propagated_flags, instruction, mut limit)) = next.pop_front() {
312312
if max_commits_recharge_location.binary_search(&id).is_ok() {
313313
limit.set_but_keep_goal(max_limit);
@@ -330,7 +330,6 @@ impl Graph {
330330
&mut seen,
331331
&mut next,
332332
id,
333-
limit,
334333
propagated_flags,
335334
src_sidx,
336335
)?;
@@ -359,7 +358,6 @@ impl Graph {
359358
&mut seen,
360359
&mut next,
361360
id,
362-
limit,
363361
propagated_flags,
364362
parent_above,
365363
)?;
@@ -432,7 +430,7 @@ impl Graph {
432430
}
433431
}
434432

435-
prune_integrated_tips(&mut graph, &mut next, &desired_refs, max_limit);
433+
prune_integrated_tips(&mut graph, &mut next);
436434
}
437435

438436
graph.post_processed(
@@ -459,15 +457,6 @@ struct Queue {
459457
max: Option<usize>,
460458
}
461459

462-
#[derive(Debug, Copy, Clone)]
463-
struct Limit {
464-
inner: Option<usize>,
465-
/// The commit we want to see to be able to assume normal limits. Until then there is no limit.
466-
/// This is represented by bitflag, one for each goal.
467-
/// The flag is empty if no goal is set.
468-
goal: CommitFlags,
469-
}
470-
471460
/// A set of commits to keep track of in bitflags.
472461
#[derive(Default)]
473462
struct Goals(Vec<gix::ObjectId>);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ fn create_connected_multi_segment(
358358
})
359359
{
360360
let ref_name = &refs[ref_idx];
361-
let new_segment = branch_segment_from_name_and_meta(Some(ref_name.clone()), meta, None)?;
361+
let new_segment =
362+
branch_segment_from_name_and_meta(Some((ref_name.clone(), None)), meta, None)?;
362363
let above_commit_idx = {
363364
let s = &graph[above_idx];
364365
let cidx = s.commit_index_of(commit.id);

0 commit comments

Comments
 (0)