1#![allow(missing_docs)]
23
24mod composite;
25mod entry;
26mod mutable;
27mod readonly;
28mod rev_walk;
29pub mod revset_engine;
30mod revset_graph_iterator;
31mod store;
32
33pub use self::composite::AsCompositeIndex;
34pub use self::composite::CompositeIndex;
35pub use self::composite::IndexLevelStats;
36pub use self::composite::IndexStats;
37pub use self::entry::IndexEntry;
38pub use self::entry::IndexPosition;
39pub use self::mutable::DefaultMutableIndex;
40pub use self::readonly::DefaultReadonlyIndex;
41pub use self::readonly::ReadonlyIndexLoadError;
42pub use self::store::DefaultIndexStore;
43pub use self::store::DefaultIndexStoreError;
44pub use self::store::DefaultIndexStoreInitError;
45
46#[cfg(test)]
47mod tests {
48 use std::sync::Arc;
49
50 use itertools::Itertools as _;
51 use smallvec::smallvec_inline;
52 use test_case::test_case;
53
54 use super::composite::DynIndexSegment;
55 use super::composite::IndexSegment as _;
56 use super::entry::SmallIndexPositionsVec;
57 use super::mutable::MutableIndexSegment;
58 use super::*;
59 use crate::backend::ChangeId;
60 use crate::backend::CommitId;
61 use crate::default_index::entry::LocalPosition;
62 use crate::default_index::entry::SmallLocalPositionsVec;
63 use crate::index::Index as _;
64 use crate::object_id::HexPrefix;
65 use crate::object_id::ObjectId as _;
66 use crate::object_id::PrefixResolution;
67 use crate::tests::new_temp_dir;
68
69 fn commit_id_generator() -> impl FnMut() -> CommitId {
71 let mut iter = (1_u128..).map(|n| CommitId::new(n.to_le_bytes().into()));
72 move || iter.next().unwrap()
73 }
74
75 fn change_id_generator() -> impl FnMut() -> ChangeId {
77 let mut iter = (1_u128..).map(|n| ChangeId::new(n.to_le_bytes().into()));
78 move || iter.next().unwrap()
79 }
80
81 #[test_case(false; "memory")]
82 #[test_case(true; "file")]
83 fn index_empty(on_disk: bool) {
84 let temp_dir = new_temp_dir();
85 let mutable_segment = MutableIndexSegment::full(3, 16);
86 let index_segment: Box<DynIndexSegment> = if on_disk {
87 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
88 Box::new(Arc::try_unwrap(saved_index).unwrap())
89 } else {
90 Box::new(mutable_segment)
91 };
92 let index = CompositeIndex::new(index_segment.as_ref());
93
94 let stats = index.stats();
96 assert_eq!(stats.num_commits, 0);
97 assert_eq!(stats.num_heads, 0);
98 assert_eq!(stats.max_generation_number, 0);
99 assert_eq!(stats.num_merges, 0);
100 assert_eq!(stats.num_changes, 0);
101 assert_eq!(index.num_commits(), 0);
102 assert!(index.entry_by_id(&CommitId::from_hex("000000")).is_none());
104 assert!(index.entry_by_id(&CommitId::from_hex("aaa111")).is_none());
105 assert!(index.entry_by_id(&CommitId::from_hex("ffffff")).is_none());
106 }
107
108 #[test_case(false; "memory")]
109 #[test_case(true; "file")]
110 fn index_root_commit(on_disk: bool) {
111 let temp_dir = new_temp_dir();
112 let mut new_change_id = change_id_generator();
113 let mut mutable_segment = MutableIndexSegment::full(3, 16);
114 let id_0 = CommitId::from_hex("000000");
115 let change_id0 = new_change_id();
116 mutable_segment.add_commit_data(id_0.clone(), change_id0.clone(), &[]);
117 let index_segment: Box<DynIndexSegment> = if on_disk {
118 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
119 Box::new(Arc::try_unwrap(saved_index).unwrap())
120 } else {
121 Box::new(mutable_segment)
122 };
123 let index = CompositeIndex::new(index_segment.as_ref());
124
125 let stats = index.stats();
127 assert_eq!(stats.num_commits, 1);
128 assert_eq!(stats.num_heads, 1);
129 assert_eq!(stats.max_generation_number, 0);
130 assert_eq!(stats.num_merges, 0);
131 assert_eq!(stats.num_changes, 1);
132 assert_eq!(index.num_commits(), 1);
133 assert_eq!(index.commit_id_to_pos(&id_0), Some(IndexPosition(0)));
135 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("aaaaaa")), None);
136 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("ffffff")), None);
137 let entry = index.entry_by_id(&id_0).unwrap();
139 assert_eq!(entry.position(), IndexPosition(0));
140 assert_eq!(entry.commit_id(), id_0);
141 assert_eq!(entry.change_id(), change_id0);
142 assert_eq!(entry.generation_number(), 0);
143 assert_eq!(entry.num_parents(), 0);
144 assert_eq!(entry.parent_positions(), SmallIndexPositionsVec::new());
145 assert_eq!(entry.parents().len(), 0);
146 }
147
148 #[test]
149 #[should_panic(expected = "parent commit is not indexed")]
150 fn index_missing_parent_commit() {
151 let mut new_change_id = change_id_generator();
152 let mut index = DefaultMutableIndex::full(3, 16);
153 let id_0 = CommitId::from_hex("000000");
154 let id_1 = CommitId::from_hex("111111");
155 index.add_commit_data(id_1, new_change_id(), &[id_0]);
156 }
157
158 #[test_case(false, false; "full in memory")]
159 #[test_case(false, true; "full on disk")]
160 #[test_case(true, false; "incremental in memory")]
161 #[test_case(true, true; "incremental on disk")]
162 fn index_multiple_commits(incremental: bool, on_disk: bool) {
163 let temp_dir = new_temp_dir();
164 let mut new_change_id = change_id_generator();
165 let mut mutable_segment = MutableIndexSegment::full(3, 16);
166 let id_0 = CommitId::from_hex("000000");
174 let change_id0 = new_change_id();
175 let id_1 = CommitId::from_hex("111111");
176 let change_id1 = new_change_id();
177 let id_2 = CommitId::from_hex("222222");
178 #[expect(clippy::redundant_clone)] let change_id2 = change_id1.clone();
182 mutable_segment.add_commit_data(id_0.clone(), change_id0, &[]);
183 mutable_segment.add_commit_data(id_1.clone(), change_id1.clone(), &[id_0.clone()]);
184 mutable_segment.add_commit_data(id_2.clone(), change_id2.clone(), &[id_0.clone()]);
185
186 if incremental {
189 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
190 mutable_segment = MutableIndexSegment::incremental(initial_file);
191 }
192
193 let id_3 = CommitId::from_hex("333333");
194 let change_id3 = new_change_id();
195 let id_4 = CommitId::from_hex("444444");
196 let change_id4 = new_change_id();
197 let id_5 = CommitId::from_hex("555555");
198 let change_id5 = change_id3.clone();
199 mutable_segment.add_commit_data(id_3.clone(), change_id3.clone(), &[id_2.clone()]);
200 mutable_segment.add_commit_data(id_4.clone(), change_id4, &[id_1.clone()]);
201 mutable_segment.add_commit_data(id_5.clone(), change_id5, &[id_4.clone(), id_2.clone()]);
202 let index_segment: Box<DynIndexSegment> = if on_disk {
203 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
204 Box::new(Arc::try_unwrap(saved_index).unwrap())
205 } else {
206 Box::new(mutable_segment)
207 };
208 let index = CompositeIndex::new(index_segment.as_ref());
209
210 let stats = index.stats();
212 assert_eq!(stats.num_commits, 6);
213 assert_eq!(stats.num_heads, 2);
214 assert_eq!(stats.max_generation_number, 3);
215 assert_eq!(stats.num_merges, 1);
216 assert_eq!(stats.num_changes, 4);
217 assert_eq!(index.num_commits(), 6);
218 let entry_0 = index.entry_by_id(&id_0).unwrap();
220 let entry_1 = index.entry_by_id(&id_1).unwrap();
221 let entry_2 = index.entry_by_id(&id_2).unwrap();
222 let entry_3 = index.entry_by_id(&id_3).unwrap();
223 let entry_4 = index.entry_by_id(&id_4).unwrap();
224 let entry_5 = index.entry_by_id(&id_5).unwrap();
225 assert_eq!(entry_0.position(), IndexPosition(0));
227 assert_eq!(entry_0.commit_id(), id_0);
228 assert_eq!(entry_1.position(), IndexPosition(1));
229 assert_eq!(entry_1.commit_id(), id_1);
230 assert_eq!(entry_1.change_id(), change_id1);
231 assert_eq!(entry_1.generation_number(), 1);
232 assert_eq!(entry_1.num_parents(), 1);
233 assert_eq!(
234 entry_1.parent_positions(),
235 smallvec_inline![IndexPosition(0)]
236 );
237 assert_eq!(entry_1.parents().len(), 1);
238 assert_eq!(
239 entry_1.parents().next().unwrap().position(),
240 IndexPosition(0)
241 );
242 assert_eq!(entry_2.position(), IndexPosition(2));
243 assert_eq!(entry_2.commit_id(), id_2);
244 assert_eq!(entry_2.change_id(), change_id2);
245 assert_eq!(entry_2.generation_number(), 1);
246 assert_eq!(entry_2.num_parents(), 1);
247 assert_eq!(
248 entry_2.parent_positions(),
249 smallvec_inline![IndexPosition(0)]
250 );
251 assert_eq!(entry_3.change_id(), change_id3);
252 assert_eq!(entry_3.generation_number(), 2);
253 assert_eq!(
254 entry_3.parent_positions(),
255 smallvec_inline![IndexPosition(2)]
256 );
257 assert_eq!(entry_4.position(), IndexPosition(4));
258 assert_eq!(entry_4.generation_number(), 2);
259 assert_eq!(entry_4.num_parents(), 1);
260 assert_eq!(
261 entry_4.parent_positions(),
262 smallvec_inline![IndexPosition(1)]
263 );
264 assert_eq!(entry_5.generation_number(), 3);
265 assert_eq!(entry_5.num_parents(), 2);
266 assert_eq!(
267 entry_5.parent_positions(),
268 smallvec_inline![IndexPosition(4), IndexPosition(2)]
269 );
270 assert_eq!(entry_5.parents().len(), 2);
271 assert_eq!(
272 entry_5.parents().next().unwrap().position(),
273 IndexPosition(4)
274 );
275 assert_eq!(
276 entry_5.parents().nth(1).unwrap().position(),
277 IndexPosition(2)
278 );
279 }
280
281 #[test_case(false; "in memory")]
282 #[test_case(true; "on disk")]
283 fn index_many_parents(on_disk: bool) {
284 let temp_dir = new_temp_dir();
285 let mut new_change_id = change_id_generator();
286 let mut mutable_segment = MutableIndexSegment::full(3, 16);
287 let id_0 = CommitId::from_hex("000000");
297 let id_1 = CommitId::from_hex("111111");
298 let id_2 = CommitId::from_hex("222222");
299 let id_3 = CommitId::from_hex("333333");
300 let id_4 = CommitId::from_hex("444444");
301 let id_5 = CommitId::from_hex("555555");
302 let id_6 = CommitId::from_hex("666666");
303 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
304 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
305 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
306 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
307 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone()]);
308 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[id_0]);
309 mutable_segment.add_commit_data(
310 id_6.clone(),
311 new_change_id(),
312 &[id_1, id_2, id_3, id_4, id_5],
313 );
314 let index_segment: Box<DynIndexSegment> = if on_disk {
315 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
316 Box::new(Arc::try_unwrap(saved_index).unwrap())
317 } else {
318 Box::new(mutable_segment)
319 };
320 let index = CompositeIndex::new(index_segment.as_ref());
321
322 let stats = index.stats();
324 assert_eq!(stats.num_commits, 7);
325 assert_eq!(stats.num_heads, 1);
326 assert_eq!(stats.max_generation_number, 2);
327 assert_eq!(stats.num_merges, 1);
328
329 let entry_6 = index.entry_by_id(&id_6).unwrap();
331 assert_eq!(entry_6.commit_id(), id_6.clone());
332 assert_eq!(entry_6.num_parents(), 5);
333 assert_eq!(
334 entry_6.parent_positions(),
335 smallvec_inline![
336 IndexPosition(1),
337 IndexPosition(2),
338 IndexPosition(3),
339 IndexPosition(4),
340 IndexPosition(5),
341 ]
342 );
343 assert_eq!(entry_6.generation_number(), 2);
344 }
345
346 #[test]
347 fn resolve_commit_id_prefix() {
348 let temp_dir = new_temp_dir();
349 let mut new_change_id = change_id_generator();
350 let mut mutable_segment = MutableIndexSegment::full(3, 16);
351
352 let id_0 = CommitId::from_hex("000000");
354 let id_1 = CommitId::from_hex("009999");
355 let id_2 = CommitId::from_hex("055488");
356 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
357 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
358 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
359
360 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
362 mutable_segment = MutableIndexSegment::incremental(initial_file);
363
364 let id_3 = CommitId::from_hex("055444");
365 let id_4 = CommitId::from_hex("055555");
366 let id_5 = CommitId::from_hex("033333");
367 mutable_segment.add_commit_data(id_3, new_change_id(), &[]);
368 mutable_segment.add_commit_data(id_4, new_change_id(), &[]);
369 mutable_segment.add_commit_data(id_5, new_change_id(), &[]);
370
371 let index = mutable_segment.as_composite();
372
373 assert_eq!(
375 index.resolve_commit_id_prefix(&HexPrefix::new(&id_0.hex()).unwrap()),
376 PrefixResolution::SingleMatch(id_0)
377 );
378 assert_eq!(
379 index.resolve_commit_id_prefix(&HexPrefix::new(&id_1.hex()).unwrap()),
380 PrefixResolution::SingleMatch(id_1)
381 );
382 assert_eq!(
383 index.resolve_commit_id_prefix(&HexPrefix::new(&id_2.hex()).unwrap()),
384 PrefixResolution::SingleMatch(id_2)
385 );
386 assert_eq!(
388 index.resolve_commit_id_prefix(&HexPrefix::new("ffffff").unwrap()),
389 PrefixResolution::NoMatch
390 );
391 assert_eq!(
392 index.resolve_commit_id_prefix(&HexPrefix::new("000001").unwrap()),
393 PrefixResolution::NoMatch
394 );
395 assert_eq!(
397 index.resolve_commit_id_prefix(&HexPrefix::new("0").unwrap()),
398 PrefixResolution::AmbiguousMatch
399 );
400 assert_eq!(
402 index.resolve_commit_id_prefix(&HexPrefix::new("009").unwrap()),
403 PrefixResolution::SingleMatch(CommitId::from_hex("009999"))
404 );
405 assert_eq!(
407 index.resolve_commit_id_prefix(&HexPrefix::new("03").unwrap()),
408 PrefixResolution::SingleMatch(CommitId::from_hex("033333"))
409 );
410 assert_eq!(
412 index.resolve_commit_id_prefix(&HexPrefix::new("0554").unwrap()),
413 PrefixResolution::AmbiguousMatch
414 );
415 }
416
417 #[test]
418 #[expect(clippy::redundant_clone)] fn neighbor_commit_ids() {
420 let temp_dir = new_temp_dir();
421 let mut new_change_id = change_id_generator();
422 let mut mutable_segment = MutableIndexSegment::full(3, 16);
423
424 let id_0 = CommitId::from_hex("000001");
426 let id_1 = CommitId::from_hex("009999");
427 let id_2 = CommitId::from_hex("055488");
428 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
429 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
430 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
431
432 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
434 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
435
436 let id_3 = CommitId::from_hex("055444");
437 let id_4 = CommitId::from_hex("055555");
438 let id_5 = CommitId::from_hex("033333");
439 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
440 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
441 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
442
443 assert_eq!(
445 initial_file.resolve_neighbor_commit_ids(&id_0),
446 (None, Some(id_1.clone())),
447 );
448 assert_eq!(
449 initial_file.resolve_neighbor_commit_ids(&id_1),
450 (Some(id_0.clone()), Some(id_2.clone())),
451 );
452 assert_eq!(
453 initial_file.resolve_neighbor_commit_ids(&id_2),
454 (Some(id_1.clone()), None),
455 );
456
457 assert_eq!(
459 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
460 (None, Some(id_0.clone())),
461 );
462 assert_eq!(
463 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000002")),
464 (Some(id_0.clone()), Some(id_1.clone())),
465 );
466 assert_eq!(
467 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
468 (Some(id_2.clone()), None),
469 );
470
471 assert_eq!(
473 mutable_segment.resolve_neighbor_commit_ids(&id_5),
474 (None, Some(id_3.clone())),
475 );
476 assert_eq!(
477 mutable_segment.resolve_neighbor_commit_ids(&id_3),
478 (Some(id_5.clone()), Some(id_4.clone())),
479 );
480 assert_eq!(
481 mutable_segment.resolve_neighbor_commit_ids(&id_4),
482 (Some(id_3.clone()), None),
483 );
484
485 assert_eq!(
487 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033332")),
488 (None, Some(id_5.clone())),
489 );
490 assert_eq!(
491 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
492 (Some(id_5.clone()), Some(id_3.clone())),
493 );
494 assert_eq!(
495 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
496 (Some(id_4.clone()), None),
497 );
498
499 let composite_index = CompositeIndex::new(&mutable_segment);
501 assert_eq!(
502 composite_index.resolve_neighbor_commit_ids(&id_0),
503 (None, Some(id_1.clone())),
504 );
505 assert_eq!(
506 composite_index.resolve_neighbor_commit_ids(&id_1),
507 (Some(id_0.clone()), Some(id_5.clone())),
508 );
509 assert_eq!(
510 composite_index.resolve_neighbor_commit_ids(&id_5),
511 (Some(id_1.clone()), Some(id_3.clone())),
512 );
513 assert_eq!(
514 composite_index.resolve_neighbor_commit_ids(&id_3),
515 (Some(id_5.clone()), Some(id_2.clone())),
516 );
517 assert_eq!(
518 composite_index.resolve_neighbor_commit_ids(&id_2),
519 (Some(id_3.clone()), Some(id_4.clone())),
520 );
521 assert_eq!(
522 composite_index.resolve_neighbor_commit_ids(&id_4),
523 (Some(id_2.clone()), None),
524 );
525
526 assert_eq!(
529 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
530 (None, Some(id_0.clone())),
531 );
532 assert_eq!(
533 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("010000")),
534 (Some(id_1.clone()), Some(id_5.clone())),
535 );
536 assert_eq!(
537 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
538 (Some(id_5.clone()), Some(id_3.clone())),
539 );
540 assert_eq!(
541 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
542 (Some(id_4.clone()), None),
543 );
544 }
545
546 #[test]
547 fn shortest_unique_commit_id_prefix() {
548 let temp_dir = new_temp_dir();
549 let mut new_change_id = change_id_generator();
550 let mut mutable_segment = MutableIndexSegment::full(3, 16);
551
552 let id_0 = CommitId::from_hex("000001");
554 let id_1 = CommitId::from_hex("009999");
555 let id_2 = CommitId::from_hex("055488");
556 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
557 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
558 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
559
560 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
562 mutable_segment = MutableIndexSegment::incremental(initial_file);
563
564 let id_3 = CommitId::from_hex("055444");
565 let id_4 = CommitId::from_hex("055555");
566 let id_5 = CommitId::from_hex("033333");
567 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
568 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
569 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
570
571 let index = mutable_segment.as_composite();
572
573 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_0), 3);
575 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_1), 3);
576 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_2), 5);
577 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_3), 5);
578 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_4), 4);
579 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_5), 2);
580
581 assert_eq!(
583 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("000002")),
584 6
585 );
586 assert_eq!(
587 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("010000")),
588 2
589 );
590 assert_eq!(
591 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("033334")),
592 6
593 );
594 assert_eq!(
595 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("ffffff")),
596 1
597 );
598 }
599
600 #[test]
601 fn resolve_change_id_prefix() {
602 let temp_dir = new_temp_dir();
603 let mut new_commit_id = commit_id_generator();
604 let local_positions_vec = |positions: &[u32]| -> SmallLocalPositionsVec {
605 positions.iter().copied().map(LocalPosition).collect()
606 };
607 let index_positions_vec = |positions: &[u32]| -> SmallIndexPositionsVec {
608 positions.iter().copied().map(IndexPosition).collect()
609 };
610
611 let id_0 = ChangeId::from_hex("00000001");
612 let id_1 = ChangeId::from_hex("00999999");
613 let id_2 = ChangeId::from_hex("05548888");
614 let id_3 = ChangeId::from_hex("05544444");
615 let id_4 = ChangeId::from_hex("05555555");
616 let id_5 = ChangeId::from_hex("05555333");
617
618 let mut mutable_segment = MutableIndexSegment::full(16, 4);
620 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
621 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
622 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
623 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
624 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
625 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
626
627 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
629 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
630
631 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
632 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
633 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
634 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
635 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
636
637 assert_eq!(
639 initial_file.resolve_change_id_prefix(&HexPrefix::new(&id_0.hex()).unwrap()),
640 PrefixResolution::SingleMatch((id_0.clone(), local_positions_vec(&[0])))
641 );
642 assert_eq!(
643 initial_file.resolve_change_id_prefix(&HexPrefix::new(&id_1.hex()).unwrap()),
644 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[1, 3])))
645 );
646 assert_eq!(
647 initial_file.resolve_change_id_prefix(&HexPrefix::new(&id_2.hex()).unwrap()),
648 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
649 );
650
651 assert_eq!(
653 mutable_segment.resolve_change_id_prefix(&HexPrefix::new(&id_1.hex()).unwrap()),
654 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[3])))
655 );
656 assert_eq!(
657 mutable_segment.resolve_change_id_prefix(&HexPrefix::new(&id_3.hex()).unwrap()),
658 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
659 );
660 assert_eq!(
661 mutable_segment.resolve_change_id_prefix(&HexPrefix::new(&id_4.hex()).unwrap()),
662 PrefixResolution::SingleMatch((id_4.clone(), local_positions_vec(&[2])))
663 );
664 assert_eq!(
665 mutable_segment.resolve_change_id_prefix(&HexPrefix::new(&id_5.hex()).unwrap()),
666 PrefixResolution::SingleMatch((id_5.clone(), local_positions_vec(&[4])))
667 );
668
669 assert_eq!(
671 initial_file.resolve_change_id_prefix(&HexPrefix::new("0555").unwrap()),
672 PrefixResolution::NoMatch
673 );
674 assert_eq!(
675 mutable_segment.resolve_change_id_prefix(&HexPrefix::new("000").unwrap()),
676 PrefixResolution::NoMatch
677 );
678
679 assert_eq!(
681 initial_file.resolve_change_id_prefix(&HexPrefix::new("0554").unwrap()),
682 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
683 );
684 assert_eq!(
685 mutable_segment.resolve_change_id_prefix(&HexPrefix::new("0554").unwrap()),
686 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
687 );
688
689 assert_eq!(
691 initial_file.resolve_change_id_prefix(&HexPrefix::new("00").unwrap()),
692 PrefixResolution::AmbiguousMatch
693 );
694 assert_eq!(
695 mutable_segment.resolve_change_id_prefix(&HexPrefix::new("05555").unwrap()),
696 PrefixResolution::AmbiguousMatch
697 );
698
699 let index = mutable_segment.as_composite();
700
701 assert_eq!(
703 index.resolve_change_id_prefix(&HexPrefix::new(&id_0.hex()).unwrap()),
704 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
705 );
706 assert_eq!(
707 index.resolve_change_id_prefix(&HexPrefix::new(&id_1.hex()).unwrap()),
708 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
709 );
710 assert_eq!(
711 index.resolve_change_id_prefix(&HexPrefix::new(&id_2.hex()).unwrap()),
712 PrefixResolution::SingleMatch((id_2.clone(), index_positions_vec(&[2, 4, 5])))
713 );
714 assert_eq!(
715 index.resolve_change_id_prefix(&HexPrefix::new(&id_3.hex()).unwrap()),
716 PrefixResolution::SingleMatch((id_3.clone(), index_positions_vec(&[6, 7])))
717 );
718 assert_eq!(
719 index.resolve_change_id_prefix(&HexPrefix::new(&id_4.hex()).unwrap()),
720 PrefixResolution::SingleMatch((id_4.clone(), index_positions_vec(&[8])))
721 );
722 assert_eq!(
723 index.resolve_change_id_prefix(&HexPrefix::new(&id_5.hex()).unwrap()),
724 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
725 );
726
727 assert_eq!(
729 index.resolve_change_id_prefix(&HexPrefix::new("ffffffff").unwrap()),
730 PrefixResolution::NoMatch
731 );
732 assert_eq!(
733 index.resolve_change_id_prefix(&HexPrefix::new("00000002").unwrap()),
734 PrefixResolution::NoMatch
735 );
736
737 assert_eq!(
739 index.resolve_change_id_prefix(&HexPrefix::new("000").unwrap()),
740 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
741 );
742 assert_eq!(
743 index.resolve_change_id_prefix(&HexPrefix::new("055553").unwrap()),
744 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
745 );
746
747 assert_eq!(
749 index.resolve_change_id_prefix(&HexPrefix::new("009").unwrap()),
750 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
751 );
752
753 assert_eq!(
755 index.resolve_change_id_prefix(&HexPrefix::new("00").unwrap()),
756 PrefixResolution::AmbiguousMatch
757 );
758 assert_eq!(
759 index.resolve_change_id_prefix(&HexPrefix::new("05555").unwrap()),
760 PrefixResolution::AmbiguousMatch
761 );
762
763 assert_eq!(
765 index.resolve_change_id_prefix(&HexPrefix::new("0554").unwrap()),
766 PrefixResolution::AmbiguousMatch
767 );
768 }
769
770 #[test]
771 fn neighbor_change_ids() {
772 let temp_dir = new_temp_dir();
773 let mut new_commit_id = commit_id_generator();
774
775 let id_0 = ChangeId::from_hex("00000001");
776 let id_1 = ChangeId::from_hex("00999999");
777 let id_2 = ChangeId::from_hex("05548888");
778 let id_3 = ChangeId::from_hex("05544444");
779 let id_4 = ChangeId::from_hex("05555555");
780 let id_5 = ChangeId::from_hex("05555333");
781
782 let mut mutable_segment = MutableIndexSegment::full(16, 4);
784 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
785 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
786 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
787 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
788 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
789 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
790
791 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
793 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
794
795 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
796 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
797 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
798 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
799 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
800
801 assert_eq!(
803 initial_file.resolve_neighbor_change_ids(&id_0),
804 (None, Some(id_1.clone())),
805 );
806 assert_eq!(
807 initial_file.resolve_neighbor_change_ids(&id_1),
808 (Some(id_0.clone()), Some(id_2.clone())),
809 );
810 assert_eq!(
811 initial_file.resolve_neighbor_change_ids(&id_2),
812 (Some(id_1.clone()), None),
813 );
814
815 assert_eq!(
817 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
818 (None, Some(id_0.clone())),
819 );
820 assert_eq!(
821 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000002")),
822 (Some(id_0.clone()), Some(id_1.clone())),
823 );
824 assert_eq!(
825 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
826 (Some(id_2.clone()), None),
827 );
828
829 assert_eq!(
832 mutable_segment.resolve_neighbor_change_ids(&id_1),
833 (None, Some(id_3.clone())),
834 );
835 assert_eq!(
836 mutable_segment.resolve_neighbor_change_ids(&id_3),
837 (Some(id_1.clone()), Some(id_5.clone())),
838 );
839 assert_eq!(
840 mutable_segment.resolve_neighbor_change_ids(&id_5),
841 (Some(id_3.clone()), Some(id_4.clone())),
842 );
843 assert_eq!(
844 mutable_segment.resolve_neighbor_change_ids(&id_4),
845 (Some(id_5.clone()), None),
846 );
847
848 assert_eq!(
851 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("00999998")),
852 (None, Some(id_1.clone())),
853 );
854 assert_eq!(
855 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
856 (Some(id_1.clone()), Some(id_3.clone())),
857 );
858 assert_eq!(
859 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("05555332")),
860 (Some(id_3.clone()), Some(id_5.clone())),
861 );
862 assert_eq!(
863 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
864 (Some(id_4.clone()), None),
865 );
866
867 let index = mutable_segment.as_composite();
868
869 assert_eq!(
872 index.resolve_neighbor_change_ids(&id_0),
873 (None, Some(id_1.clone())),
874 );
875 assert_eq!(
876 index.resolve_neighbor_change_ids(&id_1),
877 (Some(id_0.clone()), Some(id_3.clone())),
878 );
879 assert_eq!(
880 index.resolve_neighbor_change_ids(&id_3),
881 (Some(id_1.clone()), Some(id_2.clone())),
882 );
883 assert_eq!(
884 index.resolve_neighbor_change_ids(&id_2),
885 (Some(id_3.clone()), Some(id_5.clone())),
886 );
887 assert_eq!(
888 index.resolve_neighbor_change_ids(&id_5),
889 (Some(id_2.clone()), Some(id_4.clone())),
890 );
891 assert_eq!(
892 index.resolve_neighbor_change_ids(&id_4),
893 (Some(id_5.clone()), None),
894 );
895
896 assert_eq!(
899 index.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
900 (None, Some(id_0.clone())),
901 );
902 assert_eq!(
903 index.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
904 (Some(id_1.clone()), Some(id_3.clone())),
905 );
906 assert_eq!(
907 index.resolve_neighbor_change_ids(&ChangeId::from_hex("05544555")),
908 (Some(id_3.clone()), Some(id_2.clone())),
909 );
910 assert_eq!(
911 index.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
912 (Some(id_4.clone()), None),
913 );
914 }
915
916 #[test]
917 fn shortest_unique_change_id_prefix() {
918 let temp_dir = new_temp_dir();
919 let mut new_commit_id = commit_id_generator();
920
921 let id_0 = ChangeId::from_hex("00000001");
922 let id_1 = ChangeId::from_hex("00999999");
923 let id_2 = ChangeId::from_hex("05548888");
924 let id_3 = ChangeId::from_hex("05544444");
925 let id_4 = ChangeId::from_hex("05555555");
926 let id_5 = ChangeId::from_hex("05555333");
927
928 let mut mutable_segment = MutableIndexSegment::full(16, 4);
930 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
931 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
932 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
933 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
934 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
935 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
936
937 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
939 mutable_segment = MutableIndexSegment::incremental(initial_file.clone());
940
941 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
942 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
943 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
944 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
945 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
946
947 let index = mutable_segment.as_composite();
948
949 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_0), 3);
951 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_1), 3);
952 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_2), 5);
953 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_3), 5);
954 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_4), 6);
955 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_5), 6);
956
957 assert_eq!(
959 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("00000002")),
960 8
961 );
962 assert_eq!(
963 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("01000000")),
964 2
965 );
966 assert_eq!(
967 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("05555344")),
968 7
969 );
970 assert_eq!(
971 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("ffffffff")),
972 1
973 );
974 }
975
976 #[test]
977 fn test_is_ancestor() {
978 let mut new_change_id = change_id_generator();
979 let mut index = DefaultMutableIndex::full(3, 16);
980 let id_0 = CommitId::from_hex("000000");
988 let id_1 = CommitId::from_hex("111111");
989 let id_2 = CommitId::from_hex("222222");
990 let id_3 = CommitId::from_hex("333333");
991 let id_4 = CommitId::from_hex("444444");
992 let id_5 = CommitId::from_hex("555555");
993 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
994 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
995 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
996 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
997 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
998 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
999
1000 assert!(index.is_ancestor(&id_0, &id_0));
1001 assert!(index.is_ancestor(&id_0, &id_1));
1002 assert!(index.is_ancestor(&id_2, &id_3));
1003 assert!(index.is_ancestor(&id_2, &id_5));
1004 assert!(index.is_ancestor(&id_1, &id_5));
1005 assert!(index.is_ancestor(&id_0, &id_5));
1006 assert!(!index.is_ancestor(&id_1, &id_0));
1007 assert!(!index.is_ancestor(&id_5, &id_3));
1008 assert!(!index.is_ancestor(&id_3, &id_5));
1009 assert!(!index.is_ancestor(&id_2, &id_4));
1010 assert!(!index.is_ancestor(&id_4, &id_2));
1011 }
1012
1013 #[test]
1014 fn test_common_ancestors() {
1015 let mut new_change_id = change_id_generator();
1016 let mut index = DefaultMutableIndex::full(3, 16);
1017 let id_0 = CommitId::from_hex("000000");
1026 let id_1 = CommitId::from_hex("111111");
1027 let id_2 = CommitId::from_hex("222222");
1028 let id_3 = CommitId::from_hex("333333");
1029 let id_4 = CommitId::from_hex("444444");
1030 let id_5 = CommitId::from_hex("555555");
1031 let id_6 = CommitId::from_hex("666666");
1032 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1033 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1034 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1035 index.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
1036 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1037 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1038 index.add_commit_data(id_6.clone(), new_change_id(), &[id_4.clone()]);
1039
1040 assert_eq!(
1041 index.common_ancestors(&[id_0.clone()], &[id_0.clone()]),
1042 vec![id_0.clone()]
1043 );
1044 assert_eq!(
1045 index.common_ancestors(&[id_5.clone()], &[id_5.clone()]),
1046 vec![id_5.clone()]
1047 );
1048 assert_eq!(
1049 index.common_ancestors(&[id_1.clone()], &[id_2.clone()]),
1050 vec![id_0.clone()]
1051 );
1052 assert_eq!(
1053 index.common_ancestors(&[id_2.clone()], &[id_1.clone()]),
1054 vec![id_0.clone()]
1055 );
1056 assert_eq!(
1057 index.common_ancestors(&[id_1.clone()], &[id_4.clone()]),
1058 vec![id_1.clone()]
1059 );
1060 assert_eq!(
1061 index.common_ancestors(&[id_4.clone()], &[id_1.clone()]),
1062 vec![id_1.clone()]
1063 );
1064 assert_eq!(
1065 index.common_ancestors(&[id_3.clone()], &[id_5.clone()]),
1066 vec![id_0.clone()]
1067 );
1068 assert_eq!(
1069 index.common_ancestors(&[id_5.clone()], &[id_3.clone()]),
1070 vec![id_0.clone()]
1071 );
1072 assert_eq!(
1073 index.common_ancestors(&[id_2.clone()], &[id_6.clone()]),
1074 vec![id_0.clone()]
1075 );
1076
1077 assert_eq!(
1079 index.common_ancestors(&[id_0.clone(), id_1.clone()], &[id_0.clone()]),
1080 vec![id_0.clone()]
1081 );
1082 assert_eq!(
1083 index.common_ancestors(&[id_0.clone(), id_1.clone()], &[id_1.clone()]),
1084 vec![id_1.clone()]
1085 );
1086 assert_eq!(
1087 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_1.clone()]),
1088 vec![id_1.clone()]
1089 );
1090 assert_eq!(
1091 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_4]),
1092 vec![id_1.clone()]
1093 );
1094 assert_eq!(
1095 index.common_ancestors(&[id_5.clone(), id_6.clone()], &[id_2.clone()]),
1096 &[id_2.clone()]
1097 );
1098 assert_eq!(
1101 index.common_ancestors(&[id_1.clone(), id_2.clone()], &[id_5]),
1102 vec![id_1.clone(), id_2.clone()]
1103 );
1104 assert_eq!(index.common_ancestors(&[id_1, id_2], &[id_3]), vec![id_0]);
1105 }
1106
1107 #[test]
1108 fn test_common_ancestors_criss_cross() {
1109 let mut new_change_id = change_id_generator();
1110 let mut index = DefaultMutableIndex::full(3, 16);
1111 let id_0 = CommitId::from_hex("000000");
1117 let id_1 = CommitId::from_hex("111111");
1118 let id_2 = CommitId::from_hex("222222");
1119 let id_3 = CommitId::from_hex("333333");
1120 let id_4 = CommitId::from_hex("444444");
1121 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1122 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1123 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0]);
1124 index.add_commit_data(id_3.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1125 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1126
1127 let mut common_ancestors = index.common_ancestors(&[id_3], &[id_4]);
1128 common_ancestors.sort();
1129 assert_eq!(common_ancestors, vec![id_1, id_2]);
1130 }
1131
1132 #[test]
1133 fn test_common_ancestors_merge_with_ancestor() {
1134 let mut new_change_id = change_id_generator();
1135 let mut index = DefaultMutableIndex::full(3, 16);
1136 let id_0 = CommitId::from_hex("000000");
1142 let id_1 = CommitId::from_hex("111111");
1143 let id_2 = CommitId::from_hex("222222");
1144 let id_3 = CommitId::from_hex("333333");
1145 let id_4 = CommitId::from_hex("444444");
1146 let id_5 = CommitId::from_hex("555555");
1147 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1148 index.add_commit_data(id_1, new_change_id(), &[id_0.clone()]);
1149 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1150 index.add_commit_data(id_3, new_change_id(), &[id_0.clone()]);
1151 index.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone(), id_2.clone()]);
1152 index.add_commit_data(id_5.clone(), new_change_id(), &[id_0, id_2.clone()]);
1153
1154 let mut common_ancestors = index.common_ancestors(&[id_4], &[id_5]);
1155 common_ancestors.sort();
1156 assert_eq!(common_ancestors, vec![id_2]);
1157 }
1158
1159 #[test]
1160 fn test_heads() {
1161 let mut new_change_id = change_id_generator();
1162 let mut index = DefaultMutableIndex::full(3, 16);
1163 let id_0 = CommitId::from_hex("000000");
1171 let id_1 = CommitId::from_hex("111111");
1172 let id_2 = CommitId::from_hex("222222");
1173 let id_3 = CommitId::from_hex("333333");
1174 let id_4 = CommitId::from_hex("444444");
1175 let id_5 = CommitId::from_hex("555555");
1176 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1177 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1178 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1179 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1180 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1181 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1182
1183 assert!(index.heads(&mut [].iter()).unwrap().is_empty());
1185 assert_eq!(
1187 index.heads(&mut [id_4.clone()].iter()).unwrap(),
1188 vec![id_4.clone()]
1189 );
1190 assert_eq!(
1192 index.heads(&mut [id_4.clone(), id_1].iter()).unwrap(),
1193 vec![id_4.clone()]
1194 );
1195 assert_eq!(
1197 index.heads(&mut [id_4.clone(), id_0].iter()).unwrap(),
1198 vec![id_4.clone()]
1199 );
1200 assert_eq!(
1202 index
1203 .heads(&mut [id_4.clone(), id_3.clone()].iter())
1204 .unwrap(),
1205 vec![id_3.clone(), id_4]
1206 );
1207 assert_eq!(
1209 index.heads(&mut [id_5.clone(), id_2].iter()).unwrap(),
1210 vec![id_5.clone()]
1211 );
1212 assert_eq!(
1214 index
1215 .heads(&mut [id_5.clone(), id_3.clone()].iter())
1216 .unwrap(),
1217 vec![id_3.clone(), id_5.clone()]
1218 );
1219
1220 assert_eq!(
1221 index.all_heads_for_gc().unwrap().collect_vec(),
1222 vec![id_3.clone(), id_5.clone()]
1223 );
1224 }
1225}