Show More
@@ -18,11 +18,12 b' use crate::{' | |||
|
18 | 18 | }; |
|
19 | 19 | |
|
20 | 20 | pub const INDEX_ENTRY_SIZE: usize = 64; |
|
21 | pub const INDEX_HEADER_SIZE: usize = 4; | |
|
21 | 22 | pub const COMPRESSION_MODE_INLINE: u8 = 2; |
|
22 | 23 | |
|
23 | 24 | #[derive(Debug)] |
|
24 | 25 | pub struct IndexHeader { |
|
25 |
pub(super) header_bytes: [u8; |
|
|
26 | pub(super) header_bytes: [u8; INDEX_HEADER_SIZE], | |
|
26 | 27 | } |
|
27 | 28 | |
|
28 | 29 | #[derive(Copy, Clone)] |
@@ -92,14 +93,21 b' struct IndexData {' | |||
|
92 | 93 | truncation: Option<usize>, |
|
93 | 94 | /// Bytes that were added after reading the index |
|
94 | 95 | added: Vec<u8>, |
|
96 | first_entry: [u8; INDEX_ENTRY_SIZE], | |
|
95 | 97 | } |
|
96 | 98 | |
|
97 | 99 | impl IndexData { |
|
98 | 100 | pub fn new(bytes: Box<dyn Deref<Target = [u8]> + Send + Sync>) -> Self { |
|
101 | let mut first_entry = [0; INDEX_ENTRY_SIZE]; | |
|
102 | if bytes.len() >= INDEX_ENTRY_SIZE { | |
|
103 | first_entry[INDEX_HEADER_SIZE..] | |
|
104 | .copy_from_slice(&bytes[INDEX_HEADER_SIZE..INDEX_ENTRY_SIZE]) | |
|
105 | } | |
|
99 | 106 | Self { |
|
100 | 107 | bytes, |
|
101 | 108 | truncation: None, |
|
102 | 109 | added: vec![], |
|
110 | first_entry, | |
|
103 | 111 | } |
|
104 | 112 | } |
|
105 | 113 | |
@@ -356,7 +364,6 b' impl Index {' | |||
|
356 | 364 | let end = offset + INDEX_ENTRY_SIZE; |
|
357 | 365 | let entry = IndexEntry { |
|
358 | 366 | bytes: &bytes[offset..end], |
|
359 | offset_override: None, | |
|
360 | 367 | }; |
|
361 | 368 | |
|
362 | 369 | offset += INDEX_ENTRY_SIZE + entry.compressed_len() as usize; |
@@ -449,11 +456,17 b' impl Index {' | |||
|
449 | 456 | if rev == NULL_REVISION { |
|
450 | 457 | return None; |
|
451 | 458 | } |
|
452 | Some(if self.is_inline() { | |
|
453 | self.get_entry_inline(rev) | |
|
459 | if rev.0 == 0 { | |
|
460 | Some(IndexEntry { | |
|
461 | bytes: &self.bytes.first_entry[..], | |
|
462 | }) | |
|
454 | 463 | } else { |
|
455 | self.get_entry_separated(rev) | |
|
456 | }) | |
|
464 | Some(if self.is_inline() { | |
|
465 | self.get_entry_inline(rev) | |
|
466 | } else { | |
|
467 | self.get_entry_separated(rev) | |
|
468 | }) | |
|
469 | } | |
|
457 | 470 | } |
|
458 | 471 | |
|
459 | 472 | /// Return the binary content of the index entry for the given revision |
@@ -512,13 +525,7 b' impl Index {' | |||
|
512 | 525 | let end = start + INDEX_ENTRY_SIZE; |
|
513 | 526 | let bytes = &self.bytes[start..end]; |
|
514 | 527 | |
|
515 | // See IndexEntry for an explanation of this override. | |
|
516 | let offset_override = Some(end); | |
|
517 | ||
|
518 | IndexEntry { | |
|
519 | bytes, | |
|
520 | offset_override, | |
|
521 | } | |
|
528 | IndexEntry { bytes } | |
|
522 | 529 | } |
|
523 | 530 | |
|
524 | 531 | fn get_entry_separated(&self, rev: Revision) -> IndexEntry { |
@@ -526,20 +533,12 b' impl Index {' | |||
|
526 | 533 | let end = start + INDEX_ENTRY_SIZE; |
|
527 | 534 | let bytes = &self.bytes[start..end]; |
|
528 | 535 | |
|
529 | // Override the offset of the first revision as its bytes are used | |
|
530 | // for the index's metadata (saving space because it is always 0) | |
|
531 | let offset_override = if rev == Revision(0) { Some(0) } else { None }; | |
|
532 | ||
|
533 | IndexEntry { | |
|
534 | bytes, | |
|
535 | offset_override, | |
|
536 | } | |
|
536 | IndexEntry { bytes } | |
|
537 | 537 | } |
|
538 | 538 | |
|
539 | 539 | fn null_entry(&self) -> IndexEntry { |
|
540 | 540 | IndexEntry { |
|
541 | 541 | bytes: &[0; INDEX_ENTRY_SIZE], |
|
542 | offset_override: Some(0), | |
|
543 | 542 | } |
|
544 | 543 | } |
|
545 | 544 | |
@@ -755,13 +754,20 b' impl Index {' | |||
|
755 | 754 | revision_data: RevisionDataParams, |
|
756 | 755 | ) -> Result<(), RevlogError> { |
|
757 | 756 | revision_data.validate()?; |
|
757 | let entry_v1 = revision_data.into_v1(); | |
|
758 | let entry_bytes = entry_v1.as_bytes(); | |
|
759 | if self.bytes.len() == 0 { | |
|
760 | self.bytes.first_entry[INDEX_HEADER_SIZE..].copy_from_slice( | |
|
761 | &entry_bytes[INDEX_HEADER_SIZE..INDEX_ENTRY_SIZE], | |
|
762 | ) | |
|
763 | } | |
|
758 | 764 | if self.is_inline() { |
|
759 | 765 | let new_offset = self.bytes.len(); |
|
760 | 766 | if let Some(offsets) = &mut *self.get_offsets_mut() { |
|
761 | 767 | offsets.push(new_offset) |
|
762 | 768 | } |
|
763 | 769 | } |
|
764 |
self.bytes.added.extend( |
|
|
770 | self.bytes.added.extend(entry_bytes); | |
|
765 | 771 | self.clear_head_revs(); |
|
766 | 772 | Ok(()) |
|
767 | 773 | } |
@@ -1654,7 +1660,6 b' fn inline_scan(bytes: &[u8]) -> (usize, ' | |||
|
1654 | 1660 | let end = offset + INDEX_ENTRY_SIZE; |
|
1655 | 1661 | let entry = IndexEntry { |
|
1656 | 1662 | bytes: &bytes[offset..end], |
|
1657 | offset_override: None, | |
|
1658 | 1663 | }; |
|
1659 | 1664 | |
|
1660 | 1665 | offset += INDEX_ENTRY_SIZE + entry.compressed_len() as usize; |
@@ -1678,29 +1683,14 b' impl super::RevlogIndex for Index {' | |||
|
1678 | 1683 | #[derive(Debug)] |
|
1679 | 1684 | pub struct IndexEntry<'a> { |
|
1680 | 1685 | bytes: &'a [u8], |
|
1681 | /// Allows to override the offset value of the entry. | |
|
1682 | /// | |
|
1683 | /// For interleaved index and data, the offset stored in the index | |
|
1684 | /// corresponds to the separated data offset. | |
|
1685 | /// It has to be overridden with the actual offset in the interleaved | |
|
1686 | /// index which is just after the index block. | |
|
1687 | /// | |
|
1688 | /// For separated index and data, the offset stored in the first index | |
|
1689 | /// entry is mixed with the index headers. | |
|
1690 | /// It has to be overridden with 0. | |
|
1691 | offset_override: Option<usize>, | |
|
1692 | 1686 | } |
|
1693 | 1687 | |
|
1694 | 1688 | impl<'a> IndexEntry<'a> { |
|
1695 | 1689 | /// Return the offset of the data. |
|
1696 | 1690 | pub fn offset(&self) -> usize { |
|
1697 | if let Some(offset_override) = self.offset_override { | |
|
1698 | offset_override | |
|
1699 | } else { | |
|
1700 | let mut bytes = [0; 8]; | |
|
1701 | bytes[2..8].copy_from_slice(&self.bytes[0..=5]); | |
|
1702 | BigEndian::read_u64(&bytes[..]) as usize | |
|
1703 | } | |
|
1691 | let mut bytes = [0; 8]; | |
|
1692 | bytes[2..8].copy_from_slice(&self.bytes[0..=5]); | |
|
1693 | BigEndian::read_u64(&bytes[..]) as usize | |
|
1704 | 1694 | } |
|
1705 | 1695 | pub fn raw_offset(&self) -> u64 { |
|
1706 | 1696 | BigEndian::read_u64(&self.bytes[0..8]) |
@@ -1956,32 +1946,15 b' mod tests {' | |||
|
1956 | 1946 | #[test] |
|
1957 | 1947 | fn test_offset() { |
|
1958 | 1948 | let bytes = IndexEntryBuilder::new().with_offset(1).build(); |
|
1959 | let entry = IndexEntry { | |
|
1960 | bytes: &bytes, | |
|
1961 | offset_override: None, | |
|
1962 | }; | |
|
1949 | let entry = IndexEntry { bytes: &bytes }; | |
|
1963 | 1950 | |
|
1964 | 1951 | assert_eq!(entry.offset(), 1) |
|
1965 | 1952 | } |
|
1966 | 1953 | |
|
1967 | 1954 | #[test] |
|
1968 | fn test_with_overridden_offset() { | |
|
1969 | let bytes = IndexEntryBuilder::new().with_offset(1).build(); | |
|
1970 | let entry = IndexEntry { | |
|
1971 | bytes: &bytes, | |
|
1972 | offset_override: Some(2), | |
|
1973 | }; | |
|
1974 | ||
|
1975 | assert_eq!(entry.offset(), 2) | |
|
1976 | } | |
|
1977 | ||
|
1978 | #[test] | |
|
1979 | 1955 | fn test_compressed_len() { |
|
1980 | 1956 | let bytes = IndexEntryBuilder::new().with_compressed_len(1).build(); |
|
1981 | let entry = IndexEntry { | |
|
1982 | bytes: &bytes, | |
|
1983 | offset_override: None, | |
|
1984 | }; | |
|
1957 | let entry = IndexEntry { bytes: &bytes }; | |
|
1985 | 1958 | |
|
1986 | 1959 | assert_eq!(entry.compressed_len(), 1) |
|
1987 | 1960 | } |
@@ -1989,10 +1962,7 b' mod tests {' | |||
|
1989 | 1962 | #[test] |
|
1990 | 1963 | fn test_uncompressed_len() { |
|
1991 | 1964 | let bytes = IndexEntryBuilder::new().with_uncompressed_len(1).build(); |
|
1992 | let entry = IndexEntry { | |
|
1993 | bytes: &bytes, | |
|
1994 | offset_override: None, | |
|
1995 | }; | |
|
1965 | let entry = IndexEntry { bytes: &bytes }; | |
|
1996 | 1966 | |
|
1997 | 1967 | assert_eq!(entry.uncompressed_len(), 1) |
|
1998 | 1968 | } |
@@ -2002,10 +1972,7 b' mod tests {' | |||
|
2002 | 1972 | let bytes = IndexEntryBuilder::new() |
|
2003 | 1973 | .with_base_revision_or_base_of_delta_chain(Revision(1)) |
|
2004 | 1974 | .build(); |
|
2005 | let entry = IndexEntry { | |
|
2006 | bytes: &bytes, | |
|
2007 | offset_override: None, | |
|
2008 | }; | |
|
1975 | let entry = IndexEntry { bytes: &bytes }; | |
|
2009 | 1976 | |
|
2010 | 1977 | assert_eq!(entry.base_revision_or_base_of_delta_chain(), 1.into()) |
|
2011 | 1978 | } |
@@ -2016,10 +1983,7 b' mod tests {' | |||
|
2016 | 1983 | .with_link_revision(Revision(123)) |
|
2017 | 1984 | .build(); |
|
2018 | 1985 | |
|
2019 | let entry = IndexEntry { | |
|
2020 | bytes: &bytes, | |
|
2021 | offset_override: None, | |
|
2022 | }; | |
|
1986 | let entry = IndexEntry { bytes: &bytes }; | |
|
2023 | 1987 | |
|
2024 | 1988 | assert_eq!(entry.link_revision(), 123.into()); |
|
2025 | 1989 | } |
@@ -2028,10 +1992,7 b' mod tests {' | |||
|
2028 | 1992 | fn p1_test() { |
|
2029 | 1993 | let bytes = IndexEntryBuilder::new().with_p1(Revision(123)).build(); |
|
2030 | 1994 | |
|
2031 | let entry = IndexEntry { | |
|
2032 | bytes: &bytes, | |
|
2033 | offset_override: None, | |
|
2034 | }; | |
|
1995 | let entry = IndexEntry { bytes: &bytes }; | |
|
2035 | 1996 | |
|
2036 | 1997 | assert_eq!(entry.p1(), 123.into()); |
|
2037 | 1998 | } |
@@ -2040,10 +2001,7 b' mod tests {' | |||
|
2040 | 2001 | fn p2_test() { |
|
2041 | 2002 | let bytes = IndexEntryBuilder::new().with_p2(Revision(123)).build(); |
|
2042 | 2003 | |
|
2043 | let entry = IndexEntry { | |
|
2044 | bytes: &bytes, | |
|
2045 | offset_override: None, | |
|
2046 | }; | |
|
2004 | let entry = IndexEntry { bytes: &bytes }; | |
|
2047 | 2005 | |
|
2048 | 2006 | assert_eq!(entry.p2(), 123.into()); |
|
2049 | 2007 | } |
@@ -2054,10 +2012,7 b' mod tests {' | |||
|
2054 | 2012 | .unwrap(); |
|
2055 | 2013 | let bytes = IndexEntryBuilder::new().with_node(node).build(); |
|
2056 | 2014 | |
|
2057 | let entry = IndexEntry { | |
|
2058 | bytes: &bytes, | |
|
2059 | offset_override: None, | |
|
2060 | }; | |
|
2015 | let entry = IndexEntry { bytes: &bytes }; | |
|
2061 | 2016 | |
|
2062 | 2017 | assert_eq!(*entry.hash(), node); |
|
2063 | 2018 | } |
@@ -29,6 +29,7 b' use zstd;' | |||
|
29 | 29 | use self::node::{NODE_BYTES_LENGTH, NULL_NODE}; |
|
30 | 30 | use self::nodemap_docket::NodeMapDocket; |
|
31 | 31 | use super::index::Index; |
|
32 | use super::index::INDEX_ENTRY_SIZE; | |
|
32 | 33 | use super::nodemap::{NodeMap, NodeMapError}; |
|
33 | 34 | use crate::errors::HgError; |
|
34 | 35 | use crate::vfs::Vfs; |
@@ -531,7 +532,12 b' impl Revlog {' | |||
|
531 | 532 | .index |
|
532 | 533 | .get_entry(rev) |
|
533 | 534 | .ok_or(RevlogError::InvalidRevision)?; |
|
534 |
let |
|
|
535 | let offset = index_entry.offset(); | |
|
536 | let start = if self.index.is_inline() { | |
|
537 | offset + ((rev.0 as usize + 1) * INDEX_ENTRY_SIZE) | |
|
538 | } else { | |
|
539 | offset | |
|
540 | }; | |
|
535 | 541 | let end = start + index_entry.compressed_len() as usize; |
|
536 | 542 | let data = if self.index.is_inline() { |
|
537 | 543 | self.index.data(start, end) |
General Comments 0
You need to be logged in to leave comments.
Login now