##// END OF EJS Templates
rust: use HgError in RevlogError and Vfs...
Simon Sapin -
r47172:43d63979 default
parent child Browse files
Show More
@@ -35,6 +35,9 b' pub enum IoErrorContext {'
35
35
36 impl HgError {
36 impl HgError {
37 pub fn corrupted(explanation: impl Into<String>) -> Self {
37 pub fn corrupted(explanation: impl Into<String>) -> Self {
38 // TODO: capture a backtrace here and keep it in the error value
39 // to aid debugging?
40 // https://doc.rust-lang.org/std/backtrace/struct.Backtrace.html
38 HgError::CorruptedRepository(explanation.into())
41 HgError::CorruptedRepository(explanation.into())
39 }
42 }
40 }
43 }
@@ -3,6 +3,7 b''
3 //
3 //
4 // This software may be used and distributed according to the terms of the
4 // This software may be used and distributed according to the terms of the
5 // GNU General Public License version 2 or any later version.
5 // GNU General Public License version 2 or any later version.
6
6 mod ancestors;
7 mod ancestors;
7 pub mod dagops;
8 pub mod dagops;
8 pub mod errors;
9 pub mod errors;
@@ -33,8 +33,8 b' pub fn cat('
33 let changelog = Changelog::open(repo)?;
33 let changelog = Changelog::open(repo)?;
34 let manifest = Manifest::open(repo)?;
34 let manifest = Manifest::open(repo)?;
35 let changelog_entry = changelog.get_rev(rev)?;
35 let changelog_entry = changelog.get_rev(rev)?;
36 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
36 let manifest_node =
37 .map_err(|_| RevlogError::Corrupted)?;
37 Node::from_hex_for_repo(&changelog_entry.manifest_node()?)?;
38 let manifest_entry = manifest.get_node(manifest_node.into())?;
38 let manifest_entry = manifest.get_node(manifest_node.into())?;
39 let mut bytes = vec![];
39 let mut bytes = vec![];
40
40
@@ -46,8 +46,7 b' pub fn cat('
46
46
47 let file_log =
47 let file_log =
48 Revlog::open(repo, &index_path, Some(&data_path))?;
48 Revlog::open(repo, &index_path, Some(&data_path))?;
49 let file_node = Node::from_hex(node_bytes)
49 let file_node = Node::from_hex_for_repo(node_bytes)?;
50 .map_err(|_| RevlogError::Corrupted)?;
51 let file_rev = file_log.get_node_rev(file_node.into())?;
50 let file_rev = file_log.get_node_rev(file_node.into())?;
52 let data = file_log.get_rev_data(file_rev)?;
51 let data = file_log.get_rev_data(file_rev)?;
53 if data.starts_with(&METADATA_DELIMITER) {
52 if data.starts_with(&METADATA_DELIMITER) {
@@ -6,7 +6,7 b''
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 use crate::dirstate::parsers::parse_dirstate;
8 use crate::dirstate::parsers::parse_dirstate;
9 use crate::errors::{HgError, IoResultExt};
9 use crate::errors::HgError;
10 use crate::repo::Repo;
10 use crate::repo::Repo;
11 use crate::revlog::changelog::Changelog;
11 use crate::revlog::changelog::Changelog;
12 use crate::revlog::manifest::{Manifest, ManifestEntry};
12 use crate::revlog::manifest::{Manifest, ManifestEntry};
@@ -25,12 +25,7 b' pub struct Dirstate {'
25
25
26 impl Dirstate {
26 impl Dirstate {
27 pub fn new(repo: &Repo) -> Result<Self, HgError> {
27 pub fn new(repo: &Repo) -> Result<Self, HgError> {
28 let content = repo
28 let content = repo.hg_vfs().read("dirstate")?;
29 .hg_vfs()
30 .read("dirstate")
31 // TODO: this will be more accurate when we use `HgError` in
32 // `Vfs::read`.
33 .for_file("dirstate".as_ref())?;
34 Ok(Self { content })
29 Ok(Self { content })
35 }
30 }
36
31
@@ -57,8 +52,8 b' pub fn list_rev_tracked_files('
57 let changelog = Changelog::open(repo)?;
52 let changelog = Changelog::open(repo)?;
58 let manifest = Manifest::open(repo)?;
53 let manifest = Manifest::open(repo)?;
59 let changelog_entry = changelog.get_rev(rev)?;
54 let changelog_entry = changelog.get_rev(rev)?;
60 let manifest_node = Node::from_hex(&changelog_entry.manifest_node()?)
55 let manifest_node =
61 .map_err(|_| RevlogError::Corrupted)?;
56 Node::from_hex_for_repo(&changelog_entry.manifest_node()?)?;
62 let manifest_entry = manifest.get_node(manifest_node.into())?;
57 let manifest_entry = manifest.get_node(manifest_node.into())?;
63 Ok(FilesForRev(manifest_entry))
58 Ok(FilesForRev(manifest_entry))
64 }
59 }
@@ -1,4 +1,4 b''
1 use crate::errors::HgError;
1 use crate::errors::{HgError, IoResultExt};
2 use crate::operations::{find_root, FindRootError};
2 use crate::operations::{find_root, FindRootError};
3 use crate::requirements;
3 use crate::requirements;
4 use memmap::{Mmap, MmapOptions};
4 use memmap::{Mmap, MmapOptions};
@@ -68,24 +68,19 b" impl Vfs<'_> {"
68 pub(crate) fn read(
68 pub(crate) fn read(
69 &self,
69 &self,
70 relative_path: impl AsRef<Path>,
70 relative_path: impl AsRef<Path>,
71 ) -> std::io::Result<Vec<u8>> {
71 ) -> Result<Vec<u8>, HgError> {
72 std::fs::read(self.base.join(relative_path))
72 let path = self.base.join(relative_path);
73 }
73 std::fs::read(&path).for_file(&path)
74
75 pub(crate) fn open(
76 &self,
77 relative_path: impl AsRef<Path>,
78 ) -> std::io::Result<std::fs::File> {
79 std::fs::File::open(self.base.join(relative_path))
80 }
74 }
81
75
82 pub(crate) fn mmap_open(
76 pub(crate) fn mmap_open(
83 &self,
77 &self,
84 relative_path: impl AsRef<Path>,
78 relative_path: impl AsRef<Path>,
85 ) -> std::io::Result<Mmap> {
79 ) -> Result<Mmap, HgError> {
86 let file = self.open(relative_path)?;
80 let path = self.base.join(relative_path);
81 let file = std::fs::File::open(&path).for_file(&path)?;
87 // TODO: what are the safety requirements here?
82 // TODO: what are the safety requirements here?
88 let mmap = unsafe { MmapOptions::new().map(&file) }?;
83 let mmap = unsafe { MmapOptions::new().map(&file) }.for_file(&path)?;
89 Ok(mmap)
84 Ok(mmap)
90 }
85 }
91 }
86 }
@@ -1,4 +1,4 b''
1 use crate::errors::{HgError, HgResultExt, IoResultExt};
1 use crate::errors::{HgError, HgResultExt};
2 use crate::repo::Repo;
2 use crate::repo::Repo;
3
3
4 fn parse(bytes: &[u8]) -> Result<Vec<String>, HgError> {
4 fn parse(bytes: &[u8]) -> Result<Vec<String>, HgError> {
@@ -22,11 +22,8 b' fn parse(bytes: &[u8]) -> Result<Vec<Str'
22 }
22 }
23
23
24 pub fn load(repo: &Repo) -> Result<Vec<String>, HgError> {
24 pub fn load(repo: &Repo) -> Result<Vec<String>, HgError> {
25 if let Some(bytes) = repo
25 if let Some(bytes) =
26 .hg_vfs()
26 repo.hg_vfs().read("requires").io_not_found_as_none()?
27 .read("requires")
28 .for_file("requires".as_ref())
29 .io_not_found_as_none()?
30 {
27 {
31 parse(&bytes)
28 parse(&bytes)
32 } else {
29 } else {
@@ -1,3 +1,4 b''
1 use crate::errors::HgError;
1 use crate::repo::Repo;
2 use crate::repo::Repo;
2 use crate::revlog::revlog::{Revlog, RevlogError};
3 use crate::revlog::revlog::{Revlog, RevlogError};
3 use crate::revlog::NodePrefix;
4 use crate::revlog::NodePrefix;
@@ -53,6 +54,8 b' impl ChangelogEntry {'
53 /// Return the node id of the `manifest` referenced by this `changelog`
54 /// Return the node id of the `manifest` referenced by this `changelog`
54 /// entry.
55 /// entry.
55 pub fn manifest_node(&self) -> Result<&[u8], RevlogError> {
56 pub fn manifest_node(&self) -> Result<&[u8], RevlogError> {
56 self.lines().next().ok_or(RevlogError::Corrupted)
57 self.lines()
58 .next()
59 .ok_or_else(|| HgError::corrupted("empty changelog entry").into())
57 }
60 }
58 }
61 }
@@ -3,6 +3,7 b' use std::ops::Deref;'
3
3
4 use byteorder::{BigEndian, ByteOrder};
4 use byteorder::{BigEndian, ByteOrder};
5
5
6 use crate::errors::HgError;
6 use crate::revlog::node::Node;
7 use crate::revlog::node::Node;
7 use crate::revlog::revlog::RevlogError;
8 use crate::revlog::revlog::RevlogError;
8 use crate::revlog::{Revision, NULL_REVISION};
9 use crate::revlog::{Revision, NULL_REVISION};
@@ -44,7 +45,8 b' impl Index {'
44 offsets: Some(offsets),
45 offsets: Some(offsets),
45 })
46 })
46 } else {
47 } else {
47 Err(RevlogError::Corrupted)
48 Err(HgError::corrupted("unexpected inline revlog length")
49 .into())
48 }
50 }
49 } else {
51 } else {
50 Ok(Self {
52 Ok(Self {
@@ -8,6 +8,7 b''
8 //! In Mercurial code base, it is customary to call "a node" the binary SHA
8 //! In Mercurial code base, it is customary to call "a node" the binary SHA
9 //! of a revision.
9 //! of a revision.
10
10
11 use crate::errors::HgError;
11 use bytes_cast::BytesCast;
12 use bytes_cast::BytesCast;
12 use std::convert::{TryFrom, TryInto};
13 use std::convert::{TryFrom, TryInto};
13 use std::fmt;
14 use std::fmt;
@@ -136,6 +137,19 b' impl Node {'
136 }
137 }
137 }
138 }
138
139
140 /// `from_hex`, but for input from an internal file of the repository such
141 /// as a changelog or manifest entry.
142 ///
143 /// An error is treated as repository corruption.
144 pub fn from_hex_for_repo(hex: impl AsRef<[u8]>) -> Result<Node, HgError> {
145 Self::from_hex(hex.as_ref()).map_err(|FromHexError| {
146 HgError::CorruptedRepository(format!(
147 "Expected a full hexadecimal node ID, found {}",
148 String::from_utf8_lossy(hex.as_ref())
149 ))
150 })
151 }
152
139 /// Provide access to binary data
153 /// Provide access to binary data
140 ///
154 ///
141 /// This is needed by FFI layers, for instance to return expected
155 /// This is needed by FFI layers, for instance to return expected
@@ -1,3 +1,4 b''
1 use crate::errors::{HgError, HgResultExt};
1 use bytes_cast::{unaligned, BytesCast};
2 use bytes_cast::{unaligned, BytesCast};
2 use memmap::Mmap;
3 use memmap::Mmap;
3 use std::path::{Path, PathBuf};
4 use std::path::{Path, PathBuf};
@@ -38,12 +39,12 b' impl NodeMapDocket {'
38 index_path: &Path,
39 index_path: &Path,
39 ) -> Result<Option<(Self, Mmap)>, RevlogError> {
40 ) -> Result<Option<(Self, Mmap)>, RevlogError> {
40 let docket_path = index_path.with_extension("n");
41 let docket_path = index_path.with_extension("n");
41 let docket_bytes = match repo.store_vfs().read(&docket_path) {
42 let docket_bytes = if let Some(bytes) =
42 Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
43 repo.store_vfs().read(&docket_path).io_not_found_as_none()?
43 return Ok(None)
44 {
44 }
45 bytes
45 Err(e) => return Err(RevlogError::IoError(e)),
46 } else {
46 Ok(bytes) => bytes,
47 return Ok(None);
47 };
48 };
48
49
49 let input = if let Some((&ONDISK_VERSION, rest)) =
50 let input = if let Some((&ONDISK_VERSION, rest)) =
@@ -54,36 +55,40 b' impl NodeMapDocket {'
54 return Ok(None);
55 return Ok(None);
55 };
56 };
56
57
57 let (header, rest) = DocketHeader::from_bytes(input)?;
58 /// Treat any error as a parse error
59 fn parse<T, E>(result: Result<T, E>) -> Result<T, RevlogError> {
60 result.map_err(|_| {
61 HgError::corrupted("nodemap docket parse error").into()
62 })
63 }
64
65 let (header, rest) = parse(DocketHeader::from_bytes(input))?;
58 let uid_size = header.uid_size as usize;
66 let uid_size = header.uid_size as usize;
59 // TODO: do we care about overflow for 4 GB+ nodemap files on 32-bit
67 // TODO: do we care about overflow for 4 GB+ nodemap files on 32-bit
60 // systems?
68 // systems?
61 let tip_node_size = header.tip_node_size.get() as usize;
69 let tip_node_size = header.tip_node_size.get() as usize;
62 let data_length = header.data_length.get() as usize;
70 let data_length = header.data_length.get() as usize;
63 let (uid, rest) = u8::slice_from_bytes(rest, uid_size)?;
71 let (uid, rest) = parse(u8::slice_from_bytes(rest, uid_size))?;
64 let (_tip_node, _rest) = u8::slice_from_bytes(rest, tip_node_size)?;
72 let (_tip_node, _rest) =
65 let uid =
73 parse(u8::slice_from_bytes(rest, tip_node_size))?;
66 std::str::from_utf8(uid).map_err(|_| RevlogError::Corrupted)?;
74 let uid = parse(std::str::from_utf8(uid))?;
67 let docket = NodeMapDocket { data_length };
75 let docket = NodeMapDocket { data_length };
68
76
69 let data_path = rawdata_path(&docket_path, uid);
77 let data_path = rawdata_path(&docket_path, uid);
70 // TODO: use `std::fs::read` here when the `persistent-nodemap.mmap`
78 // TODO: use `vfs.read()` here when the `persistent-nodemap.mmap`
71 // config is false?
79 // config is false?
72 match repo.store_vfs().mmap_open(&data_path) {
80 if let Some(mmap) = repo
73 Ok(mmap) => {
81 .store_vfs()
74 if mmap.len() >= data_length {
82 .mmap_open(&data_path)
75 Ok(Some((docket, mmap)))
83 .io_not_found_as_none()?
76 } else {
84 {
77 Err(RevlogError::Corrupted)
85 if mmap.len() >= data_length {
78 }
86 Ok(Some((docket, mmap)))
87 } else {
88 Err(HgError::corrupted("persistent nodemap too short").into())
79 }
89 }
80 Err(error) => {
90 } else {
81 if error.kind() == std::io::ErrorKind::NotFound {
91 Ok(None)
82 Ok(None)
83 } else {
84 Err(RevlogError::IoError(error))
85 }
86 }
87 }
92 }
88 }
93 }
89 }
94 }
@@ -13,25 +13,34 b' use zstd;'
13 use super::index::Index;
13 use super::index::Index;
14 use super::node::{NodePrefix, NODE_BYTES_LENGTH, NULL_NODE};
14 use super::node::{NodePrefix, NODE_BYTES_LENGTH, NULL_NODE};
15 use super::nodemap;
15 use super::nodemap;
16 use super::nodemap::NodeMap;
16 use super::nodemap::{NodeMap, NodeMapError};
17 use super::nodemap_docket::NodeMapDocket;
17 use super::nodemap_docket::NodeMapDocket;
18 use super::patch;
18 use super::patch;
19 use crate::errors::HgError;
19 use crate::repo::Repo;
20 use crate::repo::Repo;
20 use crate::revlog::Revision;
21 use crate::revlog::Revision;
21
22
23 #[derive(derive_more::From)]
22 pub enum RevlogError {
24 pub enum RevlogError {
23 IoError(std::io::Error),
24 UnsuportedVersion(u16),
25 InvalidRevision,
25 InvalidRevision,
26 /// Found more than one entry whose ID match the requested prefix
26 /// Found more than one entry whose ID match the requested prefix
27 AmbiguousPrefix,
27 AmbiguousPrefix,
28 Corrupted,
28 #[from]
29 UnknowDataFormat(u8),
29 Other(HgError),
30 }
30 }
31
31
32 impl From<bytes_cast::FromBytesError> for RevlogError {
32 impl From<NodeMapError> for RevlogError {
33 fn from(_: bytes_cast::FromBytesError) -> Self {
33 fn from(error: NodeMapError) -> Self {
34 RevlogError::Corrupted
34 match error {
35 NodeMapError::MultipleResults => RevlogError::AmbiguousPrefix,
36 NodeMapError::RevisionNotInIndex(_) => RevlogError::corrupted(),
37 }
38 }
39 }
40
41 impl RevlogError {
42 fn corrupted() -> Self {
43 RevlogError::Other(HgError::corrupted("corrupted revlog"))
35 }
44 }
36 }
45 }
37
46
@@ -59,14 +68,12 b' impl Revlog {'
59 data_path: Option<&Path>,
68 data_path: Option<&Path>,
60 ) -> Result<Self, RevlogError> {
69 ) -> Result<Self, RevlogError> {
61 let index_path = index_path.as_ref();
70 let index_path = index_path.as_ref();
62 let index_mmap = repo
71 let index_mmap = repo.store_vfs().mmap_open(&index_path)?;
63 .store_vfs()
64 .mmap_open(&index_path)
65 .map_err(RevlogError::IoError)?;
66
72
67 let version = get_version(&index_mmap);
73 let version = get_version(&index_mmap);
68 if version != 1 {
74 if version != 1 {
69 return Err(RevlogError::UnsuportedVersion(version));
75 // A proper new version should have had a repo/store requirement.
76 return Err(RevlogError::corrupted());
70 }
77 }
71
78
72 let index = Index::new(Box::new(index_mmap))?;
79 let index = Index::new(Box::new(index_mmap))?;
@@ -80,10 +87,7 b' impl Revlog {'
80 None
87 None
81 } else {
88 } else {
82 let data_path = data_path.unwrap_or(&default_data_path);
89 let data_path = data_path.unwrap_or(&default_data_path);
83 let data_mmap = repo
90 let data_mmap = repo.store_vfs().mmap_open(data_path)?;
84 .store_vfs()
85 .mmap_open(data_path)
86 .map_err(RevlogError::IoError)?;
87 Some(Box::new(data_mmap))
91 Some(Box::new(data_mmap))
88 };
92 };
89
93
@@ -121,9 +125,7 b' impl Revlog {'
121 ) -> Result<Revision, RevlogError> {
125 ) -> Result<Revision, RevlogError> {
122 if let Some(nodemap) = &self.nodemap {
126 if let Some(nodemap) = &self.nodemap {
123 return nodemap
127 return nodemap
124 .find_bin(&self.index, node)
128 .find_bin(&self.index, node)?
125 // TODO: propagate details of this error:
126 .map_err(|_| RevlogError::Corrupted)?
127 .ok_or(RevlogError::InvalidRevision);
129 .ok_or(RevlogError::InvalidRevision);
128 }
130 }
129
131
@@ -136,7 +138,9 b' impl Revlog {'
136 let mut found_by_prefix = None;
138 let mut found_by_prefix = None;
137 for rev in (0..self.len() as Revision).rev() {
139 for rev in (0..self.len() as Revision).rev() {
138 let index_entry =
140 let index_entry =
139 self.index.get_entry(rev).ok_or(RevlogError::Corrupted)?;
141 self.index.get_entry(rev).ok_or(HgError::corrupted(
142 "revlog references a revision not in the index",
143 ))?;
140 if node == *index_entry.hash() {
144 if node == *index_entry.hash() {
141 return Ok(rev);
145 return Ok(rev);
142 }
146 }
@@ -167,8 +171,9 b' impl Revlog {'
167 let mut delta_chain = vec![];
171 let mut delta_chain = vec![];
168 while let Some(base_rev) = entry.base_rev {
172 while let Some(base_rev) = entry.base_rev {
169 delta_chain.push(entry);
173 delta_chain.push(entry);
170 entry =
174 entry = self
171 self.get_entry(base_rev).or(Err(RevlogError::Corrupted))?;
175 .get_entry(base_rev)
176 .map_err(|_| RevlogError::corrupted())?;
172 }
177 }
173
178
174 // TODO do not look twice in the index
179 // TODO do not look twice in the index
@@ -191,7 +196,7 b' impl Revlog {'
191 ) {
196 ) {
192 Ok(data)
197 Ok(data)
193 } else {
198 } else {
194 Err(RevlogError::Corrupted)
199 Err(RevlogError::corrupted())
195 }
200 }
196 }
201 }
197
202
@@ -301,7 +306,8 b" impl<'a> RevlogEntry<'a> {"
301 b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
306 b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data()?)),
302 // zstd data.
307 // zstd data.
303 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
308 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data()?)),
304 format_type => Err(RevlogError::UnknowDataFormat(format_type)),
309 // A proper new format should have had a repo/store requirement.
310 _format_type => Err(RevlogError::corrupted()),
305 }
311 }
306 }
312 }
307
313
@@ -311,13 +317,13 b" impl<'a> RevlogEntry<'a> {"
311 let mut buf = Vec::with_capacity(self.compressed_len);
317 let mut buf = Vec::with_capacity(self.compressed_len);
312 decoder
318 decoder
313 .read_to_end(&mut buf)
319 .read_to_end(&mut buf)
314 .or(Err(RevlogError::Corrupted))?;
320 .map_err(|_| RevlogError::corrupted())?;
315 Ok(buf)
321 Ok(buf)
316 } else {
322 } else {
317 let mut buf = vec![0; self.uncompressed_len];
323 let mut buf = vec![0; self.uncompressed_len];
318 decoder
324 decoder
319 .read_exact(&mut buf)
325 .read_exact(&mut buf)
320 .or(Err(RevlogError::Corrupted))?;
326 .map_err(|_| RevlogError::corrupted())?;
321 Ok(buf)
327 Ok(buf)
322 }
328 }
323 }
329 }
@@ -326,14 +332,14 b" impl<'a> RevlogEntry<'a> {"
326 if self.is_delta() {
332 if self.is_delta() {
327 let mut buf = Vec::with_capacity(self.compressed_len);
333 let mut buf = Vec::with_capacity(self.compressed_len);
328 zstd::stream::copy_decode(self.bytes, &mut buf)
334 zstd::stream::copy_decode(self.bytes, &mut buf)
329 .or(Err(RevlogError::Corrupted))?;
335 .map_err(|_| RevlogError::corrupted())?;
330 Ok(buf)
336 Ok(buf)
331 } else {
337 } else {
332 let mut buf = vec![0; self.uncompressed_len];
338 let mut buf = vec![0; self.uncompressed_len];
333 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
339 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
334 .or(Err(RevlogError::Corrupted))?;
340 .map_err(|_| RevlogError::corrupted())?;
335 if len != self.uncompressed_len {
341 if len != self.uncompressed_len {
336 Err(RevlogError::Corrupted)
342 Err(RevlogError::corrupted())
337 } else {
343 } else {
338 Ok(buf)
344 Ok(buf)
339 }
345 }
@@ -103,9 +103,6 b' impl From<FindRootError> for CommandErro'
103 impl From<(RevlogError, &str)> for CommandError {
103 impl From<(RevlogError, &str)> for CommandError {
104 fn from((err, rev): (RevlogError, &str)) -> CommandError {
104 fn from((err, rev): (RevlogError, &str)) -> CommandError {
105 match err {
105 match err {
106 RevlogError::IoError(err) => CommandError::Abort(Some(
107 utf8_to_local(&format!("abort: {}\n", err)).into(),
108 )),
109 RevlogError::InvalidRevision => CommandError::Abort(Some(
106 RevlogError::InvalidRevision => CommandError::Abort(Some(
110 utf8_to_local(&format!(
107 utf8_to_local(&format!(
111 "abort: invalid revision identifier {}\n",
108 "abort: invalid revision identifier {}\n",
@@ -120,27 +117,7 b' impl From<(RevlogError, &str)> for Comma'
120 ))
117 ))
121 .into(),
118 .into(),
122 )),
119 )),
123 RevlogError::UnsuportedVersion(version) => {
120 RevlogError::Other(err) => CommandError::Other(err),
124 CommandError::Abort(Some(
125 utf8_to_local(&format!(
126 "abort: unsupported revlog version {}\n",
127 version
128 ))
129 .into(),
130 ))
131 }
132 RevlogError::Corrupted => {
133 CommandError::Abort(Some("abort: corrupted revlog\n".into()))
134 }
135 RevlogError::UnknowDataFormat(format) => {
136 CommandError::Abort(Some(
137 utf8_to_local(&format!(
138 "abort: unknow revlog dataformat {:?}\n",
139 format
140 ))
141 .into(),
142 ))
143 }
144 }
121 }
145 }
122 }
146 }
123 }
General Comments 0
You need to be logged in to leave comments. Login now