diff --git a/lib/src/index.rs b/lib/src/index.rs index 696e9b5c1..5bb7ed9b6 100644 --- a/lib/src/index.rs +++ b/lib/src/index.rs @@ -138,39 +138,43 @@ struct CommitGraphEntry<'a> { // lowest set bit to determine which generation number the pointers point to. impl CommitGraphEntry<'_> { fn size(hash_length: usize) -> usize { - 28 + hash_length + 32 + hash_length + } + + fn is_pruned(&self) -> bool { + (&self.data[0..]).read_u32::().unwrap() != 0 } fn generation_number(&self) -> u32 { - (&self.data[0..]).read_u32::().unwrap() - } - - fn num_parents(&self) -> u32 { (&self.data[4..]).read_u32::().unwrap() } - fn parent1_pos(&self) -> u32 { + fn num_parents(&self) -> u32 { (&self.data[8..]).read_u32::().unwrap() } - fn parent2_overflow_pos(&self) -> u32 { + fn parent1_pos(&self) -> u32 { (&self.data[12..]).read_u32::().unwrap() } - fn num_predecessors(&self) -> u32 { + fn parent2_overflow_pos(&self) -> u32 { (&self.data[16..]).read_u32::().unwrap() } - fn predecessor1_pos(&self) -> u32 { + fn num_predecessors(&self) -> u32 { (&self.data[20..]).read_u32::().unwrap() } - fn predecessor2_overflow_pos(&self) -> u32 { + fn predecessor1_pos(&self) -> u32 { (&self.data[24..]).read_u32::().unwrap() } + fn predecessor2_overflow_pos(&self) -> u32 { + (&self.data[28..]).read_u32::().unwrap() + } + fn commit_id(&self) -> CommitId { - CommitId(self.data[28..28 + self.hash_length].to_vec()) + CommitId(self.data[32..32 + self.hash_length].to_vec()) } } @@ -360,6 +364,7 @@ impl PrefixResolution { #[derive(Debug)] struct MutableGraphEntry { commit_id: CommitId, + is_pruned: bool, generation_number: u32, parent_positions: Vec, predecessor_positions: Vec, @@ -406,6 +411,7 @@ impl MutableIndex { pub fn add_commit(&mut self, commit: &Commit) { self.add_commit_data( commit.id().clone(), + commit.is_pruned(), commit.parent_ids(), commit.predecessor_ids(), ); @@ -414,6 +420,7 @@ impl MutableIndex { fn add_commit_data( &mut self, id: CommitId, + is_pruned: bool, parent_ids: Vec, predecessor_ids: Vec, ) { @@ -422,6 +429,7 @@ impl MutableIndex { } let mut entry = MutableGraphEntry { commit_id: id, + is_pruned, generation_number: 0, parent_positions: vec![], predecessor_positions: vec![], @@ -475,6 +483,9 @@ impl MutableIndex { let mut parent_overflow = vec![]; let mut predecessor_overflow = vec![]; for entry in self.graph { + let flags = if entry.is_pruned { 1 } else { 0 }; + buf.write_u32::(flags).unwrap(); + buf.write_u32::(entry.generation_number) .unwrap(); @@ -574,7 +585,12 @@ impl MutableIndex { .iter() .map(|pos| self.entry_by_pos(*pos).commit_id()) .collect(); - squashed.add_commit_data(entry.commit_id(), parent_ids, predecessor_ids); + squashed.add_commit_data( + entry.commit_id(), + entry.is_pruned(), + parent_ids, + predecessor_ids, + ); } squashed } @@ -663,6 +679,8 @@ trait IndexSegment { fn segment_resolve_prefix(&self, prefix: &HexPrefix) -> PrefixResolution; + fn segment_is_pruned(&self, local_pos: u32) -> bool; + fn segment_generation_number(&self, local_pos: u32) -> u32; fn segment_commit_id(&self, local_pos: u32) -> CommitId; @@ -1089,6 +1107,11 @@ impl IndexSegment for ReadonlyIndex { } } + fn segment_is_pruned(&self, local_pos: u32) -> bool { + let graph_entry = self.graph_entry(local_pos); + graph_entry.is_pruned() + } + fn segment_generation_number(&self, local_pos: u32) -> u32 { self.graph_entry(local_pos).generation_number() } @@ -1197,6 +1220,10 @@ impl IndexSegment for MutableIndex { } } + fn segment_is_pruned(&self, local_pos: u32) -> bool { + self.graph[local_pos as usize].is_pruned + } + fn segment_generation_number(&self, local_pos: u32) -> u32 { self.graph[local_pos as usize].generation_number } @@ -1254,6 +1281,10 @@ impl IndexEntry<'_> { self.source.segment_commit_id(self.local_pos) } + fn is_pruned(&self) -> bool { + self.source.segment_is_pruned(self.local_pos) + } + pub fn num_parents(&self) -> u32 { self.source.segment_num_parents(self.local_pos) } @@ -1574,7 +1605,7 @@ mod tests { let temp_dir = tempfile::tempdir().unwrap(); let mut index = MutableIndex::full(temp_dir.path().to_owned(), 3); let id_0 = CommitId::from_hex("000000"); - index.add_commit_data(id_0.clone(), vec![], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); let index = if on_disk { IndexRef::Readonly(index.save().unwrap()) } else { @@ -1610,7 +1641,7 @@ mod tests { let mut index = MutableIndex::full(temp_dir.path().to_owned(), 3); let id_0 = CommitId::from_hex("000000"); let id_1 = CommitId::from_hex("111111"); - index.add_commit_data(id_1, vec![id_0], vec![]); + index.add_commit_data(id_1, false, vec![id_0], vec![]); } #[test_case(false, false; "full in memory")] @@ -1630,9 +1661,9 @@ mod tests { let id_0 = CommitId::from_hex("000000"); let id_1 = CommitId::from_hex("111111"); let id_2 = CommitId::from_hex("222222"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); // If testing incremental indexing, write the first three commits to one file // now and build the remainder as another segment on top. @@ -1644,13 +1675,19 @@ mod tests { let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); - index.add_commit_data(id_3.clone(), vec![id_2.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_2.clone()], vec![]); index.add_commit_data( id_4.clone(), + false, vec![id_1.clone()], vec![id_2.clone(), id_3.clone()], ); - index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()], vec![]); + index.add_commit_data( + id_5.clone(), + false, + vec![id_4.clone(), id_2.clone()], + vec![], + ); let index = if on_disk { IndexRef::Readonly(index.save().unwrap()) } else { @@ -1722,14 +1759,15 @@ mod tests { let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); let id_6 = CommitId::from_hex("666666"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_5.clone(), vec![id_0.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_4.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_5.clone(), false, vec![id_0.clone()], vec![]); index.add_commit_data( id_6.clone(), + false, vec![ id_1.clone(), id_2.clone(), @@ -1769,9 +1807,9 @@ mod tests { let id_0 = CommitId::from_hex("000000"); let id_1 = CommitId::from_hex("009999"); let id_2 = CommitId::from_hex("055488"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![], vec![]); - index.add_commit_data(id_2.clone(), vec![], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![], vec![]); + index.add_commit_data(id_2.clone(), false, vec![], vec![]); // Write the first three commits to one file and build the remainder on top. let initial_file = index.save().unwrap(); @@ -1780,9 +1818,9 @@ mod tests { let id_3 = CommitId::from_hex("055444"); let id_4 = CommitId::from_hex("055555"); let id_5 = CommitId::from_hex("033333"); - index.add_commit_data(id_3.clone(), vec![], vec![]); - index.add_commit_data(id_4.clone(), vec![], vec![]); - index.add_commit_data(id_5.clone(), vec![], vec![]); + index.add_commit_data(id_3.clone(), false, vec![], vec![]); + index.add_commit_data(id_4.clone(), false, vec![], vec![]); + index.add_commit_data(id_5.clone(), false, vec![], vec![]); // Can find commits given the full hex number assert_eq!( @@ -1844,12 +1882,17 @@ mod tests { let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_2.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_1.clone()], vec![]); - index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_2.clone()], vec![]); + index.add_commit_data(id_4.clone(), false, vec![id_1.clone()], vec![]); + index.add_commit_data( + id_5.clone(), + false, + vec![id_4.clone(), id_2.clone()], + vec![], + ); assert!(index.is_ancestor(&id_0, &id_0)); assert!(index.is_ancestor(&id_0, &id_1)); @@ -1882,12 +1925,17 @@ mod tests { let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_1.clone()], vec![]); - index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_4.clone(), false, vec![id_1.clone()], vec![]); + index.add_commit_data( + id_5.clone(), + false, + vec![id_4.clone(), id_2.clone()], + vec![], + ); assert_eq!( index.common_ancestors(&[id_0.clone()], &[id_0.clone()]), @@ -1963,11 +2011,21 @@ mod tests { let id_2 = CommitId::from_hex("222222"); let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_1.clone(), id_2.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_1.clone(), id_2.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data( + id_3.clone(), + false, + vec![id_1.clone(), id_2.clone()], + vec![], + ); + index.add_commit_data( + id_4.clone(), + false, + vec![id_1.clone(), id_2.clone()], + vec![], + ); let mut common_ancestors = index.common_ancestors(&[id_3.clone()], &[id_4.clone()]); common_ancestors.sort(); @@ -1989,12 +2047,22 @@ mod tests { let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_0.clone(), id_2.clone()], vec![]); - index.add_commit_data(id_5.clone(), vec![id_0.clone(), id_2.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data( + id_4.clone(), + false, + vec![id_0.clone(), id_2.clone()], + vec![], + ); + index.add_commit_data( + id_5.clone(), + false, + vec![id_0.clone(), id_2.clone()], + vec![], + ); let mut common_ancestors = index.common_ancestors(&[id_4.clone()], &[id_5.clone()]); common_ancestors.sort(); @@ -2018,12 +2086,17 @@ mod tests { let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_2.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_1.clone()], vec![]); - index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_2.clone()], vec![]); + index.add_commit_data(id_4.clone(), false, vec![id_1.clone()], vec![]); + index.add_commit_data( + id_5.clone(), + false, + vec![id_4.clone(), id_2.clone()], + vec![], + ); // No wanted commits let revs: Vec = index.walk_revs(&[], &[]).collect(); @@ -2086,12 +2159,17 @@ mod tests { let id_3 = CommitId::from_hex("333333"); let id_4 = CommitId::from_hex("444444"); let id_5 = CommitId::from_hex("555555"); - index.add_commit_data(id_0.clone(), vec![], vec![]); - index.add_commit_data(id_1.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_2.clone(), vec![id_0.clone()], vec![]); - index.add_commit_data(id_3.clone(), vec![id_2.clone()], vec![]); - index.add_commit_data(id_4.clone(), vec![id_1.clone()], vec![]); - index.add_commit_data(id_5.clone(), vec![id_4.clone(), id_2.clone()], vec![]); + index.add_commit_data(id_0.clone(), false, vec![], vec![]); + index.add_commit_data(id_1.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_2.clone(), false, vec![id_0.clone()], vec![]); + index.add_commit_data(id_3.clone(), false, vec![id_2.clone()], vec![]); + index.add_commit_data(id_4.clone(), false, vec![id_1.clone()], vec![]); + index.add_commit_data( + id_5.clone(), + false, + vec![id_4.clone(), id_2.clone()], + vec![], + ); // Empty input assert!(index.heads(&[]).is_empty());