@@ -39,17 +39,8 @@ pub struct Options {
39
39
/// is nothing interesting left to traverse.
40
40
///
41
41
/// 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
43
43
/// 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.
53
44
pub commits_limit_hint : Option < usize > ,
54
45
/// A list of the last commits of partial segments previously returned that reset the amount of available
55
46
/// commits to traverse back to `commit_limit_hint`.
@@ -107,7 +98,7 @@ impl Graph {
107
98
gix:: head:: Kind :: Unborn ( ref_name) => {
108
99
let mut graph = Graph :: default ( ) ;
109
100
graph. insert_root ( branch_segment_from_name_and_meta (
110
- Some ( ref_name) ,
101
+ Some ( ( ref_name, None ) ) ,
111
102
meta,
112
103
None ,
113
104
) ?) ;
@@ -165,6 +156,8 @@ impl Graph {
165
156
/// * The traversal is cut short when there is only tips which are integrated, even though named segments that are
166
157
/// supposed to be in the workspace will be fully traversed (implying they will stop at the first anon segment
167
158
/// 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.
168
161
#[ instrument( skip( meta, ref_name) , err( Debug ) ) ]
169
162
pub fn from_commit_traversal (
170
163
tip : gix:: Id < ' _ > ,
@@ -177,10 +170,10 @@ impl Graph {
177
170
hard_limit,
178
171
} : Options ,
179
172
) -> anyhow:: Result < Self > {
180
- let limit = Limit :: from ( limit) ;
173
+ let repo = tip. repo ;
174
+ let max_limit = Limit :: new ( limit) ;
181
175
// TODO: also traverse (outside)-branches that ought to be in the workspace. That way we have the desired ones
182
176
// automatically and just have to find a way to prune the undesired ones.
183
- let repo = tip. repo ;
184
177
let ref_name = ref_name. into ( ) ;
185
178
if ref_name
186
179
. as_ref ( )
@@ -205,13 +198,15 @@ impl Graph {
205
198
None
206
199
} ) ,
207
200
) ?;
208
- let ( workspaces, target_refs, desired_refs ) =
201
+ let ( workspaces, target_refs) =
209
202
obtain_workspace_infos ( repo, ref_name. as_ref ( ) . map ( |rn| rn. as_ref ( ) ) , meta) ?;
210
203
let mut seen = gix:: revwalk:: graph:: IdMap :: < SegmentIndex > :: default ( ) ;
211
204
let mut goals = Goals :: default ( ) ;
212
- let tip_limit_with_goal = limit. with_goal ( tip. detach ( ) , & mut goals) ;
213
205
// 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" ) ;
215
210
216
211
let target_symbolic_remote_names = {
217
212
let remote_names = repo. remote_names ( ) ;
@@ -233,15 +228,15 @@ impl Graph {
233
228
. any ( |( _, wsrn, _) | Some ( wsrn) == ref_name. as_ref ( ) )
234
229
{
235
230
let current = graph. insert_root ( branch_segment_from_name_and_meta (
236
- ref_name. clone ( ) ,
231
+ ref_name. clone ( ) . map ( |rn| ( rn , None ) ) ,
237
232
meta,
238
233
Some ( ( & refs_by_id, tip. detach ( ) ) ) ,
239
234
) ?) ;
240
235
if next. push_back_exhausted ( (
241
236
tip. detach ( ) ,
242
237
tip_flags,
243
238
Instruction :: CollectCommit { into : current } ,
244
- limit ,
239
+ max_limit ,
245
240
) ) {
246
241
return Ok ( graph. with_hard_limit ( ) ) ;
247
242
}
@@ -261,12 +256,16 @@ impl Graph {
261
256
. map ( |tid| ( trn. clone ( ) , tid) )
262
257
} ) ;
263
258
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 )
266
261
} else {
267
- ( CommitFlags :: empty ( ) , tip_limit_with_goal)
262
+ (
263
+ CommitFlags :: empty ( ) ,
264
+ max_limit. with_indirect_goal ( tip. detach ( ) , & mut goals) ,
265
+ )
268
266
} ;
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 ) ?;
270
269
// The limits for the target ref and the worktree ref are synced so they can always find each other,
271
270
// while being able to stop when the entrypoint is included.
272
271
ws_segment. metadata = Some ( SegmentMetadata :: Workspace ( workspace_info) ) ;
@@ -279,15 +278,15 @@ impl Graph {
279
278
// We only allow workspaces that are not remote, and that are not target refs.
280
279
// Theoretically they can still cross-reference each other, but then we'd simply ignore
281
280
// their status for now.
282
- CommitFlags :: NotInRemote | ws_flags ,
281
+ CommitFlags :: NotInRemote | ws_extra_flags ,
283
282
Instruction :: CollectCommit { into : ws_segment } ,
284
283
ws_limit,
285
284
) ) {
286
285
return Ok ( graph. with_hard_limit ( ) ) ;
287
286
}
288
287
if let Some ( ( target_ref, target_ref_id) ) = target {
289
288
let target_segment = graph. insert_root ( branch_segment_from_name_and_meta (
290
- Some ( target_ref) ,
289
+ Some ( ( target_ref, None ) ) ,
291
290
meta,
292
291
None ,
293
292
) ?) ;
@@ -297,17 +296,18 @@ impl Graph {
297
296
Instruction :: CollectCommit {
298
297
into : target_segment,
299
298
} ,
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 ( ) ,
301
304
) ) {
302
305
return Ok ( graph. with_hard_limit ( ) ) ;
303
306
}
304
307
}
305
308
}
306
309
307
310
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;
311
311
while let Some ( ( id, mut propagated_flags, instruction, mut limit) ) = next. pop_front ( ) {
312
312
if max_commits_recharge_location. binary_search ( & id) . is_ok ( ) {
313
313
limit. set_but_keep_goal ( max_limit) ;
@@ -330,7 +330,6 @@ impl Graph {
330
330
& mut seen,
331
331
& mut next,
332
332
id,
333
- limit,
334
333
propagated_flags,
335
334
src_sidx,
336
335
) ?;
@@ -359,7 +358,6 @@ impl Graph {
359
358
& mut seen,
360
359
& mut next,
361
360
id,
362
- limit,
363
361
propagated_flags,
364
362
parent_above,
365
363
) ?;
@@ -432,7 +430,7 @@ impl Graph {
432
430
}
433
431
}
434
432
435
- prune_integrated_tips ( & mut graph, & mut next, & desired_refs , max_limit ) ;
433
+ prune_integrated_tips ( & mut graph, & mut next) ;
436
434
}
437
435
438
436
graph. post_processed (
@@ -459,15 +457,6 @@ struct Queue {
459
457
max : Option < usize > ,
460
458
}
461
459
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
-
471
460
/// A set of commits to keep track of in bitflags.
472
461
#[ derive( Default ) ]
473
462
struct Goals ( Vec < gix:: ObjectId > ) ;
0 commit comments