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 fn common_ancestors(
106 index: &DefaultMutableIndex,
107 set1: &[CommitId],
108 set2: &[CommitId],
109 ) -> Vec<CommitId> {
110 index.common_ancestors(set1, set2).unwrap()
111 }
112
113 fn is_ancestor(
114 index: &DefaultMutableIndex,
115 ancestor_id: &CommitId,
116 descendant_id: &CommitId,
117 ) -> bool {
118 index.is_ancestor(ancestor_id, descendant_id).unwrap()
119 }
120
121 #[test_case(false; "memory")]
122 #[test_case(true; "file")]
123 fn index_empty(on_disk: bool) {
124 let temp_dir = new_temp_dir();
125 let mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
126 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
127 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
128 let stats = get_commit_index_stats(&saved_index);
130 assert_eq!(stats.num_commits, 0);
131 assert_eq!(stats.num_heads, 0);
132 assert_eq!(stats.max_generation_number, 0);
133 assert_eq!(stats.num_merges, 0);
134 assert_eq!(stats.num_changes, 0);
135 Box::new(Arc::try_unwrap(saved_index).unwrap())
136 } else {
137 Box::new(mutable_segment)
138 };
139 let index = CompositeCommitIndex::new(index_segment.as_ref());
140 assert_eq!(index.num_commits(), 0);
141
142 assert!(index.entry_by_id(&CommitId::from_hex("000000")).is_none());
144 assert!(index.entry_by_id(&CommitId::from_hex("aaa111")).is_none());
145 assert!(index.entry_by_id(&CommitId::from_hex("ffffff")).is_none());
146 }
147
148 #[test_case(false; "memory")]
149 #[test_case(true; "file")]
150 fn index_root_commit(on_disk: bool) {
151 let temp_dir = new_temp_dir();
152 let mut new_change_id = change_id_generator();
153 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
154 let id_0 = CommitId::from_hex("000000");
155 let change_id0 = new_change_id();
156 mutable_segment.add_commit_data(id_0.clone(), change_id0.clone(), &[]);
157 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
158 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
159 let stats = get_commit_index_stats(&saved_index);
161 assert_eq!(stats.num_commits, 1);
162 assert_eq!(stats.num_heads, 1);
163 assert_eq!(stats.max_generation_number, 0);
164 assert_eq!(stats.num_merges, 0);
165 assert_eq!(stats.num_changes, 1);
166 Box::new(Arc::try_unwrap(saved_index).unwrap())
167 } else {
168 Box::new(mutable_segment)
169 };
170 let index = CompositeCommitIndex::new(index_segment.as_ref());
171 assert_eq!(index.num_commits(), 1);
172
173 assert_eq!(index.commit_id_to_pos(&id_0), Some(GlobalCommitPosition(0)));
175 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("aaaaaa")), None);
176 assert_eq!(index.commit_id_to_pos(&CommitId::from_hex("ffffff")), None);
177 let entry = index.entry_by_id(&id_0).unwrap();
179 assert_eq!(entry.position(), GlobalCommitPosition(0));
180 assert_eq!(entry.commit_id(), id_0);
181 assert_eq!(entry.change_id(), change_id0);
182 assert_eq!(entry.generation_number(), 0);
183 assert_eq!(entry.num_parents(), 0);
184 assert_eq!(
185 entry.parent_positions(),
186 SmallGlobalCommitPositionsVec::new()
187 );
188 assert_eq!(entry.parents().len(), 0);
189 }
190
191 #[test]
192 #[should_panic(expected = "parent commit is not indexed")]
193 fn index_missing_parent_commit() {
194 let mut new_change_id = change_id_generator();
195 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
196 let id_0 = CommitId::from_hex("000000");
197 let id_1 = CommitId::from_hex("111111");
198 index.add_commit_data(id_1, new_change_id(), &[id_0]);
199 }
200
201 #[test_case(false, false; "full in memory")]
202 #[test_case(false, true; "full on disk")]
203 #[test_case(true, false; "incremental in memory")]
204 #[test_case(true, true; "incremental on disk")]
205 fn index_multiple_commits(incremental: bool, on_disk: bool) {
206 let temp_dir = new_temp_dir();
207 let mut new_change_id = change_id_generator();
208 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
209 let id_0 = CommitId::from_hex("000000");
217 let change_id0 = new_change_id();
218 let id_1 = CommitId::from_hex("111111");
219 let change_id1 = new_change_id();
220 let id_2 = CommitId::from_hex("222222");
221 let change_id2 = change_id1.clone();
222 mutable_segment.add_commit_data(id_0.clone(), change_id0, &[]);
223 mutable_segment.add_commit_data(id_1.clone(), change_id1.clone(), &[id_0.clone()]);
224 mutable_segment.add_commit_data(id_2.clone(), change_id2.clone(), &[id_0.clone()]);
225
226 if incremental {
229 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
230 mutable_segment = MutableCommitIndexSegment::incremental(initial_file);
231 }
232
233 let id_3 = CommitId::from_hex("333333");
234 let change_id3 = new_change_id();
235 let id_4 = CommitId::from_hex("444444");
236 let change_id4 = new_change_id();
237 let id_5 = CommitId::from_hex("555555");
238 let change_id5 = change_id3.clone();
239 mutable_segment.add_commit_data(id_3.clone(), change_id3.clone(), &[id_2.clone()]);
240 mutable_segment.add_commit_data(id_4.clone(), change_id4, &[id_1.clone()]);
241 mutable_segment.add_commit_data(id_5.clone(), change_id5, &[id_4.clone(), id_2.clone()]);
242 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
243 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
244 let stats = get_commit_index_stats(&saved_index);
246 assert_eq!(stats.num_commits, 6);
247 assert_eq!(stats.num_heads, 2);
248 assert_eq!(stats.max_generation_number, 3);
249 assert_eq!(stats.num_merges, 1);
250 assert_eq!(stats.num_changes, 4);
251 Box::new(Arc::try_unwrap(saved_index).unwrap())
252 } else {
253 Box::new(mutable_segment)
254 };
255 let index = CompositeCommitIndex::new(index_segment.as_ref());
256 assert_eq!(index.num_commits(), 6);
257
258 let entry_0 = index.entry_by_id(&id_0).unwrap();
260 let entry_1 = index.entry_by_id(&id_1).unwrap();
261 let entry_2 = index.entry_by_id(&id_2).unwrap();
262 let entry_3 = index.entry_by_id(&id_3).unwrap();
263 let entry_4 = index.entry_by_id(&id_4).unwrap();
264 let entry_5 = index.entry_by_id(&id_5).unwrap();
265 assert_eq!(entry_0.position(), GlobalCommitPosition(0));
267 assert_eq!(entry_0.commit_id(), id_0);
268 assert_eq!(entry_1.position(), GlobalCommitPosition(1));
269 assert_eq!(entry_1.commit_id(), id_1);
270 assert_eq!(entry_1.change_id(), change_id1);
271 assert_eq!(entry_1.generation_number(), 1);
272 assert_eq!(entry_1.num_parents(), 1);
273 assert_eq!(
274 entry_1.parent_positions(),
275 smallvec_inline![GlobalCommitPosition(0)]
276 );
277 assert_eq!(entry_1.parents().len(), 1);
278 assert_eq!(
279 entry_1.parents().next().unwrap().position(),
280 GlobalCommitPosition(0)
281 );
282 assert_eq!(entry_2.position(), GlobalCommitPosition(2));
283 assert_eq!(entry_2.commit_id(), id_2);
284 assert_eq!(entry_2.change_id(), change_id2);
285 assert_eq!(entry_2.generation_number(), 1);
286 assert_eq!(entry_2.num_parents(), 1);
287 assert_eq!(
288 entry_2.parent_positions(),
289 smallvec_inline![GlobalCommitPosition(0)]
290 );
291 assert_eq!(entry_3.change_id(), change_id3);
292 assert_eq!(entry_3.generation_number(), 2);
293 assert_eq!(
294 entry_3.parent_positions(),
295 smallvec_inline![GlobalCommitPosition(2)]
296 );
297 assert_eq!(entry_4.position(), GlobalCommitPosition(4));
298 assert_eq!(entry_4.generation_number(), 2);
299 assert_eq!(entry_4.num_parents(), 1);
300 assert_eq!(
301 entry_4.parent_positions(),
302 smallvec_inline![GlobalCommitPosition(1)]
303 );
304 assert_eq!(entry_5.generation_number(), 3);
305 assert_eq!(entry_5.num_parents(), 2);
306 assert_eq!(
307 entry_5.parent_positions(),
308 smallvec_inline![GlobalCommitPosition(4), GlobalCommitPosition(2)]
309 );
310 assert_eq!(entry_5.parents().len(), 2);
311 assert_eq!(
312 entry_5.parents().next().unwrap().position(),
313 GlobalCommitPosition(4)
314 );
315 assert_eq!(
316 entry_5.parents().nth(1).unwrap().position(),
317 GlobalCommitPosition(2)
318 );
319 }
320
321 #[test_case(false; "in memory")]
322 #[test_case(true; "on disk")]
323 fn index_many_parents(on_disk: bool) {
324 let temp_dir = new_temp_dir();
325 let mut new_change_id = change_id_generator();
326 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
327 let id_0 = CommitId::from_hex("000000");
337 let id_1 = CommitId::from_hex("111111");
338 let id_2 = CommitId::from_hex("222222");
339 let id_3 = CommitId::from_hex("333333");
340 let id_4 = CommitId::from_hex("444444");
341 let id_5 = CommitId::from_hex("555555");
342 let id_6 = CommitId::from_hex("666666");
343 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
344 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
345 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
346 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
347 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone()]);
348 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[id_0]);
349 mutable_segment.add_commit_data(
350 id_6.clone(),
351 new_change_id(),
352 &[id_1, id_2, id_3, id_4, id_5],
353 );
354 let index_segment: Box<DynCommitIndexSegment> = if on_disk {
355 let saved_index = mutable_segment.save_in(temp_dir.path()).unwrap();
356 let stats = get_commit_index_stats(&saved_index);
358 assert_eq!(stats.num_commits, 7);
359 assert_eq!(stats.num_heads, 1);
360 assert_eq!(stats.max_generation_number, 2);
361 assert_eq!(stats.num_merges, 1);
362 Box::new(Arc::try_unwrap(saved_index).unwrap())
363 } else {
364 Box::new(mutable_segment)
365 };
366 let index = CompositeCommitIndex::new(index_segment.as_ref());
367 assert_eq!(index.num_commits(), 7);
368
369 let entry_6 = index.entry_by_id(&id_6).unwrap();
371 assert_eq!(entry_6.commit_id(), id_6.clone());
372 assert_eq!(entry_6.num_parents(), 5);
373 assert_eq!(
374 entry_6.parent_positions(),
375 smallvec_inline![
376 GlobalCommitPosition(1),
377 GlobalCommitPosition(2),
378 GlobalCommitPosition(3),
379 GlobalCommitPosition(4),
380 GlobalCommitPosition(5),
381 ]
382 );
383 assert_eq!(entry_6.generation_number(), 2);
384 }
385
386 #[test]
387 fn resolve_commit_id_prefix() {
388 let temp_dir = new_temp_dir();
389 let mut new_change_id = change_id_generator();
390 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
391
392 let id_0 = CommitId::from_hex("000000");
394 let id_1 = CommitId::from_hex("009999");
395 let id_2 = CommitId::from_hex("055488");
396 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
397 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
398 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
399
400 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
402 mutable_segment = MutableCommitIndexSegment::incremental(initial_file);
403
404 let id_3 = CommitId::from_hex("055444");
405 let id_4 = CommitId::from_hex("055555");
406 let id_5 = CommitId::from_hex("033333");
407 mutable_segment.add_commit_data(id_3, new_change_id(), &[]);
408 mutable_segment.add_commit_data(id_4, new_change_id(), &[]);
409 mutable_segment.add_commit_data(id_5, new_change_id(), &[]);
410
411 let index = mutable_segment.as_composite();
412
413 assert_eq!(
415 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_0)),
416 PrefixResolution::SingleMatch(id_0)
417 );
418 assert_eq!(
419 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_1)),
420 PrefixResolution::SingleMatch(id_1)
421 );
422 assert_eq!(
423 index.resolve_commit_id_prefix(&HexPrefix::from_id(&id_2)),
424 PrefixResolution::SingleMatch(id_2)
425 );
426 assert_eq!(
428 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("ffffff").unwrap()),
429 PrefixResolution::NoMatch
430 );
431 assert_eq!(
432 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("000001").unwrap()),
433 PrefixResolution::NoMatch
434 );
435 assert_eq!(
437 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("0").unwrap()),
438 PrefixResolution::AmbiguousMatch
439 );
440 assert_eq!(
442 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("009").unwrap()),
443 PrefixResolution::SingleMatch(CommitId::from_hex("009999"))
444 );
445 assert_eq!(
447 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("03").unwrap()),
448 PrefixResolution::SingleMatch(CommitId::from_hex("033333"))
449 );
450 assert_eq!(
452 index.resolve_commit_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
453 PrefixResolution::AmbiguousMatch
454 );
455 }
456
457 #[test]
458 #[expect(clippy::redundant_clone)] fn neighbor_commit_ids() {
460 let temp_dir = new_temp_dir();
461 let mut new_change_id = change_id_generator();
462 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
463
464 let id_0 = CommitId::from_hex("000001");
466 let id_1 = CommitId::from_hex("009999");
467 let id_2 = CommitId::from_hex("055488");
468 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
469 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
470 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
471
472 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
474 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
475
476 let id_3 = CommitId::from_hex("055444");
477 let id_4 = CommitId::from_hex("055555");
478 let id_5 = CommitId::from_hex("033333");
479 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
480 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
481 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
482
483 assert_eq!(
485 initial_file.resolve_neighbor_commit_ids(&id_0),
486 (None, Some(id_1.clone())),
487 );
488 assert_eq!(
489 initial_file.resolve_neighbor_commit_ids(&id_1),
490 (Some(id_0.clone()), Some(id_2.clone())),
491 );
492 assert_eq!(
493 initial_file.resolve_neighbor_commit_ids(&id_2),
494 (Some(id_1.clone()), None),
495 );
496
497 assert_eq!(
499 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
500 (None, Some(id_0.clone())),
501 );
502 assert_eq!(
503 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("000002")),
504 (Some(id_0.clone()), Some(id_1.clone())),
505 );
506 assert_eq!(
507 initial_file.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
508 (Some(id_2.clone()), None),
509 );
510
511 assert_eq!(
513 mutable_segment.resolve_neighbor_commit_ids(&id_5),
514 (None, Some(id_3.clone())),
515 );
516 assert_eq!(
517 mutable_segment.resolve_neighbor_commit_ids(&id_3),
518 (Some(id_5.clone()), Some(id_4.clone())),
519 );
520 assert_eq!(
521 mutable_segment.resolve_neighbor_commit_ids(&id_4),
522 (Some(id_3.clone()), None),
523 );
524
525 assert_eq!(
527 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033332")),
528 (None, Some(id_5.clone())),
529 );
530 assert_eq!(
531 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
532 (Some(id_5.clone()), Some(id_3.clone())),
533 );
534 assert_eq!(
535 mutable_segment.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
536 (Some(id_4.clone()), None),
537 );
538
539 let composite_index = CompositeCommitIndex::new(&mutable_segment);
541 assert_eq!(
542 composite_index.resolve_neighbor_commit_ids(&id_0),
543 (None, Some(id_1.clone())),
544 );
545 assert_eq!(
546 composite_index.resolve_neighbor_commit_ids(&id_1),
547 (Some(id_0.clone()), Some(id_5.clone())),
548 );
549 assert_eq!(
550 composite_index.resolve_neighbor_commit_ids(&id_5),
551 (Some(id_1.clone()), Some(id_3.clone())),
552 );
553 assert_eq!(
554 composite_index.resolve_neighbor_commit_ids(&id_3),
555 (Some(id_5.clone()), Some(id_2.clone())),
556 );
557 assert_eq!(
558 composite_index.resolve_neighbor_commit_ids(&id_2),
559 (Some(id_3.clone()), Some(id_4.clone())),
560 );
561 assert_eq!(
562 composite_index.resolve_neighbor_commit_ids(&id_4),
563 (Some(id_2.clone()), None),
564 );
565
566 assert_eq!(
569 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("000000")),
570 (None, Some(id_0.clone())),
571 );
572 assert_eq!(
573 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("010000")),
574 (Some(id_1.clone()), Some(id_5.clone())),
575 );
576 assert_eq!(
577 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("033334")),
578 (Some(id_5.clone()), Some(id_3.clone())),
579 );
580 assert_eq!(
581 composite_index.resolve_neighbor_commit_ids(&CommitId::from_hex("ffffff")),
582 (Some(id_4.clone()), None),
583 );
584 }
585
586 #[test]
587 fn shortest_unique_commit_id_prefix() {
588 let temp_dir = new_temp_dir();
589 let mut new_change_id = change_id_generator();
590 let mut mutable_segment = MutableCommitIndexSegment::full(TEST_FIELD_LENGTHS);
591
592 let id_0 = CommitId::from_hex("000001");
594 let id_1 = CommitId::from_hex("009999");
595 let id_2 = CommitId::from_hex("055488");
596 mutable_segment.add_commit_data(id_0.clone(), new_change_id(), &[]);
597 mutable_segment.add_commit_data(id_1.clone(), new_change_id(), &[]);
598 mutable_segment.add_commit_data(id_2.clone(), new_change_id(), &[]);
599
600 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
602 mutable_segment = MutableCommitIndexSegment::incremental(initial_file);
603
604 let id_3 = CommitId::from_hex("055444");
605 let id_4 = CommitId::from_hex("055555");
606 let id_5 = CommitId::from_hex("033333");
607 mutable_segment.add_commit_data(id_3.clone(), new_change_id(), &[]);
608 mutable_segment.add_commit_data(id_4.clone(), new_change_id(), &[]);
609 mutable_segment.add_commit_data(id_5.clone(), new_change_id(), &[]);
610
611 let index = mutable_segment.as_composite();
612
613 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_0), 3);
615 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_1), 3);
616 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_2), 5);
617 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_3), 5);
618 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_4), 4);
619 assert_eq!(index.shortest_unique_commit_id_prefix_len(&id_5), 2);
620
621 assert_eq!(
623 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("000002")),
624 6
625 );
626 assert_eq!(
627 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("010000")),
628 2
629 );
630 assert_eq!(
631 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("033334")),
632 6
633 );
634 assert_eq!(
635 index.shortest_unique_commit_id_prefix_len(&CommitId::from_hex("ffffff")),
636 1
637 );
638 }
639
640 #[test]
641 fn resolve_change_id_prefix() {
642 let temp_dir = new_temp_dir();
643 let mut new_commit_id = commit_id_generator();
644 let local_positions_vec = |positions: &[u32]| -> SmallLocalCommitPositionsVec {
645 positions.iter().copied().map(LocalCommitPosition).collect()
646 };
647 let index_positions_vec = |positions: &[u32]| -> SmallGlobalCommitPositionsVec {
648 positions
649 .iter()
650 .copied()
651 .map(GlobalCommitPosition)
652 .collect()
653 };
654
655 let id_0 = ChangeId::from_hex("00000001");
656 let id_1 = ChangeId::from_hex("00999999");
657 let id_2 = ChangeId::from_hex("05548888");
658 let id_3 = ChangeId::from_hex("05544444");
659 let id_4 = ChangeId::from_hex("05555555");
660 let id_5 = ChangeId::from_hex("05555333");
661
662 let mut mutable_segment = MutableCommitIndexSegment::full(FieldLengths {
664 commit_id: 16,
665 change_id: 4,
666 });
667 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
668 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
669 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
670 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
671 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
672 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
673
674 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
676 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
677
678 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
679 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
680 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
681 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
682 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
683
684 assert_eq!(
686 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_0)),
687 PrefixResolution::SingleMatch((id_0.clone(), local_positions_vec(&[0])))
688 );
689 assert_eq!(
690 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
691 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[1, 3])))
692 );
693 assert_eq!(
694 initial_file.resolve_change_id_prefix(&HexPrefix::from_id(&id_2)),
695 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
696 );
697
698 assert_eq!(
700 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
701 PrefixResolution::SingleMatch((id_1.clone(), local_positions_vec(&[3])))
702 );
703 assert_eq!(
704 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_3)),
705 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
706 );
707 assert_eq!(
708 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_4)),
709 PrefixResolution::SingleMatch((id_4.clone(), local_positions_vec(&[2])))
710 );
711 assert_eq!(
712 mutable_segment.resolve_change_id_prefix(&HexPrefix::from_id(&id_5)),
713 PrefixResolution::SingleMatch((id_5.clone(), local_positions_vec(&[4])))
714 );
715
716 assert_eq!(
718 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("0555").unwrap()),
719 PrefixResolution::NoMatch
720 );
721 assert_eq!(
722 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("000").unwrap()),
723 PrefixResolution::NoMatch
724 );
725
726 assert_eq!(
728 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
729 PrefixResolution::SingleMatch((id_2.clone(), local_positions_vec(&[2, 4, 5])))
730 );
731 assert_eq!(
732 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
733 PrefixResolution::SingleMatch((id_3.clone(), local_positions_vec(&[0, 1])))
734 );
735
736 assert_eq!(
738 initial_file.resolve_change_id_prefix(&HexPrefix::try_from_hex("00").unwrap()),
739 PrefixResolution::AmbiguousMatch
740 );
741 assert_eq!(
742 mutable_segment.resolve_change_id_prefix(&HexPrefix::try_from_hex("05555").unwrap()),
743 PrefixResolution::AmbiguousMatch
744 );
745
746 let index = mutable_segment.as_composite();
747
748 assert_eq!(
750 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_0)),
751 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
752 );
753 assert_eq!(
754 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_1)),
755 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
756 );
757 assert_eq!(
758 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_2)),
759 PrefixResolution::SingleMatch((id_2.clone(), index_positions_vec(&[2, 4, 5])))
760 );
761 assert_eq!(
762 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_3)),
763 PrefixResolution::SingleMatch((id_3.clone(), index_positions_vec(&[6, 7])))
764 );
765 assert_eq!(
766 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_4)),
767 PrefixResolution::SingleMatch((id_4.clone(), index_positions_vec(&[8])))
768 );
769 assert_eq!(
770 index.resolve_change_id_prefix(&HexPrefix::from_id(&id_5)),
771 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
772 );
773
774 assert_eq!(
776 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("ffffffff").unwrap()),
777 PrefixResolution::NoMatch
778 );
779 assert_eq!(
780 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("00000002").unwrap()),
781 PrefixResolution::NoMatch
782 );
783
784 assert_eq!(
786 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("000").unwrap()),
787 PrefixResolution::SingleMatch((id_0.clone(), index_positions_vec(&[0])))
788 );
789 assert_eq!(
790 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("055553").unwrap()),
791 PrefixResolution::SingleMatch((id_5.clone(), index_positions_vec(&[10])))
792 );
793
794 assert_eq!(
796 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("009").unwrap()),
797 PrefixResolution::SingleMatch((id_1.clone(), index_positions_vec(&[1, 3, 9])))
798 );
799
800 assert_eq!(
802 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("00").unwrap()),
803 PrefixResolution::AmbiguousMatch
804 );
805 assert_eq!(
806 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("05555").unwrap()),
807 PrefixResolution::AmbiguousMatch
808 );
809
810 assert_eq!(
812 index.resolve_change_id_prefix(&HexPrefix::try_from_hex("0554").unwrap()),
813 PrefixResolution::AmbiguousMatch
814 );
815 }
816
817 #[test]
818 fn neighbor_change_ids() {
819 let temp_dir = new_temp_dir();
820 let mut new_commit_id = commit_id_generator();
821
822 let id_0 = ChangeId::from_hex("00000001");
823 let id_1 = ChangeId::from_hex("00999999");
824 let id_2 = ChangeId::from_hex("05548888");
825 let id_3 = ChangeId::from_hex("05544444");
826 let id_4 = ChangeId::from_hex("05555555");
827 let id_5 = ChangeId::from_hex("05555333");
828
829 let mut mutable_segment = MutableCommitIndexSegment::full(FieldLengths {
831 commit_id: 16,
832 change_id: 4,
833 });
834 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
835 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
836 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
837 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
838 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
839 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
840
841 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
843 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
844
845 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
846 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
847 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
848 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
849 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
850
851 assert_eq!(
853 initial_file.resolve_neighbor_change_ids(&id_0),
854 (None, Some(id_1.clone())),
855 );
856 assert_eq!(
857 initial_file.resolve_neighbor_change_ids(&id_1),
858 (Some(id_0.clone()), Some(id_2.clone())),
859 );
860 assert_eq!(
861 initial_file.resolve_neighbor_change_ids(&id_2),
862 (Some(id_1.clone()), None),
863 );
864
865 assert_eq!(
867 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
868 (None, Some(id_0.clone())),
869 );
870 assert_eq!(
871 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("00000002")),
872 (Some(id_0.clone()), Some(id_1.clone())),
873 );
874 assert_eq!(
875 initial_file.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
876 (Some(id_2.clone()), None),
877 );
878
879 assert_eq!(
882 mutable_segment.resolve_neighbor_change_ids(&id_1),
883 (None, Some(id_3.clone())),
884 );
885 assert_eq!(
886 mutable_segment.resolve_neighbor_change_ids(&id_3),
887 (Some(id_1.clone()), Some(id_5.clone())),
888 );
889 assert_eq!(
890 mutable_segment.resolve_neighbor_change_ids(&id_5),
891 (Some(id_3.clone()), Some(id_4.clone())),
892 );
893 assert_eq!(
894 mutable_segment.resolve_neighbor_change_ids(&id_4),
895 (Some(id_5.clone()), None),
896 );
897
898 assert_eq!(
901 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("00999998")),
902 (None, Some(id_1.clone())),
903 );
904 assert_eq!(
905 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
906 (Some(id_1.clone()), Some(id_3.clone())),
907 );
908 assert_eq!(
909 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("05555332")),
910 (Some(id_3.clone()), Some(id_5.clone())),
911 );
912 assert_eq!(
913 mutable_segment.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
914 (Some(id_4.clone()), None),
915 );
916
917 let index = mutable_segment.as_composite();
918
919 assert_eq!(
922 index.resolve_neighbor_change_ids(&id_0),
923 (None, Some(id_1.clone())),
924 );
925 assert_eq!(
926 index.resolve_neighbor_change_ids(&id_1),
927 (Some(id_0.clone()), Some(id_3.clone())),
928 );
929 assert_eq!(
930 index.resolve_neighbor_change_ids(&id_3),
931 (Some(id_1.clone()), Some(id_2.clone())),
932 );
933 assert_eq!(
934 index.resolve_neighbor_change_ids(&id_2),
935 (Some(id_3.clone()), Some(id_5.clone())),
936 );
937 assert_eq!(
938 index.resolve_neighbor_change_ids(&id_5),
939 (Some(id_2.clone()), Some(id_4.clone())),
940 );
941 assert_eq!(
942 index.resolve_neighbor_change_ids(&id_4),
943 (Some(id_5.clone()), None),
944 );
945
946 assert_eq!(
949 index.resolve_neighbor_change_ids(&ChangeId::from_hex("00000000")),
950 (None, Some(id_0.clone())),
951 );
952 assert_eq!(
953 index.resolve_neighbor_change_ids(&ChangeId::from_hex("01000000")),
954 (Some(id_1.clone()), Some(id_3.clone())),
955 );
956 assert_eq!(
957 index.resolve_neighbor_change_ids(&ChangeId::from_hex("05544555")),
958 (Some(id_3.clone()), Some(id_2.clone())),
959 );
960 assert_eq!(
961 index.resolve_neighbor_change_ids(&ChangeId::from_hex("ffffffff")),
962 (Some(id_4.clone()), None),
963 );
964 }
965
966 #[test]
967 fn shortest_unique_change_id_prefix() {
968 let temp_dir = new_temp_dir();
969 let mut new_commit_id = commit_id_generator();
970
971 let id_0 = ChangeId::from_hex("00000001");
972 let id_1 = ChangeId::from_hex("00999999");
973 let id_2 = ChangeId::from_hex("05548888");
974 let id_3 = ChangeId::from_hex("05544444");
975 let id_4 = ChangeId::from_hex("05555555");
976 let id_5 = ChangeId::from_hex("05555333");
977
978 let mut mutable_segment = MutableCommitIndexSegment::full(FieldLengths {
980 commit_id: 16,
981 change_id: 4,
982 });
983 mutable_segment.add_commit_data(new_commit_id(), id_0.clone(), &[]);
984 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
985 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
986 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
987 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
988 mutable_segment.add_commit_data(new_commit_id(), id_2.clone(), &[]);
989
990 let initial_file = mutable_segment.save_in(temp_dir.path()).unwrap();
992 mutable_segment = MutableCommitIndexSegment::incremental(initial_file.clone());
993
994 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
995 mutable_segment.add_commit_data(new_commit_id(), id_3.clone(), &[]);
996 mutable_segment.add_commit_data(new_commit_id(), id_4.clone(), &[]);
997 mutable_segment.add_commit_data(new_commit_id(), id_1.clone(), &[]);
998 mutable_segment.add_commit_data(new_commit_id(), id_5.clone(), &[]);
999
1000 let index = mutable_segment.as_composite();
1001
1002 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_0), 3);
1004 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_1), 3);
1005 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_2), 5);
1006 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_3), 5);
1007 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_4), 6);
1008 assert_eq!(index.shortest_unique_change_id_prefix_len(&id_5), 6);
1009
1010 assert_eq!(
1012 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("00000002")),
1013 8
1014 );
1015 assert_eq!(
1016 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("01000000")),
1017 2
1018 );
1019 assert_eq!(
1020 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("05555344")),
1021 7
1022 );
1023 assert_eq!(
1024 index.shortest_unique_change_id_prefix_len(&ChangeId::from_hex("ffffffff")),
1025 1
1026 );
1027 }
1028
1029 #[test]
1030 fn test_is_ancestor() {
1031 let mut new_change_id = change_id_generator();
1032 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1033 let id_0 = CommitId::from_hex("000000");
1041 let id_1 = CommitId::from_hex("111111");
1042 let id_2 = CommitId::from_hex("222222");
1043 let id_3 = CommitId::from_hex("333333");
1044 let id_4 = CommitId::from_hex("444444");
1045 let id_5 = CommitId::from_hex("555555");
1046 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1047 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1048 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1049 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1050 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1051 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1052
1053 assert!(is_ancestor(&index, &id_0, &id_0));
1054 assert!(is_ancestor(&index, &id_0, &id_1));
1055 assert!(is_ancestor(&index, &id_2, &id_3));
1056 assert!(is_ancestor(&index, &id_2, &id_5));
1057 assert!(is_ancestor(&index, &id_1, &id_5));
1058 assert!(is_ancestor(&index, &id_0, &id_5));
1059 assert!(!is_ancestor(&index, &id_1, &id_0));
1060 assert!(!is_ancestor(&index, &id_5, &id_3));
1061 assert!(!is_ancestor(&index, &id_3, &id_5));
1062 assert!(!is_ancestor(&index, &id_2, &id_4));
1063 assert!(!is_ancestor(&index, &id_4, &id_2));
1064 }
1065
1066 #[test]
1067 fn test_common_ancestors() {
1068 let mut new_change_id = change_id_generator();
1069 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1070 let id_0 = CommitId::from_hex("000000");
1079 let id_1 = CommitId::from_hex("111111");
1080 let id_2 = CommitId::from_hex("222222");
1081 let id_3 = CommitId::from_hex("333333");
1082 let id_4 = CommitId::from_hex("444444");
1083 let id_5 = CommitId::from_hex("555555");
1084 let id_6 = CommitId::from_hex("666666");
1085 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1086 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1087 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1088 index.add_commit_data(id_3.clone(), new_change_id(), &[id_0.clone()]);
1089 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1090 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1091 index.add_commit_data(id_6.clone(), new_change_id(), &[id_4.clone()]);
1092
1093 assert_eq!(
1094 common_ancestors(&index, &[id_0.clone()], &[id_0.clone()]),
1095 vec![id_0.clone()]
1096 );
1097 assert_eq!(
1098 common_ancestors(&index, &[id_5.clone()], &[id_5.clone()]),
1099 vec![id_5.clone()]
1100 );
1101 assert_eq!(
1102 common_ancestors(&index, &[id_1.clone()], &[id_2.clone()]),
1103 vec![id_0.clone()]
1104 );
1105 assert_eq!(
1106 common_ancestors(&index, &[id_2.clone()], &[id_1.clone()]),
1107 vec![id_0.clone()]
1108 );
1109 assert_eq!(
1110 common_ancestors(&index, &[id_1.clone()], &[id_4.clone()]),
1111 vec![id_1.clone()]
1112 );
1113 assert_eq!(
1114 common_ancestors(&index, &[id_4.clone()], &[id_1.clone()]),
1115 vec![id_1.clone()]
1116 );
1117 assert_eq!(
1118 common_ancestors(&index, &[id_3.clone()], &[id_5.clone()]),
1119 vec![id_0.clone()]
1120 );
1121 assert_eq!(
1122 common_ancestors(&index, &[id_5.clone()], &[id_3.clone()]),
1123 vec![id_0.clone()]
1124 );
1125 assert_eq!(
1126 common_ancestors(&index, &[id_2.clone()], &[id_6.clone()]),
1127 vec![id_0.clone()]
1128 );
1129
1130 assert_eq!(
1132 common_ancestors(&index, &[id_0.clone(), id_1.clone()], &[id_0.clone()]),
1133 vec![id_0.clone()]
1134 );
1135 assert_eq!(
1136 common_ancestors(&index, &[id_0.clone(), id_1.clone()], &[id_1.clone()]),
1137 vec![id_1.clone()]
1138 );
1139 assert_eq!(
1140 common_ancestors(&index, &[id_1.clone(), id_2.clone()], &[id_1.clone()]),
1141 vec![id_1.clone()]
1142 );
1143 assert_eq!(
1144 common_ancestors(&index, &[id_1.clone(), id_2.clone()], &[id_4]),
1145 vec![id_1.clone()]
1146 );
1147 assert_eq!(
1148 common_ancestors(&index, &[id_5.clone(), id_6.clone()], &[id_2.clone()]),
1149 &[id_2.clone()]
1150 );
1151 assert_eq!(
1154 common_ancestors(&index, &[id_1.clone(), id_2.clone()], &[id_5]),
1155 vec![id_2.clone(), id_1.clone()]
1156 );
1157 assert_eq!(common_ancestors(&index, &[id_1, id_2], &[id_3]), vec![id_0]);
1158 }
1159
1160 #[test]
1161 fn test_common_ancestors_criss_cross() {
1162 let mut new_change_id = change_id_generator();
1163 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1164 let id_0 = CommitId::from_hex("000000");
1170 let id_1 = CommitId::from_hex("111111");
1171 let id_2 = CommitId::from_hex("222222");
1172 let id_3 = CommitId::from_hex("333333");
1173 let id_4 = CommitId::from_hex("444444");
1174 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1175 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1176 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0]);
1177 index.add_commit_data(id_3.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1178 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone(), id_2.clone()]);
1179
1180 let mut common_ancestors = common_ancestors(&index, &[id_3], &[id_4]);
1181 common_ancestors.sort();
1182 assert_eq!(common_ancestors, vec![id_1, id_2]);
1183 }
1184
1185 #[test]
1186 fn test_common_ancestors_merge_with_ancestor() {
1187 let mut new_change_id = change_id_generator();
1188 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1189 let id_0 = CommitId::from_hex("000000");
1195 let id_1 = CommitId::from_hex("111111");
1196 let id_2 = CommitId::from_hex("222222");
1197 let id_3 = CommitId::from_hex("333333");
1198 let id_4 = CommitId::from_hex("444444");
1199 let id_5 = CommitId::from_hex("555555");
1200 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1201 index.add_commit_data(id_1, new_change_id(), &[id_0.clone()]);
1202 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1203 index.add_commit_data(id_3, new_change_id(), &[id_0.clone()]);
1204 index.add_commit_data(id_4.clone(), new_change_id(), &[id_0.clone(), id_2.clone()]);
1205 index.add_commit_data(id_5.clone(), new_change_id(), &[id_0, id_2.clone()]);
1206
1207 let mut common_ancestors = common_ancestors(&index, &[id_4], &[id_5]);
1208 common_ancestors.sort();
1209 assert_eq!(common_ancestors, vec![id_2]);
1210 }
1211
1212 #[test]
1213 fn test_heads() {
1214 let mut new_change_id = change_id_generator();
1215 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1216 let id_0 = CommitId::from_hex("000000");
1224 let id_1 = CommitId::from_hex("111111");
1225 let id_2 = CommitId::from_hex("222222");
1226 let id_3 = CommitId::from_hex("333333");
1227 let id_4 = CommitId::from_hex("444444");
1228 let id_5 = CommitId::from_hex("555555");
1229 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1230 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1231 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1232 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1233 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1234 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1235
1236 assert!(index.heads(&mut [].iter()).unwrap().is_empty());
1238 assert_eq!(
1240 index.heads(&mut [id_4.clone()].iter()).unwrap(),
1241 vec![id_4.clone()]
1242 );
1243 assert_eq!(
1245 index.heads(&mut [id_4.clone(), id_1].iter()).unwrap(),
1246 vec![id_4.clone()]
1247 );
1248 assert_eq!(
1250 index.heads(&mut [id_4.clone(), id_0].iter()).unwrap(),
1251 vec![id_4.clone()]
1252 );
1253 assert_eq!(
1255 index
1256 .heads(&mut [id_3.clone(), id_4.clone()].iter())
1257 .unwrap(),
1258 vec![id_4.clone(), id_3.clone()]
1259 );
1260 assert_eq!(
1262 index
1263 .heads(&mut [id_4.clone(), id_3.clone(), id_4.clone()].iter())
1264 .unwrap(),
1265 vec![id_4.clone(), id_3.clone()]
1266 );
1267 assert_eq!(
1269 index.heads(&mut [id_5.clone(), id_2].iter()).unwrap(),
1270 vec![id_5.clone()]
1271 );
1272 assert_eq!(
1274 index
1275 .heads(&mut [id_5.clone(), id_3.clone()].iter())
1276 .unwrap(),
1277 vec![id_5.clone(), id_3.clone()]
1278 );
1279
1280 assert_eq!(
1281 index.all_heads_for_gc().unwrap().collect_vec(),
1282 vec![id_3.clone(), id_5.clone()]
1283 );
1284 }
1285
1286 #[test]
1287 fn test_heads_range_with_filter() {
1288 let mut new_change_id = change_id_generator();
1289 let mut index = DefaultMutableIndex::full(TEST_FIELD_LENGTHS);
1290 let id_0 = CommitId::from_hex("000000");
1298 let id_1 = CommitId::from_hex("111111");
1299 let id_2 = CommitId::from_hex("222222");
1300 let id_3 = CommitId::from_hex("333333");
1301 let id_4 = CommitId::from_hex("444444");
1302 let id_5 = CommitId::from_hex("555555");
1303 index.add_commit_data(id_0.clone(), new_change_id(), &[]);
1304 index.add_commit_data(id_1.clone(), new_change_id(), &[id_0.clone()]);
1305 index.add_commit_data(id_2.clone(), new_change_id(), &[id_0.clone()]);
1306 index.add_commit_data(id_3.clone(), new_change_id(), &[id_2.clone()]);
1307 index.add_commit_data(id_4.clone(), new_change_id(), &[id_1.clone()]);
1308 index.add_commit_data(id_5.clone(), new_change_id(), &[id_4.clone(), id_2.clone()]);
1309
1310 let heads_range = |roots: &[&CommitId],
1313 heads: &[&CommitId],
1314 parents_range: &Range<u32>,
1315 filter: &dyn Fn(CommitId) -> bool|
1316 -> Vec<CommitId> {
1317 let roots = roots
1318 .iter()
1319 .map(|id| index.as_composite().commits().commit_id_to_pos(id).unwrap())
1320 .sorted_by_key(|&pos| Reverse(pos))
1321 .collect_vec();
1322 let heads = heads
1323 .iter()
1324 .map(|id| index.as_composite().commits().commit_id_to_pos(id).unwrap())
1325 .sorted_by_key(|&pos| Reverse(pos))
1326 .collect_vec();
1327 index
1328 .as_composite()
1329 .commits()
1330 .heads_from_range_and_filter::<Infallible>(roots, heads, parents_range, |pos| {
1331 Ok(filter(
1332 index.as_composite().commits().entry_by_pos(pos).commit_id(),
1333 ))
1334 })
1335 .unwrap()
1336 .into_iter()
1337 .map(|pos| index.as_composite().commits().entry_by_pos(pos).commit_id())
1338 .collect_vec()
1339 };
1340
1341 assert!(heads_range(&[], &[], &PARENTS_RANGE_FULL, &|_| true).is_empty());
1343 assert_eq!(
1345 heads_range(&[], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|_| true),
1346 vec![id_5.clone(), id_3.clone()]
1347 );
1348 assert_eq!(
1350 heads_range(&[], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|id| id != id_5),
1351 vec![id_4.clone(), id_3.clone()]
1352 );
1353 assert_eq!(
1355 heads_range(&[&id_5], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|_| true),
1356 vec![id_3.clone()]
1357 );
1358 assert!(
1360 heads_range(&[&id_5], &[&id_5, &id_3], &PARENTS_RANGE_FULL, &|id| id
1361 != id_3)
1362 .is_empty()
1363 );
1364 assert_eq!(
1366 heads_range(&[&id_2], &[&id_4], &PARENTS_RANGE_FULL, &|_| true),
1367 vec![id_4.clone()]
1368 );
1369 assert_eq!(
1371 heads_range(&[&id_2], &[&id_4], &PARENTS_RANGE_FULL, &|id| id != id_4),
1372 vec![id_1.clone()]
1373 );
1374 assert_eq!(
1376 heads_range(
1377 &[&id_3, &id_1],
1378 &[&id_5, &id_3],
1379 &PARENTS_RANGE_FULL,
1380 &|id| id != id_5
1381 ),
1382 vec![id_4.clone()]
1383 );
1384 assert_eq!(
1386 heads_range(&[], &[&id_5, &id_4], &PARENTS_RANGE_FULL, &|id| id != id_5),
1387 vec![id_4.clone(), id_2.clone()]
1388 );
1389 assert_eq!(
1391 heads_range(&[], &[&id_5, &id_5], &PARENTS_RANGE_FULL, &|_| true),
1392 vec![id_5.clone()]
1393 );
1394 assert_eq!(
1396 heads_range(&[], &[&id_5], &PARENTS_RANGE_FULL, &|id| id != id_5),
1397 vec![id_4.clone(), id_2.clone()]
1398 );
1399 assert_eq!(
1401 heads_range(&[], &[&id_5], &(0..1), &|id| id != id_5),
1402 vec![id_4.clone()]
1403 );
1404 assert_eq!(
1406 heads_range(&[], &[&id_5], &(1..2), &|id| id != id_5),
1407 vec![id_2.clone()]
1408 );
1409 }
1410}