Show More
@@ -84,10 +84,10 pub fn cat<'a>( | |||
|
84 | 84 | mut files: Vec<&'a HgPath>, |
|
85 | 85 | ) -> Result<CatOutput<'a>, RevlogError> { |
|
86 | 86 | let rev = crate::revset::resolve_single(revset, repo)?; |
|
87 | let manifest = repo.manifest_for_rev(rev)?; | |
|
87 | let manifest = repo.manifest_for_rev(rev.into())?; | |
|
88 | 88 | let node = *repo |
|
89 | 89 | .changelog()? |
|
90 | .node_from_rev(rev) | |
|
90 | .node_from_rev(rev.into()) | |
|
91 | 91 | .expect("should succeed when repo.manifest did"); |
|
92 | 92 | let mut results: Vec<(&'a HgPath, Vec<u8>)> = vec![]; |
|
93 | 93 | let mut found_any = false; |
@@ -33,6 +33,6 pub fn debug_data( | |||
|
33 | 33 | Revlog::open(&repo.store_vfs(), index_file, None, use_nodemap)?; |
|
34 | 34 | let rev = |
|
35 | 35 | crate::revset::resolve_rev_number_or_hex_prefix(revset, &revlog)?; |
|
36 | let data = revlog.get_rev_data(rev)?; | |
|
36 | let data = revlog.get_rev_data_for_checked_rev(rev)?; | |
|
37 | 37 | Ok(data.into_owned()) |
|
38 | 38 | } |
@@ -21,7 +21,7 pub fn list_rev_tracked_files( | |||
|
21 | 21 | ) -> Result<FilesForRev, RevlogError> { |
|
22 | 22 | let rev = crate::revset::resolve_single(revset, repo)?; |
|
23 | 23 | Ok(FilesForRev { |
|
24 | manifest: repo.manifest_for_rev(rev)?, | |
|
24 | manifest: repo.manifest_for_rev(rev.into())?, | |
|
25 | 25 | narrow_matcher, |
|
26 | 26 | }) |
|
27 | 27 | } |
@@ -15,8 +15,8 use crate::utils::files::get_path_from_b | |||
|
15 | 15 | use crate::utils::hg_path::HgPath; |
|
16 | 16 | use crate::utils::SliceExt; |
|
17 | 17 | use crate::vfs::{is_dir, is_file, Vfs}; |
|
18 | use crate::{requirements, NodePrefix}; | |
|
19 | use crate::{DirstateError, Revision}; | |
|
18 | use crate::DirstateError; | |
|
19 | use crate::{requirements, NodePrefix, UncheckedRevision}; | |
|
20 | 20 | use std::cell::{Ref, RefCell, RefMut}; |
|
21 | 21 | use std::collections::HashSet; |
|
22 | 22 | use std::io::Seek; |
@@ -562,7 +562,7 impl Repo { | |||
|
562 | 562 | /// Returns the manifest of the *changeset* with the given revision number |
|
563 | 563 | pub fn manifest_for_rev( |
|
564 | 564 | &self, |
|
565 | revision: Revision, | |
|
565 | revision: UncheckedRevision, | |
|
566 | 566 | ) -> Result<Manifest, RevlogError> { |
|
567 | 567 | self.manifestlog()?.data_for_node( |
|
568 | 568 | self.changelog()? |
@@ -4,6 +4,7 use crate::revlog::{Node, NodePrefix}; | |||
|
4 | 4 | use crate::revlog::{Revlog, RevlogEntry, RevlogError}; |
|
5 | 5 | use crate::utils::hg_path::HgPath; |
|
6 | 6 | use crate::vfs::Vfs; |
|
7 | use crate::UncheckedRevision; | |
|
7 | 8 | use itertools::Itertools; |
|
8 | 9 | use std::ascii::escape_default; |
|
9 | 10 | use std::borrow::Cow; |
@@ -29,15 +30,24 impl Changelog { | |||
|
29 | 30 | node: NodePrefix, |
|
30 | 31 | ) -> Result<ChangelogRevisionData, RevlogError> { |
|
31 | 32 | let rev = self.revlog.rev_from_node(node)?; |
|
32 |
self. |
|
|
33 | self.entry_for_checked_rev(rev)?.data() | |
|
33 | 34 | } |
|
34 | 35 | |
|
35 | 36 | /// Return the [`ChangelogEntry`] for the given revision number. |
|
36 | 37 | pub fn entry_for_rev( |
|
37 | 38 | &self, |
|
39 | rev: UncheckedRevision, | |
|
40 | ) -> Result<ChangelogEntry, RevlogError> { | |
|
41 | let revlog_entry = self.revlog.get_entry(rev)?; | |
|
42 | Ok(ChangelogEntry { revlog_entry }) | |
|
43 | } | |
|
44 | ||
|
45 | /// Same as [`Self::entry_for_rev`] for checked revisions. | |
|
46 | fn entry_for_checked_rev( | |
|
47 | &self, | |
|
38 | 48 | rev: Revision, |
|
39 | 49 | ) -> Result<ChangelogEntry, RevlogError> { |
|
40 | let revlog_entry = self.revlog.get_entry(rev)?; | |
|
50 | let revlog_entry = self.revlog.get_entry_for_checked_rev(rev)?; | |
|
41 | 51 | Ok(ChangelogEntry { revlog_entry }) |
|
42 | 52 | } |
|
43 | 53 | |
@@ -49,12 +59,12 impl Changelog { | |||
|
49 | 59 | /// [entry_for_rev](`Self::entry_for_rev`) and doing everything from there. |
|
50 | 60 | pub fn data_for_rev( |
|
51 | 61 | &self, |
|
52 | rev: Revision, | |
|
62 | rev: UncheckedRevision, | |
|
53 | 63 | ) -> Result<ChangelogRevisionData, RevlogError> { |
|
54 | 64 | self.entry_for_rev(rev)?.data() |
|
55 | 65 | } |
|
56 | 66 | |
|
57 | pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> { | |
|
67 | pub fn node_from_rev(&self, rev: UncheckedRevision) -> Option<&Node> { | |
|
58 | 68 | self.revlog.node_from_rev(rev) |
|
59 | 69 | } |
|
60 | 70 | |
@@ -330,12 +340,12 message", | |||
|
330 | 340 | |
|
331 | 341 | let changelog = Changelog { revlog }; |
|
332 | 342 | assert_eq!( |
|
333 | changelog.data_for_rev(NULL_REVISION)?, | |
|
343 | changelog.data_for_rev(NULL_REVISION.into())?, | |
|
334 | 344 | ChangelogRevisionData::null() |
|
335 | 345 | ); |
|
336 | 346 | // same with the intermediate entry object |
|
337 | 347 | assert_eq!( |
|
338 | changelog.entry_for_rev(NULL_REVISION)?.data()?, | |
|
348 | changelog.entry_for_rev(NULL_REVISION.into())?.data()?, | |
|
339 | 349 | ChangelogRevisionData::null() |
|
340 | 350 | ); |
|
341 | 351 | Ok(()) |
@@ -1,4 +1,5 | |||
|
1 | 1 | use crate::errors::HgError; |
|
2 | use crate::exit_codes; | |
|
2 | 3 | use crate::repo::Repo; |
|
3 | 4 | use crate::revlog::path_encode::path_encode; |
|
4 | 5 | use crate::revlog::NodePrefix; |
@@ -8,6 +9,7 use crate::revlog::{Revlog, RevlogError} | |||
|
8 | 9 | use crate::utils::files::get_path_from_bytes; |
|
9 | 10 | use crate::utils::hg_path::HgPath; |
|
10 | 11 | use crate::utils::SliceExt; |
|
12 | use crate::UncheckedRevision; | |
|
11 | 13 | use std::path::PathBuf; |
|
12 | 14 | |
|
13 | 15 | /// A specialized `Revlog` to work with file data logs. |
@@ -39,14 +41,14 impl Filelog { | |||
|
39 | 41 | file_node: impl Into<NodePrefix>, |
|
40 | 42 | ) -> Result<FilelogRevisionData, RevlogError> { |
|
41 | 43 | let file_rev = self.revlog.rev_from_node(file_node.into())?; |
|
42 | self.data_for_rev(file_rev) | |
|
44 | self.data_for_rev(file_rev.into()) | |
|
43 | 45 | } |
|
44 | 46 | |
|
45 | 47 | /// The given revision is that of the file as found in a filelog, not of a |
|
46 | 48 | /// changeset. |
|
47 | 49 | pub fn data_for_rev( |
|
48 | 50 | &self, |
|
49 | file_rev: Revision, | |
|
51 | file_rev: UncheckedRevision, | |
|
50 | 52 | ) -> Result<FilelogRevisionData, RevlogError> { |
|
51 | 53 | let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?.into_owned(); |
|
52 | 54 | Ok(FilelogRevisionData(data)) |
@@ -59,16 +61,25 impl Filelog { | |||
|
59 | 61 | file_node: impl Into<NodePrefix>, |
|
60 | 62 | ) -> Result<FilelogEntry, RevlogError> { |
|
61 | 63 | let file_rev = self.revlog.rev_from_node(file_node.into())?; |
|
62 | self.entry_for_rev(file_rev) | |
|
64 | self.entry_for_checked_rev(file_rev) | |
|
63 | 65 | } |
|
64 | 66 | |
|
65 | 67 | /// The given revision is that of the file as found in a filelog, not of a |
|
66 | 68 | /// changeset. |
|
67 | 69 | pub fn entry_for_rev( |
|
68 | 70 | &self, |
|
71 | file_rev: UncheckedRevision, | |
|
72 | ) -> Result<FilelogEntry, RevlogError> { | |
|
73 | Ok(FilelogEntry(self.revlog.get_entry(file_rev)?)) | |
|
74 | } | |
|
75 | ||
|
76 | fn entry_for_checked_rev( | |
|
77 | &self, | |
|
69 | 78 | file_rev: Revision, |
|
70 | 79 | ) -> Result<FilelogEntry, RevlogError> { |
|
71 | Ok(FilelogEntry(self.revlog.get_entry(file_rev)?)) | |
|
80 | Ok(FilelogEntry( | |
|
81 | self.revlog.get_entry_for_checked_rev(file_rev)?, | |
|
82 | )) | |
|
72 | 83 | } |
|
73 | 84 | } |
|
74 | 85 | |
@@ -165,7 +176,19 impl FilelogEntry<'_> { | |||
|
165 | 176 | } |
|
166 | 177 | |
|
167 | 178 | pub fn data(&self) -> Result<FilelogRevisionData, HgError> { |
|
168 | Ok(FilelogRevisionData(self.0.data()?.into_owned())) | |
|
179 | let data = self.0.data(); | |
|
180 | match data { | |
|
181 | Ok(data) => Ok(FilelogRevisionData(data.into_owned())), | |
|
182 | // Errors other than `HgError` should not happen at this point | |
|
183 | Err(e) => match e { | |
|
184 | RevlogError::Other(hg_error) => Err(hg_error), | |
|
185 | revlog_error => Err(HgError::abort( | |
|
186 | revlog_error.to_string(), | |
|
187 | exit_codes::ABORT, | |
|
188 | None, | |
|
189 | )), | |
|
190 | }, | |
|
191 | } | |
|
169 | 192 | } |
|
170 | 193 | } |
|
171 | 194 |
@@ -1,3 +1,4 | |||
|
1 | use std::fmt::Debug; | |
|
1 | 2 | use std::ops::Deref; |
|
2 | 3 | |
|
3 | 4 | use byteorder::{BigEndian, ByteOrder}; |
@@ -5,6 +6,7 use byteorder::{BigEndian, ByteOrder}; | |||
|
5 | 6 | use crate::errors::HgError; |
|
6 | 7 | use crate::revlog::node::Node; |
|
7 | 8 | use crate::revlog::{Revision, NULL_REVISION}; |
|
9 | use crate::UncheckedRevision; | |
|
8 | 10 | |
|
9 | 11 | pub const INDEX_ENTRY_SIZE: usize = 64; |
|
10 | 12 | |
@@ -86,6 +88,15 pub struct Index { | |||
|
86 | 88 | uses_generaldelta: bool, |
|
87 | 89 | } |
|
88 | 90 | |
|
91 | impl Debug for Index { | |
|
92 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
|
93 | f.debug_struct("Index") | |
|
94 | .field("offsets", &self.offsets) | |
|
95 | .field("uses_generaldelta", &self.uses_generaldelta) | |
|
96 | .finish() | |
|
97 | } | |
|
98 | } | |
|
99 | ||
|
89 | 100 | impl Index { |
|
90 | 101 | /// Create an index from bytes. |
|
91 | 102 | /// Calculate the start of each entry when is_inline is true. |
@@ -175,36 +186,32 impl Index { | |||
|
175 | 186 | if rev == NULL_REVISION { |
|
176 | 187 | return None; |
|
177 | 188 | } |
|
178 | if let Some(offsets) = &self.offsets { | |
|
189 | Some(if let Some(offsets) = &self.offsets { | |
|
179 | 190 | self.get_entry_inline(rev, offsets) |
|
180 | 191 | } else { |
|
181 | 192 | self.get_entry_separated(rev) |
|
182 | } | |
|
193 | }) | |
|
183 | 194 | } |
|
184 | 195 | |
|
185 | 196 | fn get_entry_inline( |
|
186 | 197 | &self, |
|
187 | 198 | rev: Revision, |
|
188 | 199 | offsets: &[usize], |
|
189 |
) -> |
|
|
190 |
let start = |
|
|
191 |
let end = start |
|
|
200 | ) -> IndexEntry { | |
|
201 | let start = offsets[rev as usize]; | |
|
202 | let end = start + INDEX_ENTRY_SIZE; | |
|
192 | 203 | let bytes = &self.bytes[start..end]; |
|
193 | 204 | |
|
194 | 205 | // See IndexEntry for an explanation of this override. |
|
195 | 206 | let offset_override = Some(end); |
|
196 | 207 | |
|
197 |
|
|
|
208 | IndexEntry { | |
|
198 | 209 | bytes, |
|
199 | 210 | offset_override, |
|
200 |
} |
|
|
211 | } | |
|
201 | 212 | } |
|
202 | 213 | |
|
203 |
fn get_entry_separated(&self, rev: Revision) -> |
|
|
204 | let max_rev = self.bytes.len() / INDEX_ENTRY_SIZE; | |
|
205 | if rev as usize >= max_rev { | |
|
206 | return None; | |
|
207 | } | |
|
214 | fn get_entry_separated(&self, rev: Revision) -> IndexEntry { | |
|
208 | 215 | let start = rev as usize * INDEX_ENTRY_SIZE; |
|
209 | 216 | let end = start + INDEX_ENTRY_SIZE; |
|
210 | 217 | let bytes = &self.bytes[start..end]; |
@@ -213,10 +220,10 impl Index { | |||
|
213 | 220 | // for the index's metadata (saving space because it is always 0) |
|
214 | 221 | let offset_override = if rev == 0 { Some(0) } else { None }; |
|
215 | 222 | |
|
216 |
|
|
|
223 | IndexEntry { | |
|
217 | 224 | bytes, |
|
218 | 225 | offset_override, |
|
219 |
} |
|
|
226 | } | |
|
220 | 227 | } |
|
221 | 228 | } |
|
222 | 229 | |
@@ -273,23 +280,23 impl<'a> IndexEntry<'a> { | |||
|
273 | 280 | } |
|
274 | 281 | |
|
275 | 282 | /// Return the revision upon which the data has been derived. |
|
276 | pub fn base_revision_or_base_of_delta_chain(&self) -> Revision { | |
|
283 | pub fn base_revision_or_base_of_delta_chain(&self) -> UncheckedRevision { | |
|
277 | 284 | // TODO Maybe return an Option when base_revision == rev? |
|
278 | 285 | // Requires to add rev to IndexEntry |
|
279 | 286 | |
|
280 | BigEndian::read_i32(&self.bytes[16..]) | |
|
287 | BigEndian::read_i32(&self.bytes[16..]).into() | |
|
281 | 288 | } |
|
282 | 289 | |
|
283 | pub fn link_revision(&self) -> Revision { | |
|
284 | BigEndian::read_i32(&self.bytes[20..]) | |
|
290 | pub fn link_revision(&self) -> UncheckedRevision { | |
|
291 | BigEndian::read_i32(&self.bytes[20..]).into() | |
|
285 | 292 | } |
|
286 | 293 | |
|
287 | pub fn p1(&self) -> Revision { | |
|
288 | BigEndian::read_i32(&self.bytes[24..]) | |
|
294 | pub fn p1(&self) -> UncheckedRevision { | |
|
295 | BigEndian::read_i32(&self.bytes[24..]).into() | |
|
289 | 296 | } |
|
290 | 297 | |
|
291 | pub fn p2(&self) -> Revision { | |
|
292 | BigEndian::read_i32(&self.bytes[28..]) | |
|
298 | pub fn p2(&self) -> UncheckedRevision { | |
|
299 | BigEndian::read_i32(&self.bytes[28..]).into() | |
|
293 | 300 | } |
|
294 | 301 | |
|
295 | 302 | /// Return the hash of revision's full text. |
@@ -547,7 +554,7 mod tests { | |||
|
547 | 554 | offset_override: None, |
|
548 | 555 | }; |
|
549 | 556 | |
|
550 | assert_eq!(entry.base_revision_or_base_of_delta_chain(), 1) | |
|
557 | assert_eq!(entry.base_revision_or_base_of_delta_chain(), 1.into()) | |
|
551 | 558 | } |
|
552 | 559 | |
|
553 | 560 | #[test] |
@@ -559,7 +566,7 mod tests { | |||
|
559 | 566 | offset_override: None, |
|
560 | 567 | }; |
|
561 | 568 | |
|
562 | assert_eq!(entry.link_revision(), 123); | |
|
569 | assert_eq!(entry.link_revision(), 123.into()); | |
|
563 | 570 | } |
|
564 | 571 | |
|
565 | 572 | #[test] |
@@ -571,7 +578,7 mod tests { | |||
|
571 | 578 | offset_override: None, |
|
572 | 579 | }; |
|
573 | 580 | |
|
574 | assert_eq!(entry.p1(), 123); | |
|
581 | assert_eq!(entry.p1(), 123.into()); | |
|
575 | 582 | } |
|
576 | 583 | |
|
577 | 584 | #[test] |
@@ -583,7 +590,7 mod tests { | |||
|
583 | 590 | offset_override: None, |
|
584 | 591 | }; |
|
585 | 592 | |
|
586 | assert_eq!(entry.p2(), 123); | |
|
593 | assert_eq!(entry.p2(), 123.into()); | |
|
587 | 594 | } |
|
588 | 595 | |
|
589 | 596 | #[test] |
@@ -1,10 +1,10 | |||
|
1 | 1 | use crate::errors::HgError; |
|
2 | use crate::revlog::Revision; | |
|
3 | 2 | use crate::revlog::{Node, NodePrefix}; |
|
4 | 3 | use crate::revlog::{Revlog, RevlogError}; |
|
5 | 4 | use crate::utils::hg_path::HgPath; |
|
6 | 5 | use crate::utils::SliceExt; |
|
7 | 6 | use crate::vfs::Vfs; |
|
7 | use crate::{Revision, UncheckedRevision}; | |
|
8 | 8 | |
|
9 | 9 | /// A specialized `Revlog` to work with `manifest` data format. |
|
10 | 10 | pub struct Manifestlog { |
@@ -32,7 +32,7 impl Manifestlog { | |||
|
32 | 32 | node: NodePrefix, |
|
33 | 33 | ) -> Result<Manifest, RevlogError> { |
|
34 | 34 | let rev = self.revlog.rev_from_node(node)?; |
|
35 | self.data_for_rev(rev) | |
|
35 | self.data_for_checked_rev(rev) | |
|
36 | 36 | } |
|
37 | 37 | |
|
38 | 38 | /// Return the `Manifest` of a given revision number. |
@@ -43,9 +43,18 impl Manifestlog { | |||
|
43 | 43 | /// See also `Repo::manifest_for_rev` |
|
44 | 44 | pub fn data_for_rev( |
|
45 | 45 | &self, |
|
46 | rev: UncheckedRevision, | |
|
47 | ) -> Result<Manifest, RevlogError> { | |
|
48 | let bytes = self.revlog.get_rev_data(rev)?.into_owned(); | |
|
49 | Ok(Manifest { bytes }) | |
|
50 | } | |
|
51 | ||
|
52 | pub fn data_for_checked_rev( | |
|
53 | &self, | |
|
46 | 54 | rev: Revision, |
|
47 | 55 | ) -> Result<Manifest, RevlogError> { |
|
48 | let bytes = self.revlog.get_rev_data(rev)?.into_owned(); | |
|
56 | let bytes = | |
|
57 | self.revlog.get_rev_data_for_checked_rev(rev)?.into_owned(); | |
|
49 | 58 | Ok(Manifest { bytes }) |
|
50 | 59 | } |
|
51 | 60 | } |
@@ -47,7 +47,24 pub type Revision = i32; | |||
|
47 | 47 | /// |
|
48 | 48 | /// As noted in revlog.c, revision numbers are actually encoded in |
|
49 | 49 | /// 4 bytes, and are liberally converted to ints, whence the i32 |
|
50 | pub type UncheckedRevision = i32; | |
|
50 | #[derive( | |
|
51 | Debug, | |
|
52 | derive_more::Display, | |
|
53 | Clone, | |
|
54 | Copy, | |
|
55 | Hash, | |
|
56 | PartialEq, | |
|
57 | Eq, | |
|
58 | PartialOrd, | |
|
59 | Ord, | |
|
60 | )] | |
|
61 | pub struct UncheckedRevision(i32); | |
|
62 | ||
|
63 | impl From<Revision> for UncheckedRevision { | |
|
64 | fn from(value: Revision) -> Self { | |
|
65 | Self(value) | |
|
66 | } | |
|
67 | } | |
|
51 | 68 | |
|
52 | 69 | /// Marker expressing the absence of a parent |
|
53 | 70 | /// |
@@ -60,7 +77,8 pub const NULL_REVISION: Revision = -1; | |||
|
60 | 77 | /// This is also equal to `i32::max_value()`, but it's better to spell |
|
61 | 78 | /// it out explicitely, same as in `mercurial.node` |
|
62 | 79 | #[allow(clippy::unreadable_literal)] |
|
63 |
pub const WORKING_DIRECTORY_REVISION: Revision = |
|
|
80 | pub const WORKING_DIRECTORY_REVISION: UncheckedRevision = | |
|
81 | UncheckedRevision(0x7fffffff); | |
|
64 | 82 | |
|
65 | 83 | pub const WORKING_DIRECTORY_HEX: &str = |
|
66 | 84 | "ffffffffffffffffffffffffffffffffffffffff"; |
@@ -90,14 +108,14 pub trait RevlogIndex { | |||
|
90 | 108 | self.len() == 0 |
|
91 | 109 | } |
|
92 | 110 | |
|
93 |
/// Return a reference to the Node or `None` |
|
|
94 | /// | |
|
95 | /// `NULL_REVISION` is not considered to be out of bounds. | |
|
111 | /// Return a reference to the Node or `None` for `NULL_REVISION` | |
|
96 | 112 | fn node(&self, rev: Revision) -> Option<&Node>; |
|
97 | 113 | |
|
98 | 114 | /// Return a [`Revision`] if `rev` is a valid revision number for this |
|
99 | 115 | /// index |
|
100 | 116 | fn check_revision(&self, rev: UncheckedRevision) -> Option<Revision> { |
|
117 | let rev = rev.0; | |
|
118 | ||
|
101 | 119 | if rev == NULL_REVISION || (rev >= 0 && (rev as usize) < self.len()) { |
|
102 | 120 | Some(rev) |
|
103 | 121 | } else { |
@@ -120,7 +138,7 const REVIDX_KNOWN_FLAGS: u16 = REVISION | |||
|
120 | 138 | |
|
121 | 139 | const NULL_REVLOG_ENTRY_FLAGS: u16 = 0; |
|
122 | 140 | |
|
123 | #[derive(Debug, derive_more::From)] | |
|
141 | #[derive(Debug, derive_more::From, derive_more::Display)] | |
|
124 | 142 | pub enum RevlogError { |
|
125 | 143 | InvalidRevision, |
|
126 | 144 | /// Working directory is not supported |
@@ -231,10 +249,11 impl Revlog { | |||
|
231 | 249 | |
|
232 | 250 | /// Returns the node ID for the given revision number, if it exists in this |
|
233 | 251 | /// revlog |
|
234 | pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> { | |
|
235 | if rev == NULL_REVISION { | |
|
252 | pub fn node_from_rev(&self, rev: UncheckedRevision) -> Option<&Node> { | |
|
253 | if rev == NULL_REVISION.into() { | |
|
236 | 254 | return Some(&NULL_NODE); |
|
237 | 255 | } |
|
256 | let rev = self.index.check_revision(rev)?; | |
|
238 | 257 | Some(self.index.get_entry(rev)?.hash()) |
|
239 | 258 | } |
|
240 | 259 | |
@@ -296,8 +315,8 impl Revlog { | |||
|
296 | 315 | } |
|
297 | 316 | |
|
298 | 317 | /// Returns whether the given revision exists in this revlog. |
|
299 | pub fn has_rev(&self, rev: Revision) -> bool { | |
|
300 |
self.index. |
|
|
318 | pub fn has_rev(&self, rev: UncheckedRevision) -> bool { | |
|
319 | self.index.check_revision(rev).is_some() | |
|
301 | 320 | } |
|
302 | 321 | |
|
303 | 322 | /// Return the full data associated to a revision. |
@@ -307,12 +326,23 impl Revlog { | |||
|
307 | 326 | /// snapshot to rebuild the final data. |
|
308 | 327 | pub fn get_rev_data( |
|
309 | 328 | &self, |
|
329 | rev: UncheckedRevision, | |
|
330 | ) -> Result<Cow<[u8]>, RevlogError> { | |
|
331 | if rev == NULL_REVISION.into() { | |
|
332 | return Ok(Cow::Borrowed(&[])); | |
|
333 | }; | |
|
334 | self.get_entry(rev)?.data() | |
|
335 | } | |
|
336 | ||
|
337 | /// [`Self::get_rev_data`] for checked revisions. | |
|
338 | pub fn get_rev_data_for_checked_rev( | |
|
339 | &self, | |
|
310 | 340 | rev: Revision, |
|
311 | 341 | ) -> Result<Cow<[u8]>, RevlogError> { |
|
312 | 342 | if rev == NULL_REVISION { |
|
313 | 343 | return Ok(Cow::Borrowed(&[])); |
|
314 | 344 | }; |
|
315 |
|
|
|
345 | self.get_entry_for_checked_rev(rev)?.data() | |
|
316 | 346 | } |
|
317 | 347 | |
|
318 | 348 | /// Check the hash of some given data against the recorded hash. |
@@ -380,8 +410,7 impl Revlog { | |||
|
380 | 410 | } |
|
381 | 411 | } |
|
382 | 412 | |
|
383 | /// Get an entry of the revlog. | |
|
384 | pub fn get_entry( | |
|
413 | fn get_entry_for_checked_rev( | |
|
385 | 414 | &self, |
|
386 | 415 | rev: Revision, |
|
387 | 416 | ) -> Result<RevlogEntry, RevlogError> { |
@@ -399,36 +428,60 impl Revlog { | |||
|
399 | 428 | } else { |
|
400 | 429 | &self.data()[start..end] |
|
401 | 430 | }; |
|
431 | let base_rev = self | |
|
432 | .index | |
|
433 | .check_revision(index_entry.base_revision_or_base_of_delta_chain()) | |
|
434 | .ok_or_else(|| { | |
|
435 | RevlogError::corrupted(format!( | |
|
436 | "base revision for rev {} is invalid", | |
|
437 | rev | |
|
438 | )) | |
|
439 | })?; | |
|
440 | let p1 = | |
|
441 | self.index.check_revision(index_entry.p1()).ok_or_else(|| { | |
|
442 | RevlogError::corrupted(format!( | |
|
443 | "p1 for rev {} is invalid", | |
|
444 | rev | |
|
445 | )) | |
|
446 | })?; | |
|
447 | let p2 = | |
|
448 | self.index.check_revision(index_entry.p2()).ok_or_else(|| { | |
|
449 | RevlogError::corrupted(format!( | |
|
450 | "p2 for rev {} is invalid", | |
|
451 | rev | |
|
452 | )) | |
|
453 | })?; | |
|
402 | 454 | let entry = RevlogEntry { |
|
403 | 455 | revlog: self, |
|
404 | 456 | rev, |
|
405 | 457 | bytes: data, |
|
406 | 458 | compressed_len: index_entry.compressed_len(), |
|
407 | 459 | uncompressed_len: index_entry.uncompressed_len(), |
|
408 |
base_rev_or_base_of_delta_chain: if |
|
|
409 | .base_revision_or_base_of_delta_chain() | |
|
410 | == rev | |
|
411 | { | |
|
460 | base_rev_or_base_of_delta_chain: if base_rev == rev { | |
|
412 | 461 | None |
|
413 | 462 | } else { |
|
414 | Some(index_entry.base_revision_or_base_of_delta_chain()) | |
|
463 | Some(base_rev) | |
|
415 | 464 | }, |
|
416 |
p1 |
|
|
417 |
p2 |
|
|
465 | p1, | |
|
466 | p2, | |
|
418 | 467 | flags: index_entry.flags(), |
|
419 | 468 | hash: *index_entry.hash(), |
|
420 | 469 | }; |
|
421 | 470 | Ok(entry) |
|
422 | 471 | } |
|
423 | 472 | |
|
424 | /// when resolving internal references within revlog, any errors | |
|
425 | /// should be reported as corruption, instead of e.g. "invalid revision" | |
|
426 | fn get_entry_internal( | |
|
473 | /// Get an entry of the revlog. | |
|
474 | pub fn get_entry( | |
|
427 | 475 | &self, |
|
428 | rev: Revision, | |
|
429 |
) -> Result<RevlogEntry, |
|
|
430 | self.get_entry(rev) | |
|
431 | .map_err(|_| corrupted(format!("revision {} out of range", rev))) | |
|
476 | rev: UncheckedRevision, | |
|
477 | ) -> Result<RevlogEntry, RevlogError> { | |
|
478 | if rev == NULL_REVISION.into() { | |
|
479 | return Ok(self.make_null_entry()); | |
|
480 | } | |
|
481 | let rev = self.index.check_revision(rev).ok_or_else(|| { | |
|
482 | RevlogError::corrupted(format!("rev {} is invalid", rev)) | |
|
483 | })?; | |
|
484 | self.get_entry_for_checked_rev(rev) | |
|
432 | 485 | } |
|
433 | 486 | } |
|
434 | 487 | |
@@ -486,7 +539,7 impl<'revlog> RevlogEntry<'revlog> { | |||
|
486 | 539 | if self.p1 == NULL_REVISION { |
|
487 | 540 | Ok(None) |
|
488 | 541 | } else { |
|
489 | Ok(Some(self.revlog.get_entry(self.p1)?)) | |
|
542 | Ok(Some(self.revlog.get_entry_for_checked_rev(self.p1)?)) | |
|
490 | 543 | } |
|
491 | 544 | } |
|
492 | 545 | |
@@ -496,7 +549,7 impl<'revlog> RevlogEntry<'revlog> { | |||
|
496 | 549 | if self.p2 == NULL_REVISION { |
|
497 | 550 | Ok(None) |
|
498 | 551 | } else { |
|
499 | Ok(Some(self.revlog.get_entry(self.p2)?)) | |
|
552 | Ok(Some(self.revlog.get_entry_for_checked_rev(self.p2)?)) | |
|
500 | 553 | } |
|
501 | 554 | } |
|
502 | 555 | |
@@ -527,7 +580,7 impl<'revlog> RevlogEntry<'revlog> { | |||
|
527 | 580 | } |
|
528 | 581 | |
|
529 | 582 | /// The data for this entry, after resolving deltas if any. |
|
530 |
pub fn rawdata(&self) -> Result<Cow<'revlog, [u8]>, |
|
|
583 | pub fn rawdata(&self) -> Result<Cow<'revlog, [u8]>, RevlogError> { | |
|
531 | 584 | let mut entry = self.clone(); |
|
532 | 585 | let mut delta_chain = vec![]; |
|
533 | 586 | |
@@ -539,11 +592,11 impl<'revlog> RevlogEntry<'revlog> { | |||
|
539 | 592 | while let Some(base_rev) = entry.base_rev_or_base_of_delta_chain { |
|
540 | 593 | entry = if uses_generaldelta { |
|
541 | 594 | delta_chain.push(entry); |
|
542 |
self.revlog.get_entry_ |
|
|
595 | self.revlog.get_entry_for_checked_rev(base_rev)? | |
|
543 | 596 | } else { |
|
544 | let base_rev = entry.rev - 1; | |
|
597 | let base_rev = UncheckedRevision(entry.rev - 1); | |
|
545 | 598 | delta_chain.push(entry); |
|
546 |
self.revlog.get_entry |
|
|
599 | self.revlog.get_entry(base_rev)? | |
|
547 | 600 | }; |
|
548 | 601 | } |
|
549 | 602 | |
@@ -559,7 +612,7 impl<'revlog> RevlogEntry<'revlog> { | |||
|
559 | 612 | fn check_data( |
|
560 | 613 | &self, |
|
561 | 614 | data: Cow<'revlog, [u8]>, |
|
562 |
) -> Result<Cow<'revlog, [u8]>, |
|
|
615 | ) -> Result<Cow<'revlog, [u8]>, RevlogError> { | |
|
563 | 616 | if self.revlog.check_hash( |
|
564 | 617 | self.p1, |
|
565 | 618 | self.p2, |
@@ -571,22 +624,24 impl<'revlog> RevlogEntry<'revlog> { | |||
|
571 | 624 | if (self.flags & REVISION_FLAG_ELLIPSIS) != 0 { |
|
572 | 625 | return Err(HgError::unsupported( |
|
573 | 626 | "ellipsis revisions are not supported by rhg", |
|
574 |
) |
|
|
627 | ) | |
|
628 | .into()); | |
|
575 | 629 | } |
|
576 | 630 | Err(corrupted(format!( |
|
577 | 631 | "hash check failed for revision {}", |
|
578 | 632 | self.rev |
|
579 |
)) |
|
|
633 | )) | |
|
634 | .into()) | |
|
580 | 635 | } |
|
581 | 636 | } |
|
582 | 637 | |
|
583 |
pub fn data(&self) -> Result<Cow<'revlog, [u8]>, |
|
|
638 | pub fn data(&self) -> Result<Cow<'revlog, [u8]>, RevlogError> { | |
|
584 | 639 | let data = self.rawdata()?; |
|
585 | 640 | if self.rev == NULL_REVISION { |
|
586 | 641 | return Ok(data); |
|
587 | 642 | } |
|
588 | 643 | if self.is_censored() { |
|
589 | return Err(HgError::CensoredNodeError); | |
|
644 | return Err(HgError::CensoredNodeError.into()); | |
|
590 | 645 | } |
|
591 | 646 | self.check_data(data) |
|
592 | 647 | } |
@@ -705,13 +760,13 mod tests { | |||
|
705 | 760 | let revlog = Revlog::open(&vfs, "foo.i", None, false).unwrap(); |
|
706 | 761 | assert!(revlog.is_empty()); |
|
707 | 762 | assert_eq!(revlog.len(), 0); |
|
708 | assert!(revlog.get_entry(0).is_err()); | |
|
709 | assert!(!revlog.has_rev(0)); | |
|
763 | assert!(revlog.get_entry(0.into()).is_err()); | |
|
764 | assert!(!revlog.has_rev(0.into())); | |
|
710 | 765 | assert_eq!( |
|
711 | 766 | revlog.rev_from_node(NULL_NODE.into()).unwrap(), |
|
712 | 767 | NULL_REVISION |
|
713 | 768 | ); |
|
714 | let null_entry = revlog.get_entry(NULL_REVISION).ok().unwrap(); | |
|
769 | let null_entry = revlog.get_entry(NULL_REVISION.into()).ok().unwrap(); | |
|
715 | 770 | assert_eq!(null_entry.revision(), NULL_REVISION); |
|
716 | 771 | assert!(null_entry.data().unwrap().is_empty()); |
|
717 | 772 | } |
@@ -750,7 +805,7 mod tests { | |||
|
750 | 805 | std::fs::write(temp.path().join("foo.i"), contents).unwrap(); |
|
751 | 806 | let revlog = Revlog::open(&vfs, "foo.i", None, false).unwrap(); |
|
752 | 807 | |
|
753 | let entry0 = revlog.get_entry(0).ok().unwrap(); | |
|
808 | let entry0 = revlog.get_entry(0.into()).ok().unwrap(); | |
|
754 | 809 | assert_eq!(entry0.revision(), 0); |
|
755 | 810 | assert_eq!(*entry0.node(), node0); |
|
756 | 811 | assert!(!entry0.has_p1()); |
@@ -761,7 +816,7 mod tests { | |||
|
761 | 816 | let p2_entry = entry0.p2_entry().unwrap(); |
|
762 | 817 | assert!(p2_entry.is_none()); |
|
763 | 818 | |
|
764 | let entry1 = revlog.get_entry(1).ok().unwrap(); | |
|
819 | let entry1 = revlog.get_entry(1.into()).ok().unwrap(); | |
|
765 | 820 | assert_eq!(entry1.revision(), 1); |
|
766 | 821 | assert_eq!(*entry1.node(), node1); |
|
767 | 822 | assert!(!entry1.has_p1()); |
@@ -772,7 +827,7 mod tests { | |||
|
772 | 827 | let p2_entry = entry1.p2_entry().unwrap(); |
|
773 | 828 | assert!(p2_entry.is_none()); |
|
774 | 829 | |
|
775 | let entry2 = revlog.get_entry(2).ok().unwrap(); | |
|
830 | let entry2 = revlog.get_entry(2.into()).ok().unwrap(); | |
|
776 | 831 | assert_eq!(entry2.revision(), 2); |
|
777 | 832 | assert_eq!(*entry2.node(), node2); |
|
778 | 833 | assert!(entry2.has_p1()); |
@@ -817,7 +872,7 mod tests { | |||
|
817 | 872 | let revlog = Revlog::open(&vfs, "foo.i", None, false).unwrap(); |
|
818 | 873 | |
|
819 | 874 | // accessing the data shows the corruption |
|
820 | revlog.get_entry(0).unwrap().data().unwrap_err(); | |
|
875 | revlog.get_entry(0.into()).unwrap().data().unwrap_err(); | |
|
821 | 876 | |
|
822 | 877 | assert_eq!(revlog.rev_from_node(NULL_NODE.into()).unwrap(), -1); |
|
823 | 878 | assert_eq!(revlog.rev_from_node(node0.into()).unwrap(), 0); |
@@ -12,6 +12,8 | |||
|
12 | 12 | //! Following existing implicit conventions, the "nodemap" terminology |
|
13 | 13 | //! is used in a more abstract context. |
|
14 | 14 | |
|
15 | use crate::UncheckedRevision; | |
|
16 | ||
|
15 | 17 | use super::{ |
|
16 | 18 | node::NULL_NODE, Node, NodePrefix, Revision, RevlogIndex, NULL_REVISION, |
|
17 | 19 | }; |
@@ -30,7 +32,7 pub enum NodeMapError { | |||
|
30 | 32 | /// This can be returned by methods meant for (at most) one match. |
|
31 | 33 | MultipleResults, |
|
32 | 34 | /// A `Revision` stored in the nodemap could not be found in the index |
|
33 | RevisionNotInIndex(Revision), | |
|
35 | RevisionNotInIndex(UncheckedRevision), | |
|
34 | 36 | } |
|
35 | 37 | |
|
36 | 38 | /// Mapping system from Mercurial nodes to revision numbers. |
@@ -125,7 +127,9 type RawElement = unaligned::I32Be; | |||
|
125 | 127 | /// use. |
|
126 | 128 | #[derive(Clone, Debug, Eq, PartialEq)] |
|
127 | 129 | enum Element { |
|
128 | Rev(Revision), | |
|
130 | // This is not a Mercurial revision. It's a `i32` because this is the | |
|
131 | // right type for this structure. | |
|
132 | Rev(i32), | |
|
129 | 133 | Block(usize), |
|
130 | 134 | None, |
|
131 | 135 | } |
@@ -245,17 +249,21 impl Index<usize> for NodeTree { | |||
|
245 | 249 | fn has_prefix_or_none( |
|
246 | 250 | idx: &impl RevlogIndex, |
|
247 | 251 | prefix: NodePrefix, |
|
248 | rev: Revision, | |
|
252 | rev: UncheckedRevision, | |
|
249 | 253 | ) -> Result<Option<Revision>, NodeMapError> { |
|
250 | idx.node(rev) | |
|
251 | .ok_or(NodeMapError::RevisionNotInIndex(rev)) | |
|
252 | .map(|node| { | |
|
253 | if prefix.is_prefix_of(node) { | |
|
254 | Some(rev) | |
|
255 | } else { | |
|
256 |
|
|
|
257 | } | |
|
258 | }) | |
|
254 | match idx.check_revision(rev) { | |
|
255 | Some(checked) => idx | |
|
256 | .node(checked) | |
|
257 | .ok_or(NodeMapError::RevisionNotInIndex(rev)) | |
|
258 | .map(|node| { | |
|
259 | if prefix.is_prefix_of(node) { | |
|
260 | Some(checked) | |
|
261 | } else { | |
|
262 | None | |
|
263 | } | |
|
264 | }), | |
|
265 | None => Err(NodeMapError::RevisionNotInIndex(rev)), | |
|
266 | } | |
|
259 | 267 | } |
|
260 | 268 | |
|
261 | 269 | /// validate that the candidate's node starts indeed with given prefix, |
@@ -266,7 +274,7 fn has_prefix_or_none( | |||
|
266 | 274 | fn validate_candidate( |
|
267 | 275 | idx: &impl RevlogIndex, |
|
268 | 276 | prefix: NodePrefix, |
|
269 | candidate: (Option<Revision>, usize), | |
|
277 | candidate: (Option<UncheckedRevision>, usize), | |
|
270 | 278 | ) -> Result<(Option<Revision>, usize), NodeMapError> { |
|
271 | 279 | let (rev, steps) = candidate; |
|
272 | 280 | if let Some(nz_nybble) = prefix.first_different_nybble(&NULL_NODE) { |
@@ -384,6 +392,8 impl NodeTree { | |||
|
384 | 392 | /// be inferred from |
|
385 | 393 | /// the `NodeTree` data is that `rev` is the revision with the longest |
|
386 | 394 | /// common node prefix with the given prefix. |
|
395 | /// We return an [`UncheckedRevision`] because we have no guarantee that | |
|
396 | /// the revision we found is valid for the index. | |
|
387 | 397 | /// |
|
388 | 398 | /// The second returned value is the size of the smallest subprefix |
|
389 | 399 | /// of `prefix` that would give the same result, i.e. not the |
@@ -392,7 +402,7 impl NodeTree { | |||
|
392 | 402 | fn lookup( |
|
393 | 403 | &self, |
|
394 | 404 | prefix: NodePrefix, |
|
395 | ) -> Result<(Option<Revision>, usize), NodeMapError> { | |
|
405 | ) -> Result<(Option<UncheckedRevision>, usize), NodeMapError> { | |
|
396 | 406 | for (i, visit_item) in self.visit(prefix).enumerate() { |
|
397 | 407 | if let Some(opt) = visit_item.final_revision() { |
|
398 | 408 | return Ok((opt, i + 1)); |
@@ -464,9 +474,9 impl NodeTree { | |||
|
464 | 474 | self.mutable_block(deepest.block_idx); |
|
465 | 475 | |
|
466 | 476 | if let Element::Rev(old_rev) = deepest.element { |
|
467 | let old_node = index | |
|
468 | .node(old_rev) | |
|
469 | .ok_or(NodeMapError::RevisionNotInIndex(old_rev))?; | |
|
477 | let old_node = index.node(old_rev).ok_or_else(|| { | |
|
478 | NodeMapError::RevisionNotInIndex(old_rev.into()) | |
|
479 | })?; | |
|
470 | 480 | if old_node == node { |
|
471 | 481 | return Ok(()); // avoid creating lots of useless blocks |
|
472 | 482 | } |
@@ -623,13 +633,13 impl<'n> Iterator for NodeTreeVisitor<'n | |||
|
623 | 633 | |
|
624 | 634 | impl NodeTreeVisitItem { |
|
625 | 635 | // Return `Some(opt)` if this item is final, with `opt` being the |
|
626 | // `Revision` that it may represent. | |
|
636 | // `UncheckedRevision` that it may represent. | |
|
627 | 637 | // |
|
628 | 638 | // If the item is not terminal, return `None` |
|
629 | fn final_revision(&self) -> Option<Option<Revision>> { | |
|
639 | fn final_revision(&self) -> Option<Option<UncheckedRevision>> { | |
|
630 | 640 | match self.element { |
|
631 | 641 | Element::Block(_) => None, |
|
632 | Element::Rev(r) => Some(Some(r)), | |
|
642 | Element::Rev(r) => Some(Some(r.into())), | |
|
633 | 643 | Element::None => Some(None), |
|
634 | 644 | } |
|
635 | 645 | } |
@@ -733,16 +743,20 mod tests { | |||
|
733 | 743 | assert_eq!(block.get(4), Element::Rev(1)); |
|
734 | 744 | } |
|
735 | 745 | |
|
736 | type TestIndex = HashMap<Revision, Node>; | |
|
746 | type TestIndex = HashMap<UncheckedRevision, Node>; | |
|
737 | 747 | |
|
738 | 748 | impl RevlogIndex for TestIndex { |
|
739 | 749 | fn node(&self, rev: Revision) -> Option<&Node> { |
|
740 | self.get(&rev) | |
|
750 | self.get(&rev.into()) | |
|
741 | 751 | } |
|
742 | 752 | |
|
743 | 753 | fn len(&self) -> usize { |
|
744 | 754 | self.len() |
|
745 | 755 | } |
|
756 | ||
|
757 | fn check_revision(&self, rev: UncheckedRevision) -> Option<Revision> { | |
|
758 | self.get(&rev).map(|_| rev.0) | |
|
759 | } | |
|
746 | 760 | } |
|
747 | 761 | |
|
748 | 762 | /// Pad hexadecimal Node prefix with zeros on the right |
@@ -756,7 +770,7 mod tests { | |||
|
756 | 770 | |
|
757 | 771 | /// Pad hexadecimal Node prefix with zeros on the right, then insert |
|
758 | 772 | fn pad_insert(idx: &mut TestIndex, rev: Revision, hex: &str) { |
|
759 | idx.insert(rev, pad_node(hex)); | |
|
773 | idx.insert(rev.into(), pad_node(hex)); | |
|
760 | 774 | } |
|
761 | 775 | |
|
762 | 776 | fn sample_nodetree() -> NodeTree { |
@@ -796,7 +810,7 mod tests { | |||
|
796 | 810 | assert_eq!(nt.find_bin(&idx, hex("ab"))?, None); |
|
797 | 811 | |
|
798 | 812 | // and with full binary Nodes |
|
799 | assert_eq!(nt.find_node(&idx, idx.get(&1).unwrap())?, Some(1)); | |
|
813 | assert_eq!(nt.find_node(&idx, idx.get(&1.into()).unwrap())?, Some(1)); | |
|
800 | 814 | let unknown = Node::from_hex(&hex_pad_right("3d")).unwrap(); |
|
801 | 815 | assert_eq!(nt.find_node(&idx, &unknown)?, None); |
|
802 | 816 | Ok(()) |
@@ -857,14 +871,15 mod tests { | |||
|
857 | 871 | } |
|
858 | 872 | } |
|
859 | 873 | |
|
860 | fn insert( | |
|
861 | &mut self, | |
|
862 | rev: Revision, | |
|
863 | hex: &str, | |
|
864 | ) -> Result<(), NodeMapError> { | |
|
874 | fn insert(&mut self, rev: i32, hex: &str) -> Result<(), NodeMapError> { | |
|
865 | 875 | let node = pad_node(hex); |
|
876 | let rev: UncheckedRevision = rev.into(); | |
|
866 | 877 | self.index.insert(rev, node); |
|
867 |
self.nt.insert( |
|
|
878 | self.nt.insert( | |
|
879 | &self.index, | |
|
880 | &node, | |
|
881 | self.index.check_revision(rev).unwrap(), | |
|
882 | )?; | |
|
868 | 883 | Ok(()) |
|
869 | 884 | } |
|
870 | 885 | |
@@ -971,9 +986,9 mod tests { | |||
|
971 | 986 | let node0 = Node::from_hex(&node0_hex).unwrap(); |
|
972 | 987 | let node1 = Node::from_hex(&node1_hex).unwrap(); |
|
973 | 988 | |
|
974 | idx.insert(0, node0); | |
|
989 | idx.insert(0.into(), node0); | |
|
975 | 990 | nt.insert(idx, &node0, 0)?; |
|
976 | idx.insert(1, node1); | |
|
991 | idx.insert(1.into(), node1); | |
|
977 | 992 | nt.insert(idx, &node1, 1)?; |
|
978 | 993 | |
|
979 | 994 | assert_eq!(nt.find_bin(idx, (&node0).into())?, Some(0)); |
@@ -53,7 +53,7 pub fn resolve_rev_number_or_hex_prefix( | |||
|
53 | 53 | if let Ok(integer) = input.parse::<i32>() { |
|
54 | 54 | if integer.to_string() == input |
|
55 | 55 | && integer >= 0 |
|
56 | && revlog.has_rev(integer) | |
|
56 | && revlog.has_rev(integer.into()) | |
|
57 | 57 | { |
|
58 | 58 | return Ok(integer); |
|
59 | 59 | } |
@@ -18,7 +18,7 use cpython::{ | |||
|
18 | 18 | use hg::{ |
|
19 | 19 | nodemap::{Block, NodeMapError, NodeTree}, |
|
20 | 20 | revlog::{nodemap::NodeMap, NodePrefix, RevlogIndex}, |
|
21 | Revision, | |
|
21 | Revision, UncheckedRevision, | |
|
22 | 22 | }; |
|
23 | 23 | use std::cell::RefCell; |
|
24 | 24 | |
@@ -252,7 +252,7 py_class!(pub class MixedIndex |py| { | |||
|
252 | 252 | // Note that we don't seem to have a direct way to call |
|
253 | 253 | // PySequence_GetItem (does the job), which would possibly be better |
|
254 | 254 | // for performance |
|
255 |
let key = match key.extract::< |
|
|
255 | let key = match key.extract::<i32>(py) { | |
|
256 | 256 | Ok(rev) => rev.to_py_object(py).into_object(), |
|
257 | 257 | Err(_) => key, |
|
258 | 258 | }; |
@@ -268,7 +268,7 py_class!(pub class MixedIndex |py| { | |||
|
268 | 268 | // this is an equivalent implementation of the index_contains() |
|
269 | 269 | // defined in revlog.c |
|
270 | 270 | let cindex = self.cindex(py).borrow(); |
|
271 |
match item.extract::< |
|
|
271 | match item.extract::<i32>(py) { | |
|
272 | 272 | Ok(rev) => { |
|
273 | 273 | Ok(rev >= -1 && rev < cindex.inner().len(py)? as Revision) |
|
274 | 274 | } |
@@ -448,9 +448,12 impl MixedIndex { | |||
|
448 | 448 | let mut nt = NodeTree::load_bytes(Box::new(bytes), len); |
|
449 | 449 | |
|
450 | 450 | let data_tip = |
|
451 |
docket.getattr(py, "tip_rev")?.extract::< |
|
|
451 | docket.getattr(py, "tip_rev")?.extract::<i32>(py)?.into(); | |
|
452 | 452 | self.docket(py).borrow_mut().replace(docket.clone_ref(py)); |
|
453 | 453 | let idx = self.cindex(py).borrow(); |
|
454 | let data_tip = idx.check_revision(data_tip).ok_or_else(|| { | |
|
455 | nodemap_error(py, NodeMapError::RevisionNotInIndex(data_tip)) | |
|
456 | })?; | |
|
454 | 457 | let current_tip = idx.len(); |
|
455 | 458 | |
|
456 | 459 | for r in (data_tip + 1)..current_tip as Revision { |
@@ -479,7 +482,7 fn revlog_error(py: Python) -> PyErr { | |||
|
479 | 482 | } |
|
480 | 483 | } |
|
481 | 484 | |
|
482 | fn rev_not_in_index(py: Python, rev: Revision) -> PyErr { | |
|
485 | fn rev_not_in_index(py: Python, rev: UncheckedRevision) -> PyErr { | |
|
483 | 486 | PyErr::new::<ValueError, _>( |
|
484 | 487 | py, |
|
485 | 488 | format!( |
General Comments 0
You need to be logged in to leave comments.
Login now