1#![allow(missing_docs)]
23
24mod composite;
25mod entry;
26mod mutable;
27mod readonly;
28mod rev_walk;
29mod rev_walk_queue;
30pub mod revset_engine;
31mod revset_graph_iterator;
32mod store;
33
34pub use self::composite::AsCompositeIndex;
35pub use self::composite::CompositeIndex;
36pub use self::composite::IndexLevelStats;
37pub use self::composite::IndexStats;
38pub use self::entry::IndexEntry;
39pub use self::entry::IndexPosition;
40pub use self::mutable::DefaultMutableIndex;
41pub use self::readonly::DefaultReadonlyIndex;
42pub use self::readonly::ReadonlyIndexLoadError;
43pub use self::store::DefaultIndexStore;
44pub use self::store::DefaultIndexStoreError;
45pub use self::store::DefaultIndexStoreInitError;
46
47#[cfg(test)]
48#[rustversion::attr(
49 since(1.89),
50 expect(clippy::cloned_ref_to_slice_refs, reason = "makes tests more readable")
51)]
52mod tests {
53 use std::cmp::Reverse;
54 use std::convert::Infallible;
55 use std::sync::Arc;
56
57 use itertools::Itertools as _;
58 use smallvec::smallvec_inline;
59 use test_case::test_case;
60
61 use super::composite::DynIndexSegment;
62 use super::composite::IndexSegment as _;
63 use super::entry::SmallIndexPositionsVec;
64 use super::mutable::MutableIndexSegment;
65 use super::*;
66 use crate::backend::ChangeId;
67 use crate::backend::CommitId;
68 use crate::default_index::entry::LocalPosition;
69 use crate::default_index::entry::SmallLocalPositionsVec;
70 use crate::index::Index as _;
71 use crate::object_id::HexPrefix;
72 use crate::object_id::PrefixResolution;
73 use crate::tests::new_temp_dir;
74
75 fn commit_id_generator() -> impl FnMut() -> CommitId {
77 let mut iter = (1_u128..).map(|n| CommitId::new(n.to_le_bytes().into()));
78 move || iter.next().unwrap()
79 }
80
81 fn change_id_generator() -> impl FnMut() -> ChangeId {
83 let mut iter = (1_u128..).map(|n| ChangeId::new(n.to_le_bytes().into()));
84 move || iter.next().unwrap()
85 }
86
87 #[test_case(false; "memory")]
88 #[test_case(true; "file")]
89 fn index_empty(on_disk: bool) {
90 let temp_dir = new_temp_dir();
91 let mutable_segment = MutableIndexSegment::full(3, 16);
92 let index_segment: Box<DynIndexSegment> = if on_disk {
93 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
94 Box::new(Arc::try_unwrap(saved_index).unwrap())
95 } else {
96 Box::new(mutable_segment)
97 };
98 let index = CompositeIndex::new(index_segment.as_ref());
99
100 let stats = index.stats();
102 assert_eq!(stats.num_commits, 0);
103 assert_eq!(stats.num_heads, 0);
104 assert_eq!(stats.max_generation_number, 0);
105 assert_eq!(stats.num_merges, 0);
106 assert_eq!(stats.num_changes, 0);
107 assert_eq!(index.num_commits(), 0);
108 assert!(index.entry_by_id(&CommitId::from_hex("000000")).is_none());
110 assert!(index.entry_by_id(&CommitId::from_hex("aaa111")).is_none());
111 assert!(index.entry_by_id(&CommitId::from_hex("ffffff")).is_none());
112 }
113
114 #[test_case(false; "memory")]
115 #[test_case(true; "file")]
116 fn index_root_commit(on_disk: bool) {
117 let temp_dir = new_temp_dir();
118 let mut new_change_id = change_id_generator();
119 let mut mutable_segment = MutableIndexSegment::full(3, 16);
120 let id_0 = CommitId::from_hex("000000");
121 let change_id0 = new_change_id();
122 mutable_segment.add_commit_data(id_0.clone(), change_id0.clone(), &[]);
123 let index_segment: Box<DynIndexSegment> = if on_disk {
124 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
125 Box::new(Arc::try_unwrap(saved_index).unwrap())
126 } else {
127 Box::new(mutable_segment)
128 };
129 let index = CompositeIndex::new(index_segment.as_ref());
130
131 let stats = index.stats();
133 assert_eq!(stats.num_commits, 1);
134 assert_eq!(stats.num_heads, 1);
135 assert_eq!(stats.max_generation_number, 0);
136 assert_eq!(stats.num_merges, 0);
137 assert_eq!(stats.num_changes, 1);
138 assert_eq!(index.num_commits(), 1);
139 assert_eq!(index.commit_id_to_pos(&id_0), Some(IndexPosition(0)));
141 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("aaaaaa")), None);
142 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("ffffff")), None);
143 let entry = index.entry_by_id(&id_0).unwrap();
145 assert_eq!(entry.position(), IndexPosition(0));
146 assert_eq!(entry.commit_id(), id_0);
147 assert_eq!(entry.change_id(), change_id0);
148 assert_eq!(entry.generation_number(), 0);
149 assert_eq!(entry.num_parents(), 0);
150 assert_eq!(entry.parent_positions(), SmallIndexPositionsVec::new());
151 assert_eq!(entry.parents().len(), 0);
152 }
153
154 #[test]
155 #[should_panic(expected = "parent commit is not indexed")]
156 fn index_missing_parent_commit() {
157 let mut new_change_id = change_id_generator();
158 let mut index = DefaultMutableIndex::full(3, 16);
159 let id_0 = CommitId::from_hex("000000");
160 let id_1 = CommitId::from_hex("111111");
161 index.add_commit_data(id_1, new_change_id(), &[id_0]);
162 }
163
164 #[test_case(false, false; "full in memory")]
165 #[test_case(false, true; "full on disk")]
166 #[test_case(true, false; "incremental in memory")]
167 #[test_case(true, true; "incremental on disk")]
168 fn index_multiple_commits(incremental: bool, on_disk: bool) {
169 let temp_dir = new_temp_dir();
170 let mut new_change_id = change_id_generator();
171 let mut mutable_segment = MutableIndexSegment::full(3, 16);
172 let id_0 = CommitId::from_hex("000000");
180 let change_id0 = new_change_id();
181 let id_1 = CommitId::from_hex("111111");
182 let change_id1 = new_change_id();
183 let id_2 = CommitId::from_hex("222222");
184 let change_id2 = change_id1.clone();
185 mutable_segment.add_commit_data(id_0.clone(), change_id0, &[]);
186 mutable_segment.add_commit_data(id_1.clone(), change_id1.clone(), &[id_0.clone()]);
187 mutable_segment.add_commit_data(id_2.clone(), change_id2.clone(), &[id_0.clone()]);
188
189 if incremental {
192 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
193 mutable_segment = MutableIndexSegment::incremental(initial_file);
194 }
195
196 let id_3 = CommitId::from_hex("333333");
197 let change_id3 = new_change_id();
198 let id_4 = CommitId::from_hex("444444");
199 let change_id4 = new_change_id();
200 let id_5 = CommitId::from_hex("555555");
201 let change_id5 = change_id3.clone();
202 mutable_segment.add_commit_data(id_3.clone(), change_id3.clone(), &[id_2.clone()]);
203 mutable_segment.add_commit_data(id_4.clone(), change_id4, &[id_1.clone()]);
204 mutable_segment.add_commit_data(id_5.clone(), change_id5, &[id_4.clone(), id_2.clone()]);
205 let index_segment: Box<DynIndexSegment> = if on_disk {
206 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
207 Box::new(Arc::try_unwrap(saved_index).unwrap())
208 } else {
209 Box::new(mutable_segment)
210 };
211 let index = CompositeIndex::new(index_segment.as_ref());
212
213 let stats = index.stats();
215 assert_eq!(stats.num_commits, 6);
216 assert_eq!(stats.num_heads, 2);
217 assert_eq!(stats.max_generation_number, 3);
218 assert_eq!(stats.num_merges, 1);
219 assert_eq!(stats.num_changes, 4);
220 assert_eq!(index.num_commits(), 6);
221 let entry_0 = index.entry_by_id(&id_0).unwrap();
223 let entry_1 = index.entry_by_id(&id_1).unwrap();
224 let entry_2 = index.entry_by_id(&id_2).unwrap();
225 let entry_3 = index.entry_by_id(&id_3).unwrap();
226 let entry_4 = index.entry_by_id(&id_4).unwrap();
227 let entry_5 = index.entry_by_id(&id_5).unwrap();
228 assert_eq!(entry_0.position(), IndexPosition(0));
230 assert_eq!(entry_0.commit_id(), id_0);
231 assert_eq!(entry_1.position(), IndexPosition(1));
232 assert_eq!(entry_1.commit_id(), id_1);
233 assert_eq!(entry_1.change_id(), change_id1);
234 assert_eq!(entry_1.generation_number(), 1);
235 assert_eq!(entry_1.num_parents(), 1);
236 assert_eq!(
237 entry_1.parent_positions(),
238 smallvec_inline![IndexPosition(0)]
239 );
240 assert_eq!(entry_1.parents().len(), 1);
241 assert_eq!(
242 entry_1.parents().next().unwrap().position(),
243 IndexPosition(0)
244 );
245 assert_eq!(entry_2.position(), IndexPosition(2));
246 assert_eq!(entry_2.commit_id(), id_2);
247 assert_eq!(entry_2.change_id(), change_id2);
248 assert_eq!(entry_2.generation_number(), 1);
249 assert_eq!(entry_2.num_parents(), 1);
250 assert_eq!(
251 entry_2.parent_positions(),
252 smallvec_inline![IndexPosition(0)]
253 );
254 assert_eq!(entry_3.change_id(), change_id3);
255 assert_eq!(entry_3.generation_number(), 2);
256 assert_eq!(
257 entry_3.parent_positions(),
258 smallvec_inline![IndexPosition(2)]
259 );
260 assert_eq!(entry_4.position(), IndexPosition(4));
261 assert_eq!(entry_4.generation_number(), 2);
262 assert_eq!(entry_4.num_parents(), 1);
263 assert_eq!(
264 entry_4.parent_positions(),
265 smallvec_inline![IndexPosition(1)]
266 );
267 assert_eq!(entry_5.generation_number(), 3);
268 assert_eq!(entry_5.num_parents(), 2);
269 assert_eq!(
270 entry_5.parent_positions(),
271 smallvec_inline![IndexPosition(4), IndexPosition(2)]
272 );
273 assert_eq!(entry_5.parents().len(), 2);
274 assert_eq!(
275 entry_5.parents().next().unwrap().position(),
276 IndexPosition(4)
277 );
278 assert_eq!(
279 entry_5.parents().nth(1).unwrap().position(),
280 IndexPosition(2)
281 );
282 }
283
284 #[test_case(false; "in memory")]
285 #[test_case(true; "on disk")]
286 fn index_many_parents(on_disk: bool) {
287 let temp_dir = new_temp_dir();
288 let mut new_change_id = change_id_generator();
289 let mut mutable_segment = MutableIndexSegment::full(3, 16);
290 let id_0 = CommitId::from_hex("000000");
300 let id_1 = CommitId::from_hex("111111");
301 let id_2 = CommitId::from_hex("222222");
302 let id_3 = CommitId::from_hex("333333");
303 let id_4 = CommitId::from_hex("444444");
304 let id_5 = CommitId::from_hex("555555");
305 let id_6 = CommitId::from_hex("666666");
306 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
307 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
308 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
309 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
310 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone()]);
311 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[id_0]);
312 mutable_segment.add_commit_data(
313 id_6.clone(),
314 new_change_id(),
315 &[id_1, id_2, id_3, id_4, id_5],
316 );
317 let index_segment: Box<DynIndexSegment> = if on_disk {
318 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
319 Box::new(Arc::try_unwrap(saved_index).unwrap())
320 } else {
321 Box::new(mutable_segment)
322 };
323 let index = CompositeIndex::new(index_segment.as_ref());
324
325 let stats = index.stats();
327 assert_eq!(stats.num_commits, 7);
328 assert_eq!(stats.num_heads, 1);
329 assert_eq!(stats.max_generation_number, 2);
330 assert_eq!(stats.num_merges, 1);
331
332 let entry_6 = index.entry_by_id(&id_6).unwrap();
334 assert_eq!(entry_6.commit_id(), id_6.clone());
335 assert_eq!(entry_6.num_parents(), 5);
336 assert_eq!(
337 entry_6.parent_positions(),
338 smallvec_inline![
339 IndexPosition(1),
340 IndexPosition(2),
341 IndexPosition(3),
342 IndexPosition(4),
343 IndexPosition(5),
344 ]
345 );
346 assert_eq!(entry_6.generation_number(), 2);
347 }
348
349 #[test]
350 fn resolve_commit_id_prefix() {
351 let temp_dir = new_temp_dir();
352 let mut new_change_id = change_id_generator();
353 let mut mutable_segment = MutableIndexSegment::full(3, 16);
354
355 let id_0 = CommitId::from_hex("000000");
357 let id_1 = CommitId::from_hex("009999");
358 let id_2 = CommitId::from_hex("055488");
359 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
360 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
361 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
362
363 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
365 mutable_segment = MutableIndexSegment::incremental(initial_file);
366
367 let id_3 = CommitId::from_hex("055444");
368 let id_4 = CommitId::from_hex("055555");
369 let id_5 = CommitId::from_hex("033333");
370 mutable_segment.add_commit_data(id_3, new_change_id(), &[]);
371 mutable_segment.add_commit_data(id_4, new_change_id(), &[]);
372 mutable_segment.add_commit_data(id_5, new_change_id(), &[]);
373
374 let index = mutable_segment.as_composite();
375
376 assert_eq!(
378 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_0)),
379 PrefixResolution::SingleMatch(id_0)
380 );
381 assert_eq!(
382 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_1)),
383 PrefixResolution::SingleMatch(id_1)
384 );
385 assert_eq!(
386 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_2)),
387 PrefixResolution::SingleMatch(id_2)
388 );
389 assert_eq!(
391 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("ffffff").unwrap()),
392 PrefixResolution::NoMatch
393 );
394 assert_eq!(
395 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("000001").unwrap()),
396 PrefixResolution::NoMatch
397 );
398 assert_eq!(
400 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("0").unwrap()),
401 PrefixResolution::AmbiguousMatch
402 );
403 assert_eq!(
405 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("009").unwrap()),
406 PrefixResolution::SingleMatch(CommitId::from_hex("009999"))
407 );
408 assert_eq!(
410 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("03").unwrap()),
411 PrefixResolution::SingleMatch(CommitId::from_hex("033333"))
412 );
413 assert_eq!(
415 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
416 PrefixResolution::AmbiguousMatch
417 );
418 }
419
420 #[test]
421 #[expect(clippy::redundant_clone)] fn neighbor_commit_ids() {
423 let temp_dir = new_temp_dir();
424 let mut new_change_id = change_id_generator();
425 let mut mutable_segment = MutableIndexSegment::full(3, 16);
426
427 let id_0 = CommitId::from_hex("000001");
429 let id_1 = CommitId::from_hex("009999");
430 let id_2 = CommitId::from_hex("055488");
431 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
432 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
433 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
434
435 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
437 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
438
439 let id_3 = CommitId::from_hex("055444");
440 let id_4 = CommitId::from_hex("055555");
441 let id_5 = CommitId::from_hex("033333");
442 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
443 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
444 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
445
446 assert_eq!(
448 initial_file.resolve_neighbor_commit_ids(&id_0),
449 (None, Some(id_1.clone())),
450 );
451 assert_eq!(
452 initial_file.resolve_neighbor_commit_ids(&id_1),
453 (Some(id_0.clone()), Some(id_2.clone())),
454 );
455 assert_eq!(
456 initial_file.resolve_neighbor_commit_ids(&id_2),
457 (Some(id_1.clone()), None),
458 );
459
460 assert_eq!(
462 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
463 (None, Some(id_0.clone())),
464 );
465 assert_eq!(
466 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000002")),
467 (Some(id_0.clone()), Some(id_1.clone())),
468 );
469 assert_eq!(
470 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
471 (Some(id_2.clone()), None),
472 );
473
474 assert_eq!(
476 mutable_segment.resolve_neighbor_commit_ids(&id_5),
477 (None, Some(id_3.clone())),
478 );
479 assert_eq!(
480 mutable_segment.resolve_neighbor_commit_ids(&id_3),
481 (Some(id_5.clone()), Some(id_4.clone())),
482 );
483 assert_eq!(
484 mutable_segment.resolve_neighbor_commit_ids(&id_4),
485 (Some(id_3.clone()), None),
486 );
487
488 assert_eq!(
490 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033332")),
491 (None, Some(id_5.clone())),
492 );
493 assert_eq!(
494 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
495 (Some(id_5.clone()), Some(id_3.clone())),
496 );
497 assert_eq!(
498 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
499 (Some(id_4.clone()), None),
500 );
501
502 let composite_index = CompositeIndex::new(&mutable_segment);
504 assert_eq!(
505 composite_index.resolve_neighbor_commit_ids(&id_0),
506 (None, Some(id_1.clone())),
507 );
508 assert_eq!(
509 composite_index.resolve_neighbor_commit_ids(&id_1),
510 (Some(id_0.clone()), Some(id_5.clone())),
511 );
512 assert_eq!(
513 composite_index.resolve_neighbor_commit_ids(&id_5),
514 (Some(id_1.clone()), Some(id_3.clone())),
515 );
516 assert_eq!(
517 composite_index.resolve_neighbor_commit_ids(&id_3),
518 (Some(id_5.clone()), Some(id_2.clone())),
519 );
520 assert_eq!(
521 composite_index.resolve_neighbor_commit_ids(&id_2),
522 (Some(id_3.clone()), Some(id_4.clone())),
523 );
524 assert_eq!(
525 composite_index.resolve_neighbor_commit_ids(&id_4),
526 (Some(id_2.clone()), None),
527 );
528
529 assert_eq!(
532 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
533 (None, Some(id_0.clone())),
534 );
535 assert_eq!(
536 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("010000")),
537 (Some(id_1.clone()), Some(id_5.clone())),
538 );
539 assert_eq!(
540 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
541 (Some(id_5.clone()), Some(id_3.clone())),
542 );
543 assert_eq!(
544 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
545 (Some(id_4.clone()), None),
546 );
547 }
548
549 #[test]
550 fn shortest_unique_commit_id_prefix() {
551 let temp_dir = new_temp_dir();
552 let mut new_change_id = change_id_generator();
553 let mut mutable_segment = MutableIndexSegment::full(3, 16);
554
555 let id_0 = CommitId::from_hex("000001");
557 let id_1 = CommitId::from_hex("009999");
558 let id_2 = CommitId::from_hex("055488");
559 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
560 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
561 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
562
563 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
565 mutable_segment = MutableIndexSegment::incremental(initial_file);
566
567 let id_3 = CommitId::from_hex("055444");
568 let id_4 = CommitId::from_hex("055555");
569 let id_5 = CommitId::from_hex("033333");
570 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
571 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
572 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
573
574 let index = mutable_segment.as_composite();
575
576 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_0), 3);
578 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_1), 3);
579 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_2), 5);
580 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_3), 5);
581 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_4), 4);
582 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_5), 2);
583
584 assert_eq!(
586 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("000002")),
587 6
588 );
589 assert_eq!(
590 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("010000")),
591 2
592 );
593 assert_eq!(
594 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("033334")),
595 6
596 );
597 assert_eq!(
598 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("ffffff")),
599 1
600 );
601 }
602
603 #[test]
604 fn resolve_change_id_prefix() {
605 let temp_dir = new_temp_dir();
606 let mut new_commit_id = commit_id_generator();
607 let local_positions_vec = |positions: &[u32]| -> SmallLocalPositionsVec {
608 positions.iter().copied().map(LocalPosition).collect()
609 };
610 let index_positions_vec = |positions: &[u32]| -> SmallIndexPositionsVec {
611 positions.iter().copied().map(IndexPosition).collect()
612 };
613
614 let id_0 = ChangeId::from_hex("00000001");
615 let id_1 = ChangeId::from_hex("00999999");
616 let id_2 = ChangeId::from_hex("05548888");
617 let id_3 = ChangeId::from_hex("05544444");
618 let id_4 = ChangeId::from_hex("05555555");
619 let id_5 = ChangeId::from_hex("05555333");
620
621 let mut mutable_segment = MutableIndexSegment::full(16, 4);
623 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
624 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
625 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
626 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
627 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
628 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
629
630 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
632 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
633
634 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
635 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
636 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
637 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
638 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
639
640 assert_eq!(
642 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_0)),
643 PrefixResolution::SingleMatch((id_0.clone(), local_positions_vec(&[0])))
644 );
645 assert_eq!(
646 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
647 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[1, 3])))
648 );
649 assert_eq!(
650 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_2)),
651 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
652 );
653
654 assert_eq!(
656 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
657 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[3])))
658 );
659 assert_eq!(
660 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_3)),
661 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
662 );
663 assert_eq!(
664 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_4)),
665 PrefixResolution::SingleMatch((id_4.clone(), local_positions_vec(&[2])))
666 );
667 assert_eq!(
668 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_5)),
669 PrefixResolution::SingleMatch((id_5.clone(), local_positions_vec(&[4])))
670 );
671
672 assert_eq!(
674 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("0555").unwrap()),
675 PrefixResolution::NoMatch
676 );
677 assert_eq!(
678 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("000").unwrap()),
679 PrefixResolution::NoMatch
680 );
681
682 assert_eq!(
684 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
685 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
686 );
687 assert_eq!(
688 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
689 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
690 );
691
692 assert_eq!(
694 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("00").unwrap()),
695 PrefixResolution::AmbiguousMatch
696 );
697 assert_eq!(
698 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("05555").unwrap()),
699 PrefixResolution::AmbiguousMatch
700 );
701
702 let index = mutable_segment.as_composite();
703
704 assert_eq!(
706 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_0)),
707 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
708 );
709 assert_eq!(
710 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
711 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
712 );
713 assert_eq!(
714 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_2)),
715 PrefixResolution::SingleMatch((id_2.clone(), index_positions_vec(&[2, 4, 5])))
716 );
717 assert_eq!(
718 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_3)),
719 PrefixResolution::SingleMatch((id_3.clone(), index_positions_vec(&[6, 7])))
720 );
721 assert_eq!(
722 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_4)),
723 PrefixResolution::SingleMatch((id_4.clone(), index_positions_vec(&[8])))
724 );
725 assert_eq!(
726 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_5)),
727 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
728 );
729
730 assert_eq!(
732 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("ffffffff").unwrap()),
733 PrefixResolution::NoMatch
734 );
735 assert_eq!(
736 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("00000002").unwrap()),
737 PrefixResolution::NoMatch
738 );
739
740 assert_eq!(
742 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("000").unwrap()),
743 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
744 );
745 assert_eq!(
746 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("055553").unwrap()),
747 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
748 );
749
750 assert_eq!(
752 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("009").unwrap()),
753 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
754 );
755
756 assert_eq!(
758 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("00").unwrap()),
759 PrefixResolution::AmbiguousMatch
760 );
761 assert_eq!(
762 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("05555").unwrap()),
763 PrefixResolution::AmbiguousMatch
764 );
765
766 assert_eq!(
768 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
769 PrefixResolution::AmbiguousMatch
770 );
771 }
772
773 #[test]
774 fn neighbor_change_ids() {
775 let temp_dir = new_temp_dir();
776 let mut new_commit_id = commit_id_generator();
777
778 let id_0 = ChangeId::from_hex("00000001");
779 let id_1 = ChangeId::from_hex("00999999");
780 let id_2 = ChangeId::from_hex("05548888");
781 let id_3 = ChangeId::from_hex("05544444");
782 let id_4 = ChangeId::from_hex("05555555");
783 let id_5 = ChangeId::from_hex("05555333");
784
785 let mut mutable_segment = MutableIndexSegment::full(16, 4);
787 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
788 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
789 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
790 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
791 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
792 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
793
794 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
796 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
797
798 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
799 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
800 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
801 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
802 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
803
804 assert_eq!(
806 initial_file.resolve_neighbor_change_ids(&id_0),
807 (None, Some(id_1.clone())),
808 );
809 assert_eq!(
810 initial_file.resolve_neighbor_change_ids(&id_1),
811 (Some(id_0.clone()), Some(id_2.clone())),
812 );
813 assert_eq!(
814 initial_file.resolve_neighbor_change_ids(&id_2),
815 (Some(id_1.clone()), None),
816 );
817
818 assert_eq!(
820 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
821 (None, Some(id_0.clone())),
822 );
823 assert_eq!(
824 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000002")),
825 (Some(id_0.clone()), Some(id_1.clone())),
826 );
827 assert_eq!(
828 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
829 (Some(id_2.clone()), None),
830 );
831
832 assert_eq!(
835 mutable_segment.resolve_neighbor_change_ids(&id_1),
836 (None, Some(id_3.clone())),
837 );
838 assert_eq!(
839 mutable_segment.resolve_neighbor_change_ids(&id_3),
840 (Some(id_1.clone()), Some(id_5.clone())),
841 );
842 assert_eq!(
843 mutable_segment.resolve_neighbor_change_ids(&id_5),
844 (Some(id_3.clone()), Some(id_4.clone())),
845 );
846 assert_eq!(
847 mutable_segment.resolve_neighbor_change_ids(&id_4),
848 (Some(id_5.clone()), None),
849 );
850
851 assert_eq!(
854 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("00999998")),
855 (None, Some(id_1.clone())),
856 );
857 assert_eq!(
858 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
859 (Some(id_1.clone()), Some(id_3.clone())),
860 );
861 assert_eq!(
862 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("05555332")),
863 (Some(id_3.clone()), Some(id_5.clone())),
864 );
865 assert_eq!(
866 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
867 (Some(id_4.clone()), None),
868 );
869
870 let index = mutable_segment.as_composite();
871
872 assert_eq!(
875 index.resolve_neighbor_change_ids(&id_0),
876 (None, Some(id_1.clone())),
877 );
878 assert_eq!(
879 index.resolve_neighbor_change_ids(&id_1),
880 (Some(id_0.clone()), Some(id_3.clone())),
881 );
882 assert_eq!(
883 index.resolve_neighbor_change_ids(&id_3),
884 (Some(id_1.clone()), Some(id_2.clone())),
885 );
886 assert_eq!(
887 index.resolve_neighbor_change_ids(&id_2),
888 (Some(id_3.clone()), Some(id_5.clone())),
889 );
890 assert_eq!(
891 index.resolve_neighbor_change_ids(&id_5),
892 (Some(id_2.clone()), Some(id_4.clone())),
893 );
894 assert_eq!(
895 index.resolve_neighbor_change_ids(&id_4),
896 (Some(id_5.clone()), None),
897 );
898
899 assert_eq!(
902 index.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
903 (None, Some(id_0.clone())),
904 );
905 assert_eq!(
906 index.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
907 (Some(id_1.clone()), Some(id_3.clone())),
908 );
909 assert_eq!(
910 index.resolve_neighbor_change_ids(&ChangeId::from_hex("05544555")),
911 (Some(id_3.clone()), Some(id_2.clone())),
912 );
913 assert_eq!(
914 index.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
915 (Some(id_4.clone()), None),
916 );
917 }
918
919 #[test]
920 fn shortest_unique_change_id_prefix() {
921 let temp_dir = new_temp_dir();
922 let mut new_commit_id = commit_id_generator();
923
924 let id_0 = ChangeId::from_hex("00000001");
925 let id_1 = ChangeId::from_hex("00999999");
926 let id_2 = ChangeId::from_hex("05548888");
927 let id_3 = ChangeId::from_hex("05544444");
928 let id_4 = ChangeId::from_hex("05555555");
929 let id_5 = ChangeId::from_hex("05555333");
930
931 let mut mutable_segment = MutableIndexSegment::full(16, 4);
933 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
934 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
935 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
936 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
937 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
938 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
939
940 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
942 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
943
944 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
945 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
946 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
947 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
948 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
949
950 let index = mutable_segment.as_composite();
951
952 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_0), 3);
954 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_1), 3);
955 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_2), 5);
956 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_3), 5);
957 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_4), 6);
958 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_5), 6);
959
960 assert_eq!(
962 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("00000002")),
963 8
964 );
965 assert_eq!(
966 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("01000000")),
967 2
968 );
969 assert_eq!(
970 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("05555344")),
971 7
972 );
973 assert_eq!(
974 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("ffffffff")),
975 1
976 );
977 }
978
979 #[test]
980 fn test_is_ancestor() {
981 let mut new_change_id = change_id_generator();
982 let mut index = DefaultMutableIndex::full(3, 16);
983 let id_0 = CommitId::from_hex("000000");
991 let id_1 = CommitId::from_hex("111111");
992 let id_2 = CommitId::from_hex("222222");
993 let id_3 = CommitId::from_hex("333333");
994 let id_4 = CommitId::from_hex("444444");
995 let id_5 = CommitId::from_hex("555555");
996 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
997 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
998 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
999 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1000 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1001 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1002
1003 assert!(index.is_ancestor(&id_0, &id_0));
1004 assert!(index.is_ancestor(&id_0, &id_1));
1005 assert!(index.is_ancestor(&id_2, &id_3));
1006 assert!(index.is_ancestor(&id_2, &id_5));
1007 assert!(index.is_ancestor(&id_1, &id_5));
1008 assert!(index.is_ancestor(&id_0, &id_5));
1009 assert!(!index.is_ancestor(&id_1, &id_0));
1010 assert!(!index.is_ancestor(&id_5, &id_3));
1011 assert!(!index.is_ancestor(&id_3, &id_5));
1012 assert!(!index.is_ancestor(&id_2, &id_4));
1013 assert!(!index.is_ancestor(&id_4, &id_2));
1014 }
1015
1016 #[test]
1017 fn test_common_ancestors() {
1018 let mut new_change_id = change_id_generator();
1019 let mut index = DefaultMutableIndex::full(3, 16);
1020 let id_0 = CommitId::from_hex("000000");
1029 let id_1 = CommitId::from_hex("111111");
1030 let id_2 = CommitId::from_hex("222222");
1031 let id_3 = CommitId::from_hex("333333");
1032 let id_4 = CommitId::from_hex("444444");
1033 let id_5 = CommitId::from_hex("555555");
1034 let id_6 = CommitId::from_hex("666666");
1035 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1036 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1037 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1038 index.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
1039 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1040 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1041 index.add_commit_data(id_6.clone(), new_change_id(), &[id_4.clone()]);
1042
1043 assert_eq!(
1044 index.common_ancestors(&[id_0.clone()], &[id_0.clone()]),
1045 vec![id_0.clone()]
1046 );
1047 assert_eq!(
1048 index.common_ancestors(&[id_5.clone()], &[id_5.clone()]),
1049 vec![id_5.clone()]
1050 );
1051 assert_eq!(
1052 index.common_ancestors(&[id_1.clone()], &[id_2.clone()]),
1053 vec![id_0.clone()]
1054 );
1055 assert_eq!(
1056 index.common_ancestors(&[id_2.clone()], &[id_1.clone()]),
1057 vec![id_0.clone()]
1058 );
1059 assert_eq!(
1060 index.common_ancestors(&[id_1.clone()], &[id_4.clone()]),
1061 vec![id_1.clone()]
1062 );
1063 assert_eq!(
1064 index.common_ancestors(&[id_4.clone()], &[id_1.clone()]),
1065 vec![id_1.clone()]
1066 );
1067 assert_eq!(
1068 index.common_ancestors(&[id_3.clone()], &[id_5.clone()]),
1069 vec![id_0.clone()]
1070 );
1071 assert_eq!(
1072 index.common_ancestors(&[id_5.clone()], &[id_3.clone()]),
1073 vec![id_0.clone()]
1074 );
1075 assert_eq!(
1076 index.common_ancestors(&[id_2.clone()], &[id_6.clone()]),
1077 vec![id_0.clone()]
1078 );
1079
1080 assert_eq!(
1082 index.common_ancestors(&[id_0.clone(), id_1.clone()], &[id_0.clone()]),
1083 vec![id_0.clone()]
1084 );
1085 assert_eq!(
1086 index.common_ancestors(&[id_0.clone(), id_1.clone()], &[id_1.clone()]),
1087 vec![id_1.clone()]
1088 );
1089 assert_eq!(
1090 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_1.clone()]),
1091 vec![id_1.clone()]
1092 );
1093 assert_eq!(
1094 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_4]),
1095 vec![id_1.clone()]
1096 );
1097 assert_eq!(
1098 index.common_ancestors(&[id_5.clone(), id_6.clone()], &[id_2.clone()]),
1099 &[id_2.clone()]
1100 );
1101 assert_eq!(
1104 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_5]),
1105 vec![id_2.clone(), id_1.clone()]
1106 );
1107 assert_eq!(index.common_ancestors(&[id_1, id_2], &[id_3]), vec![id_0]);
1108 }
1109
1110 #[test]
1111 fn test_common_ancestors_criss_cross() {
1112 let mut new_change_id = change_id_generator();
1113 let mut index = DefaultMutableIndex::full(3, 16);
1114 let id_0 = CommitId::from_hex("000000");
1120 let id_1 = CommitId::from_hex("111111");
1121 let id_2 = CommitId::from_hex("222222");
1122 let id_3 = CommitId::from_hex("333333");
1123 let id_4 = CommitId::from_hex("444444");
1124 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1125 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1126 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0]);
1127 index.add_commit_data(id_3.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1128 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1129
1130 let mut common_ancestors = index.common_ancestors(&[id_3], &[id_4]);
1131 common_ancestors.sort();
1132 assert_eq!(common_ancestors, vec![id_1, id_2]);
1133 }
1134
1135 #[test]
1136 fn test_common_ancestors_merge_with_ancestor() {
1137 let mut new_change_id = change_id_generator();
1138 let mut index = DefaultMutableIndex::full(3, 16);
1139 let id_0 = CommitId::from_hex("000000");
1145 let id_1 = CommitId::from_hex("111111");
1146 let id_2 = CommitId::from_hex("222222");
1147 let id_3 = CommitId::from_hex("333333");
1148 let id_4 = CommitId::from_hex("444444");
1149 let id_5 = CommitId::from_hex("555555");
1150 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1151 index.add_commit_data(id_1, new_change_id(), &[id_0.clone()]);
1152 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1153 index.add_commit_data(id_3, new_change_id(), &[id_0.clone()]);
1154 index.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone(), id_2.clone()]);
1155 index.add_commit_data(id_5.clone(), new_change_id(), &[id_0, id_2.clone()]);
1156
1157 let mut common_ancestors = index.common_ancestors(&[id_4], &[id_5]);
1158 common_ancestors.sort();
1159 assert_eq!(common_ancestors, vec![id_2]);
1160 }
1161
1162 #[test]
1163 fn test_heads() {
1164 let mut new_change_id = change_id_generator();
1165 let mut index = DefaultMutableIndex::full(3, 16);
1166 let id_0 = CommitId::from_hex("000000");
1174 let id_1 = CommitId::from_hex("111111");
1175 let id_2 = CommitId::from_hex("222222");
1176 let id_3 = CommitId::from_hex("333333");
1177 let id_4 = CommitId::from_hex("444444");
1178 let id_5 = CommitId::from_hex("555555");
1179 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1180 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1181 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1182 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1183 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1184 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1185
1186 assert!(index.heads(&mut [].iter()).unwrap().is_empty());
1188 assert_eq!(
1190 index.heads(&mut [id_4.clone()].iter()).unwrap(),
1191 vec![id_4.clone()]
1192 );
1193 assert_eq!(
1195 index.heads(&mut [id_4.clone(), id_1].iter()).unwrap(),
1196 vec![id_4.clone()]
1197 );
1198 assert_eq!(
1200 index.heads(&mut [id_4.clone(), id_0].iter()).unwrap(),
1201 vec![id_4.clone()]
1202 );
1203 assert_eq!(
1205 index
1206 .heads(&mut [id_3.clone(), id_4.clone()].iter())
1207 .unwrap(),
1208 vec![id_4.clone(), id_3.clone()]
1209 );
1210 assert_eq!(
1212 index
1213 .heads(&mut [id_4.clone(), id_3.clone(), id_4.clone()].iter())
1214 .unwrap(),
1215 vec![id_4.clone(), id_3.clone()]
1216 );
1217 assert_eq!(
1219 index.heads(&mut [id_5.clone(), id_2].iter()).unwrap(),
1220 vec![id_5.clone()]
1221 );
1222 assert_eq!(
1224 index
1225 .heads(&mut [id_5.clone(), id_3.clone()].iter())
1226 .unwrap(),
1227 vec![id_5.clone(), id_3.clone()]
1228 );
1229
1230 assert_eq!(
1231 index.all_heads_for_gc().unwrap().collect_vec(),
1232 vec![id_3.clone(), id_5.clone()]
1233 );
1234 }
1235
1236 #[test]
1237 fn test_heads_range_with_filter() {
1238 let mut new_change_id = change_id_generator();
1239 let mut index = DefaultMutableIndex::full(3, 16);
1240 let id_0 = CommitId::from_hex("000000");
1248 let id_1 = CommitId::from_hex("111111");
1249 let id_2 = CommitId::from_hex("222222");
1250 let id_3 = CommitId::from_hex("333333");
1251 let id_4 = CommitId::from_hex("444444");
1252 let id_5 = CommitId::from_hex("555555");
1253 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1254 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1255 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1256 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1257 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1258 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1259
1260 let heads_range = |roots: &[&CommitId],
1263 heads: &[&CommitId],
1264 filter: &dyn Fn(CommitId) -> bool|
1265 -> Vec<CommitId> {
1266 let roots = roots
1267 .iter()
1268 .map(|id| index.as_composite().commit_id_to_pos(id).unwrap())
1269 .sorted_by_key(|&pos| Reverse(pos))
1270 .collect_vec();
1271 let heads = heads
1272 .iter()
1273 .map(|id| index.as_composite().commit_id_to_pos(id).unwrap())
1274 .sorted_by_key(|&pos| Reverse(pos))
1275 .collect_vec();
1276 index
1277 .as_composite()
1278 .heads_from_range_and_filter::<Infallible>(roots, heads, |pos| {
1279 Ok(filter(index.as_composite().entry_by_pos(pos).commit_id()))
1280 })
1281 .unwrap()
1282 .into_iter()
1283 .map(|pos| index.as_composite().entry_by_pos(pos).commit_id())
1284 .collect_vec()
1285 };
1286
1287 assert!(heads_range(&[], &[], &|_| true).is_empty());
1289 assert_eq!(
1291 heads_range(&[], &[&id_5, &id_3], &|_| true),
1292 vec![id_5.clone(), id_3.clone()]
1293 );
1294 assert_eq!(
1296 heads_range(&[], &[&id_5, &id_3], &|id| id != id_5),
1297 vec![id_4.clone(), id_3.clone()]
1298 );
1299 assert_eq!(
1301 heads_range(&[&id_5], &[&id_5, &id_3], &|_| true),
1302 vec![id_3.clone()]
1303 );
1304 assert!(heads_range(&[&id_5], &[&id_5, &id_3], &|id| id != id_3).is_empty());
1306 assert_eq!(
1308 heads_range(&[&id_2], &[&id_4], &|_| true),
1309 vec![id_4.clone()]
1310 );
1311 assert_eq!(
1313 heads_range(&[&id_2], &[&id_4], &|id| id != id_4),
1314 vec![id_1.clone()]
1315 );
1316 assert_eq!(
1318 heads_range(&[&id_3, &id_1], &[&id_5, &id_3], &|id| id != id_5),
1319 vec![id_4.clone()]
1320 );
1321 assert_eq!(
1323 heads_range(&[], &[&id_5, &id_4], &|id| id != id_5),
1324 vec![id_4.clone(), id_2.clone()]
1325 );
1326 assert_eq!(
1328 heads_range(&[], &[&id_5, &id_5], &|_| true),
1329 vec![id_5.clone()]
1330 );
1331 }
1332}