1mod bit_set;
23mod changed_path;
24mod composite;
25mod entry;
26mod mutable;
27mod readonly;
28mod rev_walk;
29mod rev_walk_queue;
30mod revset_engine;
31mod revset_graph_iterator;
32mod store;
33
34pub use self::mutable::DefaultMutableIndex;
35pub use self::readonly::ChangedPathIndexLevelStats;
36pub use self::readonly::CommitIndexLevelStats;
37pub use self::readonly::DefaultReadonlyIndex;
38pub use self::readonly::DefaultReadonlyIndexRevset;
39pub use self::readonly::IndexStats;
40pub use self::readonly::ReadonlyIndexLoadError;
41pub use self::store::DefaultIndexStore;
42pub use self::store::DefaultIndexStoreError;
43pub use self::store::DefaultIndexStoreInitError;
44
45#[cfg(test)]
46#[rustversion::attr(
47 since(1.89),
48 expect(clippy::cloned_ref_to_slice_refs, reason = "makes tests more readable")
49)]
50mod tests {
51 use std::cmp::Reverse;
52 use std::convert::Infallible;
53 use std::ops::Range;
54 use std::sync::Arc;
55
56 use itertools::Itertools as _;
57 use smallvec::smallvec_inline;
58 use test_case::test_case;
59
60 use super::changed_path::CompositeChangedPathIndex;
61 use super::composite::AsCompositeIndex as _;
62 use super::composite::CommitIndexSegment as _;
63 use super::composite::CompositeCommitIndex;
64 use super::composite::DynCommitIndexSegment;
65 use super::entry::GlobalCommitPosition;
66 use super::entry::SmallGlobalCommitPositionsVec;
67 use super::mutable::MutableCommitIndexSegment;
68 use super::readonly::ReadonlyCommitIndexSegment;
69 use super::*;
70 use crate::backend::ChangeId;
71 use crate::backend::CommitId;
72 use crate::default_index::entry::LocalCommitPosition;
73 use crate::default_index::entry::SmallLocalCommitPositionsVec;
74 use crate::default_index::readonly::FieldLengths;
75 use crate::index::Index as _;
76 use crate::object_id::HexPrefix;
77 use crate::object_id::PrefixResolution;
78 use crate::revset::PARENTS_RANGE_FULL;
79 use crate::tests::new_temp_dir;
80
81 const TEST_FIELD_LENGTHS: FieldLengths = FieldLengths {
82 commit_id: 3,
84 change_id: 16,
85 };
86
87 fn commit_id_generator() -> impl FnMut() -> CommitId {
89 let mut iter = (1_u128..).map(|n| CommitId::new(n.to_le_bytes().into()));
90 move || iter.next().unwrap()
91 }
92
93 fn change_id_generator() -> impl FnMut() -> ChangeId {
95 let mut iter = (1_u128..).map(|n| ChangeId::new(n.to_le_bytes().into()));
96 move || iter.next().unwrap()
97 }
98
99 fn get_commit_index_stats(commits: &Arc<ReadonlyCommitIndexSegment>) -> IndexStats {
100 let changed_paths = CompositeChangedPathIndex::null();
101 let index = DefaultReadonlyIndex::from_segment(commits.clone(), changed_paths);
102 index.stats()
103 }
104
105 #[test_case(false; "memory")]
106 #[test_case(true; "file")]
107 fn index_empty(on_disk: bool) {
108 let temp_dir = new_temp_dir();
109 let mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
110 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
111 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
112 let stats = get_commit_index_stats(&saved_index);
114 assert_eq!(stats.num_commits, 0);
115 assert_eq!(stats.num_heads, 0);
116 assert_eq!(stats.max_generation_number, 0);
117 assert_eq!(stats.num_merges, 0);
118 assert_eq!(stats.num_changes, 0);
119 Box::new(Arc::try_unwrap(saved_index).unwrap())
120 } else {
121 Box::new(mutable_segment)
122 };
123 let index = CompositeCommitIndex::new(index_segment.as_ref());
124 assert_eq!(index.num_commits(), 0);
125
126 assert!(index.entry_by_id(&CommitId::from_hex("000000")).is_none());
128 assert!(index.entry_by_id(&CommitId::from_hex("aaa111")).is_none());
129 assert!(index.entry_by_id(&CommitId::from_hex("ffffff")).is_none());
130 }
131
132 #[test_case(false; "memory")]
133 #[test_case(true; "file")]
134 fn index_root_commit(on_disk: bool) {
135 let temp_dir = new_temp_dir();
136 let mut new_change_id = change_id_generator();
137 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
138 let id_0 = CommitId::from_hex("000000");
139 let change_id0 = new_change_id();
140 mutable_segment.add_commit_data(id_0.clone(), change_id0.clone(), &[]);
141 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
142 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
143 let stats = get_commit_index_stats(&saved_index);
145 assert_eq!(stats.num_commits, 1);
146 assert_eq!(stats.num_heads, 1);
147 assert_eq!(stats.max_generation_number, 0);
148 assert_eq!(stats.num_merges, 0);
149 assert_eq!(stats.num_changes, 1);
150 Box::new(Arc::try_unwrap(saved_index).unwrap())
151 } else {
152 Box::new(mutable_segment)
153 };
154 let index = CompositeCommitIndex::new(index_segment.as_ref());
155 assert_eq!(index.num_commits(), 1);
156
157 assert_eq!(index.commit_id_to_pos(&id_0), Some(GlobalCommitPosition(0)));
159 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("aaaaaa")), None);
160 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("ffffff")), None);
161 let entry = index.entry_by_id(&id_0).unwrap();
163 assert_eq!(entry.position(), GlobalCommitPosition(0));
164 assert_eq!(entry.commit_id(), id_0);
165 assert_eq!(entry.change_id(), change_id0);
166 assert_eq!(entry.generation_number(), 0);
167 assert_eq!(entry.num_parents(), 0);
168 assert_eq!(
169 entry.parent_positions(),
170 SmallGlobalCommitPositionsVec::new()
171 );
172 assert_eq!(entry.parents().len(), 0);
173 }
174
175 #[test]
176 #[should_panic(expected = "parent commit is not indexed")]
177 fn index_missing_parent_commit() {
178 let mut new_change_id = change_id_generator();
179 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
180 let id_0 = CommitId::from_hex("000000");
181 let id_1 = CommitId::from_hex("111111");
182 index.add_commit_data(id_1, new_change_id(), &[id_0]);
183 }
184
185 #[test_case(false, false; "full in memory")]
186 #[test_case(false, true; "full on disk")]
187 #[test_case(true, false; "incremental in memory")]
188 #[test_case(true, true; "incremental on disk")]
189 fn index_multiple_commits(incremental: bool, on_disk: bool) {
190 let temp_dir = new_temp_dir();
191 let mut new_change_id = change_id_generator();
192 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
193 let id_0 = CommitId::from_hex("000000");
201 let change_id0 = new_change_id();
202 let id_1 = CommitId::from_hex("111111");
203 let change_id1 = new_change_id();
204 let id_2 = CommitId::from_hex("222222");
205 let change_id2 = change_id1.clone();
206 mutable_segment.add_commit_data(id_0.clone(), change_id0, &[]);
207 mutable_segment.add_commit_data(id_1.clone(), change_id1.clone(), &[id_0.clone()]);
208 mutable_segment.add_commit_data(id_2.clone(), change_id2.clone(), &[id_0.clone()]);
209
210 if incremental {
213 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
214 mutable_segment = MutableCommitIndexSegment::incremental(initial_file);
215 }
216
217 let id_3 = CommitId::from_hex("333333");
218 let change_id3 = new_change_id();
219 let id_4 = CommitId::from_hex("444444");
220 let change_id4 = new_change_id();
221 let id_5 = CommitId::from_hex("555555");
222 let change_id5 = change_id3.clone();
223 mutable_segment.add_commit_data(id_3.clone(), change_id3.clone(), &[id_2.clone()]);
224 mutable_segment.add_commit_data(id_4.clone(), change_id4, &[id_1.clone()]);
225 mutable_segment.add_commit_data(id_5.clone(), change_id5, &[id_4.clone(), id_2.clone()]);
226 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
227 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
228 let stats = get_commit_index_stats(&saved_index);
230 assert_eq!(stats.num_commits, 6);
231 assert_eq!(stats.num_heads, 2);
232 assert_eq!(stats.max_generation_number, 3);
233 assert_eq!(stats.num_merges, 1);
234 assert_eq!(stats.num_changes, 4);
235 Box::new(Arc::try_unwrap(saved_index).unwrap())
236 } else {
237 Box::new(mutable_segment)
238 };
239 let index = CompositeCommitIndex::new(index_segment.as_ref());
240 assert_eq!(index.num_commits(), 6);
241
242 let entry_0 = index.entry_by_id(&id_0).unwrap();
244 let entry_1 = index.entry_by_id(&id_1).unwrap();
245 let entry_2 = index.entry_by_id(&id_2).unwrap();
246 let entry_3 = index.entry_by_id(&id_3).unwrap();
247 let entry_4 = index.entry_by_id(&id_4).unwrap();
248 let entry_5 = index.entry_by_id(&id_5).unwrap();
249 assert_eq!(entry_0.position(), GlobalCommitPosition(0));
251 assert_eq!(entry_0.commit_id(), id_0);
252 assert_eq!(entry_1.position(), GlobalCommitPosition(1));
253 assert_eq!(entry_1.commit_id(), id_1);
254 assert_eq!(entry_1.change_id(), change_id1);
255 assert_eq!(entry_1.generation_number(), 1);
256 assert_eq!(entry_1.num_parents(), 1);
257 assert_eq!(
258 entry_1.parent_positions(),
259 smallvec_inline![GlobalCommitPosition(0)]
260 );
261 assert_eq!(entry_1.parents().len(), 1);
262 assert_eq!(
263 entry_1.parents().next().unwrap().position(),
264 GlobalCommitPosition(0)
265 );
266 assert_eq!(entry_2.position(), GlobalCommitPosition(2));
267 assert_eq!(entry_2.commit_id(), id_2);
268 assert_eq!(entry_2.change_id(), change_id2);
269 assert_eq!(entry_2.generation_number(), 1);
270 assert_eq!(entry_2.num_parents(), 1);
271 assert_eq!(
272 entry_2.parent_positions(),
273 smallvec_inline![GlobalCommitPosition(0)]
274 );
275 assert_eq!(entry_3.change_id(), change_id3);
276 assert_eq!(entry_3.generation_number(), 2);
277 assert_eq!(
278 entry_3.parent_positions(),
279 smallvec_inline![GlobalCommitPosition(2)]
280 );
281 assert_eq!(entry_4.position(), GlobalCommitPosition(4));
282 assert_eq!(entry_4.generation_number(), 2);
283 assert_eq!(entry_4.num_parents(), 1);
284 assert_eq!(
285 entry_4.parent_positions(),
286 smallvec_inline![GlobalCommitPosition(1)]
287 );
288 assert_eq!(entry_5.generation_number(), 3);
289 assert_eq!(entry_5.num_parents(), 2);
290 assert_eq!(
291 entry_5.parent_positions(),
292 smallvec_inline![GlobalCommitPosition(4), GlobalCommitPosition(2)]
293 );
294 assert_eq!(entry_5.parents().len(), 2);
295 assert_eq!(
296 entry_5.parents().next().unwrap().position(),
297 GlobalCommitPosition(4)
298 );
299 assert_eq!(
300 entry_5.parents().nth(1).unwrap().position(),
301 GlobalCommitPosition(2)
302 );
303 }
304
305 #[test_case(false; "in memory")]
306 #[test_case(true; "on disk")]
307 fn index_many_parents(on_disk: bool) {
308 let temp_dir = new_temp_dir();
309 let mut new_change_id = change_id_generator();
310 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
311 let id_0 = CommitId::from_hex("000000");
321 let id_1 = CommitId::from_hex("111111");
322 let id_2 = CommitId::from_hex("222222");
323 let id_3 = CommitId::from_hex("333333");
324 let id_4 = CommitId::from_hex("444444");
325 let id_5 = CommitId::from_hex("555555");
326 let id_6 = CommitId::from_hex("666666");
327 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
328 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
329 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
330 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
331 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone()]);
332 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[id_0]);
333 mutable_segment.add_commit_data(
334 id_6.clone(),
335 new_change_id(),
336 &[id_1, id_2, id_3, id_4, id_5],
337 );
338 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
339 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
340 let stats = get_commit_index_stats(&saved_index);
342 assert_eq!(stats.num_commits, 7);
343 assert_eq!(stats.num_heads, 1);
344 assert_eq!(stats.max_generation_number, 2);
345 assert_eq!(stats.num_merges, 1);
346 Box::new(Arc::try_unwrap(saved_index).unwrap())
347 } else {
348 Box::new(mutable_segment)
349 };
350 let index = CompositeCommitIndex::new(index_segment.as_ref());
351 assert_eq!(index.num_commits(), 7);
352
353 let entry_6 = index.entry_by_id(&id_6).unwrap();
355 assert_eq!(entry_6.commit_id(), id_6.clone());
356 assert_eq!(entry_6.num_parents(), 5);
357 assert_eq!(
358 entry_6.parent_positions(),
359 smallvec_inline![
360 GlobalCommitPosition(1),
361 GlobalCommitPosition(2),
362 GlobalCommitPosition(3),
363 GlobalCommitPosition(4),
364 GlobalCommitPosition(5),
365 ]
366 );
367 assert_eq!(entry_6.generation_number(), 2);
368 }
369
370 #[test]
371 fn resolve_commit_id_prefix() {
372 let temp_dir = new_temp_dir();
373 let mut new_change_id = change_id_generator();
374 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
375
376 let id_0 = CommitId::from_hex("000000");
378 let id_1 = CommitId::from_hex("009999");
379 let id_2 = CommitId::from_hex("055488");
380 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
381 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
382 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
383
384 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
386 mutable_segment = MutableCommitIndexSegment::incremental(initial_file);
387
388 let id_3 = CommitId::from_hex("055444");
389 let id_4 = CommitId::from_hex("055555");
390 let id_5 = CommitId::from_hex("033333");
391 mutable_segment.add_commit_data(id_3, new_change_id(), &[]);
392 mutable_segment.add_commit_data(id_4, new_change_id(), &[]);
393 mutable_segment.add_commit_data(id_5, new_change_id(), &[]);
394
395 let index = mutable_segment.as_composite();
396
397 assert_eq!(
399 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_0)),
400 PrefixResolution::SingleMatch(id_0)
401 );
402 assert_eq!(
403 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_1)),
404 PrefixResolution::SingleMatch(id_1)
405 );
406 assert_eq!(
407 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_2)),
408 PrefixResolution::SingleMatch(id_2)
409 );
410 assert_eq!(
412 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("ffffff").unwrap()),
413 PrefixResolution::NoMatch
414 );
415 assert_eq!(
416 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("000001").unwrap()),
417 PrefixResolution::NoMatch
418 );
419 assert_eq!(
421 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("0").unwrap()),
422 PrefixResolution::AmbiguousMatch
423 );
424 assert_eq!(
426 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("009").unwrap()),
427 PrefixResolution::SingleMatch(CommitId::from_hex("009999"))
428 );
429 assert_eq!(
431 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("03").unwrap()),
432 PrefixResolution::SingleMatch(CommitId::from_hex("033333"))
433 );
434 assert_eq!(
436 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
437 PrefixResolution::AmbiguousMatch
438 );
439 }
440
441 #[test]
442 #[expect(clippy::redundant_clone)] fn neighbor_commit_ids() {
444 let temp_dir = new_temp_dir();
445 let mut new_change_id = change_id_generator();
446 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
447
448 let id_0 = CommitId::from_hex("000001");
450 let id_1 = CommitId::from_hex("009999");
451 let id_2 = CommitId::from_hex("055488");
452 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
453 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
454 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
455
456 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
458 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
459
460 let id_3 = CommitId::from_hex("055444");
461 let id_4 = CommitId::from_hex("055555");
462 let id_5 = CommitId::from_hex("033333");
463 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
464 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
465 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
466
467 assert_eq!(
469 initial_file.resolve_neighbor_commit_ids(&id_0),
470 (None, Some(id_1.clone())),
471 );
472 assert_eq!(
473 initial_file.resolve_neighbor_commit_ids(&id_1),
474 (Some(id_0.clone()), Some(id_2.clone())),
475 );
476 assert_eq!(
477 initial_file.resolve_neighbor_commit_ids(&id_2),
478 (Some(id_1.clone()), None),
479 );
480
481 assert_eq!(
483 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
484 (None, Some(id_0.clone())),
485 );
486 assert_eq!(
487 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000002")),
488 (Some(id_0.clone()), Some(id_1.clone())),
489 );
490 assert_eq!(
491 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
492 (Some(id_2.clone()), None),
493 );
494
495 assert_eq!(
497 mutable_segment.resolve_neighbor_commit_ids(&id_5),
498 (None, Some(id_3.clone())),
499 );
500 assert_eq!(
501 mutable_segment.resolve_neighbor_commit_ids(&id_3),
502 (Some(id_5.clone()), Some(id_4.clone())),
503 );
504 assert_eq!(
505 mutable_segment.resolve_neighbor_commit_ids(&id_4),
506 (Some(id_3.clone()), None),
507 );
508
509 assert_eq!(
511 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033332")),
512 (None, Some(id_5.clone())),
513 );
514 assert_eq!(
515 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
516 (Some(id_5.clone()), Some(id_3.clone())),
517 );
518 assert_eq!(
519 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
520 (Some(id_4.clone()), None),
521 );
522
523 let composite_index = CompositeCommitIndex::new(&mutable_segment);
525 assert_eq!(
526 composite_index.resolve_neighbor_commit_ids(&id_0),
527 (None, Some(id_1.clone())),
528 );
529 assert_eq!(
530 composite_index.resolve_neighbor_commit_ids(&id_1),
531 (Some(id_0.clone()), Some(id_5.clone())),
532 );
533 assert_eq!(
534 composite_index.resolve_neighbor_commit_ids(&id_5),
535 (Some(id_1.clone()), Some(id_3.clone())),
536 );
537 assert_eq!(
538 composite_index.resolve_neighbor_commit_ids(&id_3),
539 (Some(id_5.clone()), Some(id_2.clone())),
540 );
541 assert_eq!(
542 composite_index.resolve_neighbor_commit_ids(&id_2),
543 (Some(id_3.clone()), Some(id_4.clone())),
544 );
545 assert_eq!(
546 composite_index.resolve_neighbor_commit_ids(&id_4),
547 (Some(id_2.clone()), None),
548 );
549
550 assert_eq!(
553 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
554 (None, Some(id_0.clone())),
555 );
556 assert_eq!(
557 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("010000")),
558 (Some(id_1.clone()), Some(id_5.clone())),
559 );
560 assert_eq!(
561 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
562 (Some(id_5.clone()), Some(id_3.clone())),
563 );
564 assert_eq!(
565 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
566 (Some(id_4.clone()), None),
567 );
568 }
569
570 #[test]
571 fn shortest_unique_commit_id_prefix() {
572 let temp_dir = new_temp_dir();
573 let mut new_change_id = change_id_generator();
574 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
575
576 let id_0 = CommitId::from_hex("000001");
578 let id_1 = CommitId::from_hex("009999");
579 let id_2 = CommitId::from_hex("055488");
580 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
581 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
582 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
583
584 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
586 mutable_segment = MutableCommitIndexSegment::incremental(initial_file);
587
588 let id_3 = CommitId::from_hex("055444");
589 let id_4 = CommitId::from_hex("055555");
590 let id_5 = CommitId::from_hex("033333");
591 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
592 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
593 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
594
595 let index = mutable_segment.as_composite();
596
597 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_0), 3);
599 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_1), 3);
600 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_2), 5);
601 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_3), 5);
602 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_4), 4);
603 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_5), 2);
604
605 assert_eq!(
607 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("000002")),
608 6
609 );
610 assert_eq!(
611 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("010000")),
612 2
613 );
614 assert_eq!(
615 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("033334")),
616 6
617 );
618 assert_eq!(
619 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("ffffff")),
620 1
621 );
622 }
623
624 #[test]
625 fn resolve_change_id_prefix() {
626 let temp_dir = new_temp_dir();
627 let mut new_commit_id = commit_id_generator();
628 let local_positions_vec = |positions: &[u32]| -> SmallLocalCommitPositionsVec {
629 positions.iter().copied().map(LocalCommitPosition).collect()
630 };
631 let index_positions_vec = |positions: &[u32]| -> SmallGlobalCommitPositionsVec {
632 positions
633 .iter()
634 .copied()
635 .map(GlobalCommitPosition)
636 .collect()
637 };
638
639 let id_0 = ChangeId::from_hex("00000001");
640 let id_1 = ChangeId::from_hex("00999999");
641 let id_2 = ChangeId::from_hex("05548888");
642 let id_3 = ChangeId::from_hex("05544444");
643 let id_4 = ChangeId::from_hex("05555555");
644 let id_5 = ChangeId::from_hex("05555333");
645
646 let mut mutable_segment = MutableCommitIndexSegment::full(FieldLengths {
648 commit_id: 16,
649 change_id: 4,
650 });
651 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
652 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
653 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
654 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
655 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
656 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
657
658 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
660 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
661
662 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
663 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
664 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
665 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
666 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
667
668 assert_eq!(
670 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_0)),
671 PrefixResolution::SingleMatch((id_0.clone(), local_positions_vec(&[0])))
672 );
673 assert_eq!(
674 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
675 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[1, 3])))
676 );
677 assert_eq!(
678 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_2)),
679 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
680 );
681
682 assert_eq!(
684 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
685 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[3])))
686 );
687 assert_eq!(
688 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_3)),
689 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
690 );
691 assert_eq!(
692 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_4)),
693 PrefixResolution::SingleMatch((id_4.clone(), local_positions_vec(&[2])))
694 );
695 assert_eq!(
696 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_5)),
697 PrefixResolution::SingleMatch((id_5.clone(), local_positions_vec(&[4])))
698 );
699
700 assert_eq!(
702 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("0555").unwrap()),
703 PrefixResolution::NoMatch
704 );
705 assert_eq!(
706 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("000").unwrap()),
707 PrefixResolution::NoMatch
708 );
709
710 assert_eq!(
712 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
713 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
714 );
715 assert_eq!(
716 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
717 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
718 );
719
720 assert_eq!(
722 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("00").unwrap()),
723 PrefixResolution::AmbiguousMatch
724 );
725 assert_eq!(
726 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("05555").unwrap()),
727 PrefixResolution::AmbiguousMatch
728 );
729
730 let index = mutable_segment.as_composite();
731
732 assert_eq!(
734 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_0)),
735 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
736 );
737 assert_eq!(
738 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
739 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
740 );
741 assert_eq!(
742 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_2)),
743 PrefixResolution::SingleMatch((id_2.clone(), index_positions_vec(&[2, 4, 5])))
744 );
745 assert_eq!(
746 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_3)),
747 PrefixResolution::SingleMatch((id_3.clone(), index_positions_vec(&[6, 7])))
748 );
749 assert_eq!(
750 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_4)),
751 PrefixResolution::SingleMatch((id_4.clone(), index_positions_vec(&[8])))
752 );
753 assert_eq!(
754 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_5)),
755 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
756 );
757
758 assert_eq!(
760 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("ffffffff").unwrap()),
761 PrefixResolution::NoMatch
762 );
763 assert_eq!(
764 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("00000002").unwrap()),
765 PrefixResolution::NoMatch
766 );
767
768 assert_eq!(
770 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("000").unwrap()),
771 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
772 );
773 assert_eq!(
774 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("055553").unwrap()),
775 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
776 );
777
778 assert_eq!(
780 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("009").unwrap()),
781 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
782 );
783
784 assert_eq!(
786 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("00").unwrap()),
787 PrefixResolution::AmbiguousMatch
788 );
789 assert_eq!(
790 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("05555").unwrap()),
791 PrefixResolution::AmbiguousMatch
792 );
793
794 assert_eq!(
796 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
797 PrefixResolution::AmbiguousMatch
798 );
799 }
800
801 #[test]
802 fn neighbor_change_ids() {
803 let temp_dir = new_temp_dir();
804 let mut new_commit_id = commit_id_generator();
805
806 let id_0 = ChangeId::from_hex("00000001");
807 let id_1 = ChangeId::from_hex("00999999");
808 let id_2 = ChangeId::from_hex("05548888");
809 let id_3 = ChangeId::from_hex("05544444");
810 let id_4 = ChangeId::from_hex("05555555");
811 let id_5 = ChangeId::from_hex("05555333");
812
813 let mut mutable_segment = MutableCommitIndexSegment::full(FieldLengths {
815 commit_id: 16,
816 change_id: 4,
817 });
818 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
819 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
820 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
821 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
822 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
823 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
824
825 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
827 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
828
829 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
830 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
831 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
832 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
833 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
834
835 assert_eq!(
837 initial_file.resolve_neighbor_change_ids(&id_0),
838 (None, Some(id_1.clone())),
839 );
840 assert_eq!(
841 initial_file.resolve_neighbor_change_ids(&id_1),
842 (Some(id_0.clone()), Some(id_2.clone())),
843 );
844 assert_eq!(
845 initial_file.resolve_neighbor_change_ids(&id_2),
846 (Some(id_1.clone()), None),
847 );
848
849 assert_eq!(
851 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
852 (None, Some(id_0.clone())),
853 );
854 assert_eq!(
855 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000002")),
856 (Some(id_0.clone()), Some(id_1.clone())),
857 );
858 assert_eq!(
859 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
860 (Some(id_2.clone()), None),
861 );
862
863 assert_eq!(
866 mutable_segment.resolve_neighbor_change_ids(&id_1),
867 (None, Some(id_3.clone())),
868 );
869 assert_eq!(
870 mutable_segment.resolve_neighbor_change_ids(&id_3),
871 (Some(id_1.clone()), Some(id_5.clone())),
872 );
873 assert_eq!(
874 mutable_segment.resolve_neighbor_change_ids(&id_5),
875 (Some(id_3.clone()), Some(id_4.clone())),
876 );
877 assert_eq!(
878 mutable_segment.resolve_neighbor_change_ids(&id_4),
879 (Some(id_5.clone()), None),
880 );
881
882 assert_eq!(
885 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("00999998")),
886 (None, Some(id_1.clone())),
887 );
888 assert_eq!(
889 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
890 (Some(id_1.clone()), Some(id_3.clone())),
891 );
892 assert_eq!(
893 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("05555332")),
894 (Some(id_3.clone()), Some(id_5.clone())),
895 );
896 assert_eq!(
897 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
898 (Some(id_4.clone()), None),
899 );
900
901 let index = mutable_segment.as_composite();
902
903 assert_eq!(
906 index.resolve_neighbor_change_ids(&id_0),
907 (None, Some(id_1.clone())),
908 );
909 assert_eq!(
910 index.resolve_neighbor_change_ids(&id_1),
911 (Some(id_0.clone()), Some(id_3.clone())),
912 );
913 assert_eq!(
914 index.resolve_neighbor_change_ids(&id_3),
915 (Some(id_1.clone()), Some(id_2.clone())),
916 );
917 assert_eq!(
918 index.resolve_neighbor_change_ids(&id_2),
919 (Some(id_3.clone()), Some(id_5.clone())),
920 );
921 assert_eq!(
922 index.resolve_neighbor_change_ids(&id_5),
923 (Some(id_2.clone()), Some(id_4.clone())),
924 );
925 assert_eq!(
926 index.resolve_neighbor_change_ids(&id_4),
927 (Some(id_5.clone()), None),
928 );
929
930 assert_eq!(
933 index.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
934 (None, Some(id_0.clone())),
935 );
936 assert_eq!(
937 index.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
938 (Some(id_1.clone()), Some(id_3.clone())),
939 );
940 assert_eq!(
941 index.resolve_neighbor_change_ids(&ChangeId::from_hex("05544555")),
942 (Some(id_3.clone()), Some(id_2.clone())),
943 );
944 assert_eq!(
945 index.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
946 (Some(id_4.clone()), None),
947 );
948 }
949
950 #[test]
951 fn shortest_unique_change_id_prefix() {
952 let temp_dir = new_temp_dir();
953 let mut new_commit_id = commit_id_generator();
954
955 let id_0 = ChangeId::from_hex("00000001");
956 let id_1 = ChangeId::from_hex("00999999");
957 let id_2 = ChangeId::from_hex("05548888");
958 let id_3 = ChangeId::from_hex("05544444");
959 let id_4 = ChangeId::from_hex("05555555");
960 let id_5 = ChangeId::from_hex("05555333");
961
962 let mut mutable_segment = MutableCommitIndexSegment::full(FieldLengths {
964 commit_id: 16,
965 change_id: 4,
966 });
967 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
968 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
969 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
970 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
971 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
972 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
973
974 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
976 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
977
978 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
979 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
980 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
981 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
982 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
983
984 let index = mutable_segment.as_composite();
985
986 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_0), 3);
988 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_1), 3);
989 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_2), 5);
990 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_3), 5);
991 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_4), 6);
992 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_5), 6);
993
994 assert_eq!(
996 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("00000002")),
997 8
998 );
999 assert_eq!(
1000 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("01000000")),
1001 2
1002 );
1003 assert_eq!(
1004 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("05555344")),
1005 7
1006 );
1007 assert_eq!(
1008 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("ffffffff")),
1009 1
1010 );
1011 }
1012
1013 #[test]
1014 fn test_is_ancestor() {
1015 let mut new_change_id = change_id_generator();
1016 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1017 let id_0 = CommitId::from_hex("000000");
1025 let id_1 = CommitId::from_hex("111111");
1026 let id_2 = CommitId::from_hex("222222");
1027 let id_3 = CommitId::from_hex("333333");
1028 let id_4 = CommitId::from_hex("444444");
1029 let id_5 = CommitId::from_hex("555555");
1030 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1031 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1032 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1033 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1034 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1035 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1036
1037 assert!(index.is_ancestor(&id_0, &id_0));
1038 assert!(index.is_ancestor(&id_0, &id_1));
1039 assert!(index.is_ancestor(&id_2, &id_3));
1040 assert!(index.is_ancestor(&id_2, &id_5));
1041 assert!(index.is_ancestor(&id_1, &id_5));
1042 assert!(index.is_ancestor(&id_0, &id_5));
1043 assert!(!index.is_ancestor(&id_1, &id_0));
1044 assert!(!index.is_ancestor(&id_5, &id_3));
1045 assert!(!index.is_ancestor(&id_3, &id_5));
1046 assert!(!index.is_ancestor(&id_2, &id_4));
1047 assert!(!index.is_ancestor(&id_4, &id_2));
1048 }
1049
1050 #[test]
1051 fn test_common_ancestors() {
1052 let mut new_change_id = change_id_generator();
1053 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1054 let id_0 = CommitId::from_hex("000000");
1063 let id_1 = CommitId::from_hex("111111");
1064 let id_2 = CommitId::from_hex("222222");
1065 let id_3 = CommitId::from_hex("333333");
1066 let id_4 = CommitId::from_hex("444444");
1067 let id_5 = CommitId::from_hex("555555");
1068 let id_6 = CommitId::from_hex("666666");
1069 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1070 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1071 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1072 index.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
1073 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1074 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1075 index.add_commit_data(id_6.clone(), new_change_id(), &[id_4.clone()]);
1076
1077 assert_eq!(
1078 index.common_ancestors(&[id_0.clone()], &[id_0.clone()]),
1079 vec![id_0.clone()]
1080 );
1081 assert_eq!(
1082 index.common_ancestors(&[id_5.clone()], &[id_5.clone()]),
1083 vec![id_5.clone()]
1084 );
1085 assert_eq!(
1086 index.common_ancestors(&[id_1.clone()], &[id_2.clone()]),
1087 vec![id_0.clone()]
1088 );
1089 assert_eq!(
1090 index.common_ancestors(&[id_2.clone()], &[id_1.clone()]),
1091 vec![id_0.clone()]
1092 );
1093 assert_eq!(
1094 index.common_ancestors(&[id_1.clone()], &[id_4.clone()]),
1095 vec![id_1.clone()]
1096 );
1097 assert_eq!(
1098 index.common_ancestors(&[id_4.clone()], &[id_1.clone()]),
1099 vec![id_1.clone()]
1100 );
1101 assert_eq!(
1102 index.common_ancestors(&[id_3.clone()], &[id_5.clone()]),
1103 vec![id_0.clone()]
1104 );
1105 assert_eq!(
1106 index.common_ancestors(&[id_5.clone()], &[id_3.clone()]),
1107 vec![id_0.clone()]
1108 );
1109 assert_eq!(
1110 index.common_ancestors(&[id_2.clone()], &[id_6.clone()]),
1111 vec![id_0.clone()]
1112 );
1113
1114 assert_eq!(
1116 index.common_ancestors(&[id_0.clone(), id_1.clone()], &[id_0.clone()]),
1117 vec![id_0.clone()]
1118 );
1119 assert_eq!(
1120 index.common_ancestors(&[id_0.clone(), id_1.clone()], &[id_1.clone()]),
1121 vec![id_1.clone()]
1122 );
1123 assert_eq!(
1124 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_1.clone()]),
1125 vec![id_1.clone()]
1126 );
1127 assert_eq!(
1128 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_4]),
1129 vec![id_1.clone()]
1130 );
1131 assert_eq!(
1132 index.common_ancestors(&[id_5.clone(), id_6.clone()], &[id_2.clone()]),
1133 &[id_2.clone()]
1134 );
1135 assert_eq!(
1138 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_5]),
1139 vec![id_2.clone(), id_1.clone()]
1140 );
1141 assert_eq!(index.common_ancestors(&[id_1, id_2], &[id_3]), vec![id_0]);
1142 }
1143
1144 #[test]
1145 fn test_common_ancestors_criss_cross() {
1146 let mut new_change_id = change_id_generator();
1147 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1148 let id_0 = CommitId::from_hex("000000");
1154 let id_1 = CommitId::from_hex("111111");
1155 let id_2 = CommitId::from_hex("222222");
1156 let id_3 = CommitId::from_hex("333333");
1157 let id_4 = CommitId::from_hex("444444");
1158 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1159 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1160 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0]);
1161 index.add_commit_data(id_3.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1162 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1163
1164 let mut common_ancestors = index.common_ancestors(&[id_3], &[id_4]);
1165 common_ancestors.sort();
1166 assert_eq!(common_ancestors, vec![id_1, id_2]);
1167 }
1168
1169 #[test]
1170 fn test_common_ancestors_merge_with_ancestor() {
1171 let mut new_change_id = change_id_generator();
1172 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1173 let id_0 = CommitId::from_hex("000000");
1179 let id_1 = CommitId::from_hex("111111");
1180 let id_2 = CommitId::from_hex("222222");
1181 let id_3 = CommitId::from_hex("333333");
1182 let id_4 = CommitId::from_hex("444444");
1183 let id_5 = CommitId::from_hex("555555");
1184 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1185 index.add_commit_data(id_1, new_change_id(), &[id_0.clone()]);
1186 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1187 index.add_commit_data(id_3, new_change_id(), &[id_0.clone()]);
1188 index.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone(), id_2.clone()]);
1189 index.add_commit_data(id_5.clone(), new_change_id(), &[id_0, id_2.clone()]);
1190
1191 let mut common_ancestors = index.common_ancestors(&[id_4], &[id_5]);
1192 common_ancestors.sort();
1193 assert_eq!(common_ancestors, vec![id_2]);
1194 }
1195
1196 #[test]
1197 fn test_heads() {
1198 let mut new_change_id = change_id_generator();
1199 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1200 let id_0 = CommitId::from_hex("000000");
1208 let id_1 = CommitId::from_hex("111111");
1209 let id_2 = CommitId::from_hex("222222");
1210 let id_3 = CommitId::from_hex("333333");
1211 let id_4 = CommitId::from_hex("444444");
1212 let id_5 = CommitId::from_hex("555555");
1213 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1214 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1215 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1216 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1217 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1218 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1219
1220 assert!(index.heads(&mut [].iter()).unwrap().is_empty());
1222 assert_eq!(
1224 index.heads(&mut [id_4.clone()].iter()).unwrap(),
1225 vec![id_4.clone()]
1226 );
1227 assert_eq!(
1229 index.heads(&mut [id_4.clone(), id_1].iter()).unwrap(),
1230 vec![id_4.clone()]
1231 );
1232 assert_eq!(
1234 index.heads(&mut [id_4.clone(), id_0].iter()).unwrap(),
1235 vec![id_4.clone()]
1236 );
1237 assert_eq!(
1239 index
1240 .heads(&mut [id_3.clone(), id_4.clone()].iter())
1241 .unwrap(),
1242 vec![id_4.clone(), id_3.clone()]
1243 );
1244 assert_eq!(
1246 index
1247 .heads(&mut [id_4.clone(), id_3.clone(), id_4.clone()].iter())
1248 .unwrap(),
1249 vec![id_4.clone(), id_3.clone()]
1250 );
1251 assert_eq!(
1253 index.heads(&mut [id_5.clone(), id_2].iter()).unwrap(),
1254 vec![id_5.clone()]
1255 );
1256 assert_eq!(
1258 index
1259 .heads(&mut [id_5.clone(), id_3.clone()].iter())
1260 .unwrap(),
1261 vec![id_5.clone(), id_3.clone()]
1262 );
1263
1264 assert_eq!(
1265 index.all_heads_for_gc().unwrap().collect_vec(),
1266 vec![id_3.clone(), id_5.clone()]
1267 );
1268 }
1269
1270 #[test]
1271 fn test_heads_range_with_filter() {
1272 let mut new_change_id = change_id_generator();
1273 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1274 let id_0 = CommitId::from_hex("000000");
1282 let id_1 = CommitId::from_hex("111111");
1283 let id_2 = CommitId::from_hex("222222");
1284 let id_3 = CommitId::from_hex("333333");
1285 let id_4 = CommitId::from_hex("444444");
1286 let id_5 = CommitId::from_hex("555555");
1287 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1288 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1289 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1290 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1291 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1292 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1293
1294 let heads_range = |roots: &[&CommitId],
1297 heads: &[&CommitId],
1298 parents_range: &Range<u32>,
1299 filter: &dyn Fn(CommitId) -> bool|
1300 -> Vec<CommitId> {
1301 let roots = roots
1302 .iter()
1303 .map(|id| index.as_composite().commits().commit_id_to_pos(id).unwrap())
1304 .sorted_by_key(|&pos| Reverse(pos))
1305 .collect_vec();
1306 let heads = heads
1307 .iter()
1308 .map(|id| index.as_composite().commits().commit_id_to_pos(id).unwrap())
1309 .sorted_by_key(|&pos| Reverse(pos))
1310 .collect_vec();
1311 index
1312 .as_composite()
1313 .commits()
1314 .heads_from_range_and_filter::<Infallible>(roots, heads, parents_range, |pos| {
1315 Ok(filter(
1316 index.as_composite().commits().entry_by_pos(pos).commit_id(),
1317 ))
1318 })
1319 .unwrap()
1320 .into_iter()
1321 .map(|pos| index.as_composite().commits().entry_by_pos(pos).commit_id())
1322 .collect_vec()
1323 };
1324
1325 assert!(heads_range(&[], &[], &PARENTS_RANGE_FULL, &|_| true).is_empty());
1327 assert_eq!(
1329 heads_range(&[], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|_| true),
1330 vec![id_5.clone(), id_3.clone()]
1331 );
1332 assert_eq!(
1334 heads_range(&[], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|id| id != id_5),
1335 vec![id_4.clone(), id_3.clone()]
1336 );
1337 assert_eq!(
1339 heads_range(&[&id_5], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|_| true),
1340 vec![id_3.clone()]
1341 );
1342 assert!(
1344 heads_range(&[&id_5], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|id| id
1345 != id_3)
1346 .is_empty()
1347 );
1348 assert_eq!(
1350 heads_range(&[&id_2], &[&id_4], &PARENTS_RANGE_FULL, &|_| true),
1351 vec![id_4.clone()]
1352 );
1353 assert_eq!(
1355 heads_range(&[&id_2], &[&id_4], &PARENTS_RANGE_FULL, &|id| id != id_4),
1356 vec![id_1.clone()]
1357 );
1358 assert_eq!(
1360 heads_range(
1361 &[&id_3, &id_1],
1362 &[&id_5, &id_3],
1363 &PARENTS_RANGE_FULL,
1364 &|id| id != id_5
1365 ),
1366 vec![id_4.clone()]
1367 );
1368 assert_eq!(
1370 heads_range(&[], &[&id_5, &id_4], &PARENTS_RANGE_FULL, &|id| id != id_5),
1371 vec![id_4.clone(), id_2.clone()]
1372 );
1373 assert_eq!(
1375 heads_range(&[], &[&id_5, &id_5], &PARENTS_RANGE_FULL, &|_| true),
1376 vec![id_5.clone()]
1377 );
1378 assert_eq!(
1380 heads_range(&[], &[&id_5], &PARENTS_RANGE_FULL, &|id| id != id_5),
1381 vec![id_4.clone(), id_2.clone()]
1382 );
1383 assert_eq!(
1385 heads_range(&[], &[&id_5], &(0..1), &|id| id != id_5),
1386 vec![id_4.clone()]
1387 );
1388 assert_eq!(
1390 heads_range(&[], &[&id_5], &(1..2), &|id| id != id_5),
1391 vec![id_2.clone()]
1392 );
1393 }
1394}