@@ -94,7 +94,8 @@ impl<'a> Display for Format<'a> {
94
94
}
95
95
}
96
96
97
- type Flags = u32 ;
97
+ /// A bit-field which keeps track of which commit is reachable by one of 32 candidates names.
98
+ pub type Flags = u32 ;
98
99
const MAX_CANDIDATES : usize = std:: mem:: size_of :: < Flags > ( ) * 8 ;
99
100
100
101
/// The options required to call [`describe()`][function::describe()].
@@ -129,14 +130,11 @@ impl<'name> Default for Options<'name> {
129
130
/// The error returned by the [`describe()`][function::describe()] function.
130
131
#[ derive( Debug , thiserror:: Error ) ]
131
132
#[ allow( missing_docs) ]
132
- pub enum Error < E >
133
- where
134
- E : std:: error:: Error + Send + Sync + ' static ,
135
- {
136
- #[ error( "Commit {} could not be found during graph traversal" , . oid. to_hex( ) ) ]
137
- Find {
133
+ pub enum Error {
134
+ #[ error( "The parents of commit {} could not be added to graph during traversal" , oid. to_hex( ) ) ]
135
+ InsertParentsToGraph {
138
136
#[ source]
139
- err : Option < E > ,
137
+ err : crate :: graph :: insert_parents :: Error ,
140
138
oid : gix_hash:: ObjectId ,
141
139
} ,
142
140
#[ error( "A commit could not be decoded during traversal" ) ]
@@ -148,32 +146,26 @@ pub(crate) mod function {
148
146
149
147
use bstr:: BStr ;
150
148
use gix_hash:: oid;
151
- use gix_hashtable:: { hash_map, HashMap } ;
152
- use gix_object:: CommitRefIter ;
153
149
154
150
use super :: { Error , Outcome } ;
155
151
use crate :: describe:: { CommitTime , Flags , Options , MAX_CANDIDATES } ;
156
- use crate :: PriorityQueue ;
152
+ use crate :: { Graph , PriorityQueue } ;
157
153
158
- /// Given a `commit` id, traverse the commit graph and collect candidate names from the `name_by_oid` mapping to produce
154
+ /// Given a `commit` id, traverse the commit ` graph` and collect candidate names from the `name_by_oid` mapping to produce
159
155
/// an `Outcome`, which converted [`into_format()`][Outcome::into_format()] will produce a typical `git describe` string.
160
156
///
161
157
/// Note that the `name_by_oid` map is returned in the [`Outcome`], which can be forcefully returned even if there was no matching
162
158
/// candidate by setting `fallback_to_oid` to true.
163
- pub fn describe < ' name , Find , E > (
159
+ pub fn describe < ' name > (
164
160
commit : & oid ,
165
- mut find : Find ,
161
+ graph : & mut Graph < ' _ , Flags > ,
166
162
Options {
167
163
name_by_oid,
168
164
mut max_candidates,
169
165
fallback_to_oid,
170
166
first_parent,
171
167
} : Options < ' name > ,
172
- ) -> Result < Option < Outcome < ' name > > , Error < E > >
173
- where
174
- Find : for < ' b > FnMut ( & oid , & ' b mut Vec < u8 > ) -> Result < Option < CommitRefIter < ' b > > , E > ,
175
- E : std:: error:: Error + Send + Sync + ' static ,
176
- {
168
+ ) -> Result < Option < Outcome < ' name > > , Error > {
177
169
max_candidates = max_candidates. min ( MAX_CANDIDATES ) ;
178
170
if let Some ( name) = name_by_oid. get ( commit) {
179
171
return Ok ( Some ( Outcome {
@@ -199,15 +191,12 @@ pub(crate) mod function {
199
191
} ;
200
192
}
201
193
202
- let mut buf = Vec :: new ( ) ;
203
- let mut parent_buf = Vec :: new ( ) ;
204
-
205
194
let mut queue = PriorityQueue :: from_iter ( Some ( ( u32:: MAX , commit. to_owned ( ) ) ) ) ;
206
195
let mut candidates = Vec :: new ( ) ;
207
196
let mut commits_seen = 0 ;
208
197
let mut gave_up_on_commit = None ;
209
- let mut seen = HashMap :: < gix_hash :: ObjectId , Flags > :: default ( ) ;
210
- seen . insert ( commit. to_owned ( ) , 0u32 ) ;
198
+ graph . clear ( ) ;
199
+ graph . insert ( commit. to_owned ( ) , 0u32 ) ;
211
200
212
201
while let Some ( commit) = queue. pop ( ) {
213
202
commits_seen += 1 ;
@@ -220,15 +209,15 @@ pub(crate) mod function {
220
209
identity_bit,
221
210
order : candidates. len ( ) ,
222
211
} ) ;
223
- let flags = seen . get_mut ( & commit) . expect ( "inserted" ) ;
212
+ let flags = graph . get_mut ( & commit) . expect ( "inserted" ) ;
224
213
* flags |= identity_bit;
225
214
* flags
226
215
} else {
227
216
gave_up_on_commit = Some ( commit) ;
228
217
break ;
229
218
}
230
219
} else {
231
- seen [ & commit]
220
+ graph [ & commit]
232
221
} ;
233
222
234
223
for candidate in candidates
@@ -261,16 +250,7 @@ pub(crate) mod function {
261
250
}
262
251
}
263
252
264
- parents_by_date_onto_queue_and_track_names (
265
- & mut find,
266
- & mut buf,
267
- & mut parent_buf,
268
- & mut queue,
269
- & mut seen,
270
- & commit,
271
- flags,
272
- first_parent,
273
- ) ?;
253
+ parents_by_date_onto_queue_and_track_names ( graph, & mut queue, commit, flags, first_parent) ?;
274
254
}
275
255
276
256
if candidates. is_empty ( ) {
@@ -300,11 +280,8 @@ pub(crate) mod function {
300
280
301
281
commits_seen += finish_depth_computation (
302
282
queue,
303
- find ,
283
+ graph ,
304
284
candidates. first_mut ( ) . expect ( "at least one candidate" ) ,
305
- seen,
306
- buf,
307
- parent_buf,
308
285
first_parent,
309
286
) ?;
310
287
@@ -317,105 +294,49 @@ pub(crate) mod function {
317
294
} ) )
318
295
}
319
296
320
- #[ allow( clippy:: too_many_arguments) ]
321
- fn parents_by_date_onto_queue_and_track_names < Find , E > (
322
- find : & mut Find ,
323
- buf : & mut Vec < u8 > ,
324
- parent_buf : & mut Vec < u8 > ,
297
+ fn parents_by_date_onto_queue_and_track_names (
298
+ graph : & mut Graph < ' _ , Flags > ,
325
299
queue : & mut PriorityQueue < CommitTime , gix_hash:: ObjectId > ,
326
- seen : & mut HashMap < gix_hash:: ObjectId , Flags > ,
327
- commit : & gix_hash:: oid ,
300
+ commit : gix_hash:: ObjectId ,
328
301
commit_flags : Flags ,
329
302
first_parent : bool ,
330
- ) -> Result < ( ) , Error < E > >
331
- where
332
- Find : for < ' b > FnMut ( & oid , & ' b mut Vec < u8 > ) -> Result < Option < CommitRefIter < ' b > > , E > ,
333
- E : std:: error:: Error + Send + Sync + ' static ,
334
- {
335
- let commit_iter = find ( commit, buf)
336
- . map_err ( |err| Error :: Find {
337
- err : Some ( err) ,
338
- oid : commit. to_owned ( ) ,
339
- } ) ?
340
- . ok_or_else ( || Error :: Find {
341
- err : None ,
342
- oid : commit. to_owned ( ) ,
343
- } ) ?;
344
- for token in commit_iter {
345
- match token {
346
- Ok ( gix_object:: commit:: ref_iter:: Token :: Tree { .. } ) => continue ,
347
- Ok ( gix_object:: commit:: ref_iter:: Token :: Parent { id : parent_id } ) => match seen. entry ( parent_id) {
348
- hash_map:: Entry :: Vacant ( entry) => {
349
- let parent = match find ( & parent_id, parent_buf) . map_err ( |err| Error :: Find {
350
- err : Some ( err) ,
351
- oid : commit. to_owned ( ) ,
352
- } ) ? {
353
- Some ( p) => p,
354
- None => continue , // skip missing objects, they don't exist.
355
- } ;
356
-
357
- let parent_commit_date = parent
358
- . committer ( )
359
- . map ( |committer| committer. time . seconds_since_unix_epoch )
360
- . unwrap_or_default ( ) ;
361
-
362
- entry. insert ( commit_flags) ;
363
- queue. insert ( parent_commit_date, parent_id) ;
364
- }
365
- hash_map:: Entry :: Occupied ( mut entry) => {
366
- * entry. get_mut ( ) |= commit_flags;
367
- }
303
+ ) -> Result < ( ) , Error > {
304
+ graph
305
+ . insert_parents (
306
+ & commit,
307
+ |parent_id, parent_commit_date| {
308
+ queue. insert ( parent_commit_date as u32 , parent_id) ;
309
+ commit_flags
368
310
} ,
369
- Ok ( _unused_token) => break ,
370
- Err ( err) => return Err ( err. into ( ) ) ,
371
- }
372
- if first_parent {
373
- break ;
374
- }
375
- }
376
-
311
+ |_parent_id, flags| * flags |= commit_flags,
312
+ first_parent,
313
+ )
314
+ . map_err ( |err| Error :: InsertParentsToGraph { err, oid : commit } ) ?;
377
315
Ok ( ( ) )
378
316
}
379
317
380
- #[ allow( clippy:: too_many_arguments) ]
381
- fn finish_depth_computation < ' name , Find , E > (
318
+ fn finish_depth_computation (
382
319
mut queue : PriorityQueue < CommitTime , gix_hash:: ObjectId > ,
383
- mut find : Find ,
384
- best_candidate : & mut Candidate < ' name > ,
385
- mut seen : HashMap < gix_hash:: ObjectId , Flags > ,
386
- mut buf : Vec < u8 > ,
387
- mut parent_buf : Vec < u8 > ,
320
+ graph : & mut Graph < ' _ , Flags > ,
321
+ best_candidate : & mut Candidate < ' _ > ,
388
322
first_parent : bool ,
389
- ) -> Result < u32 , Error < E > >
390
- where
391
- Find : for < ' b > FnMut ( & oid , & ' b mut Vec < u8 > ) -> Result < Option < CommitRefIter < ' b > > , E > ,
392
- E : std:: error:: Error + Send + Sync + ' static ,
393
- {
323
+ ) -> Result < u32 , Error > {
394
324
let mut commits_seen = 0 ;
395
325
while let Some ( commit) = queue. pop ( ) {
396
326
commits_seen += 1 ;
397
- let flags = seen [ & commit] ;
327
+ let flags = graph [ & commit] ;
398
328
if ( flags & best_candidate. identity_bit ) == best_candidate. identity_bit {
399
329
if queue
400
330
. iter_random ( )
401
- . all ( |id| ( seen [ id] & best_candidate. identity_bit ) == best_candidate. identity_bit )
331
+ . all ( |id| ( graph [ id] & best_candidate. identity_bit ) == best_candidate. identity_bit )
402
332
{
403
333
break ;
404
334
}
405
335
} else {
406
336
best_candidate. commits_in_its_future += 1 ;
407
337
}
408
338
409
- parents_by_date_onto_queue_and_track_names (
410
- & mut find,
411
- & mut buf,
412
- & mut parent_buf,
413
- & mut queue,
414
- & mut seen,
415
- & commit,
416
- flags,
417
- first_parent,
418
- ) ?;
339
+ parents_by_date_onto_queue_and_track_names ( graph, & mut queue, commit, flags, first_parent) ?;
419
340
}
420
341
Ok ( commits_seen)
421
342
}
@@ -431,4 +352,5 @@ pub(crate) mod function {
431
352
}
432
353
}
433
354
355
+ /// The timestamp for the creation date of a commit in seconds since unix epoch.
434
356
type CommitTime = u32 ;
0 commit comments