Show More
@@ -5,7 +5,8 b'' | |||||
5 | // This software may be used and distributed according to the terms of the |
|
5 | // This software may be used and distributed according to the terms of the | |
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::{utils::hg_path::HgPathBuf, DirstateParseError, FastHashMap}; |
|
8 | use crate::errors::HgError; | |
|
9 | use crate::{utils::hg_path::HgPathBuf, FastHashMap}; | |||
9 | use std::collections::hash_map; |
|
10 | use std::collections::hash_map; | |
10 | use std::convert::TryFrom; |
|
11 | use std::convert::TryFrom; | |
11 |
|
12 | |||
@@ -60,7 +61,7 b' pub enum EntryState {' | |||||
60 | } |
|
61 | } | |
61 |
|
62 | |||
62 | impl TryFrom<u8> for EntryState { |
|
63 | impl TryFrom<u8> for EntryState { | |
63 |
type Error = |
|
64 | type Error = HgError; | |
64 |
|
65 | |||
65 | fn try_from(value: u8) -> Result<Self, Self::Error> { |
|
66 | fn try_from(value: u8) -> Result<Self, Self::Error> { | |
66 | match value { |
|
67 | match value { | |
@@ -69,8 +70,8 b' impl TryFrom<u8> for EntryState {' | |||||
69 | b'r' => Ok(EntryState::Removed), |
|
70 | b'r' => Ok(EntryState::Removed), | |
70 | b'm' => Ok(EntryState::Merged), |
|
71 | b'm' => Ok(EntryState::Merged), | |
71 | b'?' => Ok(EntryState::Unknown), |
|
72 | b'?' => Ok(EntryState::Unknown), | |
72 |
_ => Err( |
|
73 | _ => Err(HgError::CorruptedRepository(format!( | |
73 | "Incorrect entry state {}", |
|
74 | "Incorrect dirstate entry state {}", | |
74 | value |
|
75 | value | |
75 | ))), |
|
76 | ))), | |
76 | } |
|
77 | } |
@@ -5,6 +5,7 b'' | |||||
5 | // This software may be used and distributed according to the terms of the |
|
5 | // This software may be used and distributed according to the terms of the | |
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::errors::HgError; | |||
8 | use crate::revlog::node::NULL_NODE_ID; |
|
9 | use crate::revlog::node::NULL_NODE_ID; | |
9 | use crate::{ |
|
10 | use crate::{ | |
10 | dirstate::{parsers::PARENT_SIZE, EntryState, SIZE_FROM_OTHER_PARENT}, |
|
11 | dirstate::{parsers::PARENT_SIZE, EntryState, SIZE_FROM_OTHER_PARENT}, | |
@@ -14,7 +15,7 b' use crate::{' | |||||
14 | hg_path::{HgPath, HgPathBuf}, |
|
15 | hg_path::{HgPath, HgPathBuf}, | |
15 | }, |
|
16 | }, | |
16 | CopyMap, DirsMultiset, DirstateEntry, DirstateError, DirstateMapError, |
|
17 | CopyMap, DirsMultiset, DirstateEntry, DirstateError, DirstateMapError, | |
17 |
DirstateParents |
|
18 | DirstateParents, FastHashMap, StateMap, | |
18 | }; |
|
19 | }; | |
19 | use micro_timer::timed; |
|
20 | use micro_timer::timed; | |
20 | use std::collections::HashSet; |
|
21 | use std::collections::HashSet; | |
@@ -370,7 +371,9 b' impl DirstateMap {' | |||||
370 | p2: NULL_NODE_ID, |
|
371 | p2: NULL_NODE_ID, | |
371 | }; |
|
372 | }; | |
372 | } else { |
|
373 | } else { | |
373 | return Err(DirstateError::Parse(DirstateParseError::Damaged)); |
|
374 | return Err( | |
|
375 | HgError::corrupted("Dirstate appears to be damaged").into() | |||
|
376 | ); | |||
374 | } |
|
377 | } | |
375 |
|
378 | |||
376 | self.parents = Some(parents); |
|
379 | self.parents = Some(parents); |
@@ -7,7 +7,7 b' use crate::errors::HgError;' | |||||
7 | use crate::utils::hg_path::HgPath; |
|
7 | use crate::utils::hg_path::HgPath; | |
8 | use crate::{ |
|
8 | use crate::{ | |
9 | dirstate::{CopyMap, EntryState, StateMap}, |
|
9 | dirstate::{CopyMap, EntryState, StateMap}, | |
10 |
DirstateEntry, DirstateParents, |
|
10 | DirstateEntry, DirstateParents, | |
11 | }; |
|
11 | }; | |
12 | use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; |
|
12 | use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; | |
13 | use micro_timer::timed; |
|
13 | use micro_timer::timed; | |
@@ -27,11 +27,9 b" type ParseResult<'a> = (" | |||||
27 | ); |
|
27 | ); | |
28 |
|
28 | |||
29 | #[timed] |
|
29 | #[timed] | |
30 | pub fn parse_dirstate( |
|
30 | pub fn parse_dirstate(contents: &[u8]) -> Result<ParseResult, HgError> { | |
31 | contents: &[u8], |
|
|||
32 | ) -> Result<ParseResult, DirstateParseError> { |
|
|||
33 | if contents.len() < PARENT_SIZE * 2 { |
|
31 | if contents.len() < PARENT_SIZE * 2 { | |
34 | return Err(DirstateParseError::TooLittleData); |
|
32 | return Err(HgError::corrupted("Too little data for dirstate.")); | |
35 | } |
|
33 | } | |
36 | let mut copies = vec![]; |
|
34 | let mut copies = vec![]; | |
37 | let mut entries = vec![]; |
|
35 | let mut entries = vec![]; | |
@@ -44,19 +42,21 b' pub fn parse_dirstate(' | |||||
44 |
|
42 | |||
45 | while curr_pos < contents.len() { |
|
43 | while curr_pos < contents.len() { | |
46 | if curr_pos + MIN_ENTRY_SIZE > contents.len() { |
|
44 | if curr_pos + MIN_ENTRY_SIZE > contents.len() { | |
47 |
return Err( |
|
45 | return Err(HgError::corrupted("Overflow in dirstate.")); | |
48 | } |
|
46 | } | |
49 | let entry_bytes = &contents[curr_pos..]; |
|
47 | let entry_bytes = &contents[curr_pos..]; | |
50 |
|
48 | |||
51 | let mut cursor = Cursor::new(entry_bytes); |
|
49 | let mut cursor = Cursor::new(entry_bytes); | |
52 | let state = EntryState::try_from(cursor.read_u8()?)?; |
|
50 | // Unwraping errors from `byteorder` as weβve already checked | |
53 | let mode = cursor.read_i32::<BigEndian>()?; |
|
51 | // `MIN_ENTRY_SIZE` so the input should never be too short. | |
54 | let size = cursor.read_i32::<BigEndian>()?; |
|
52 | let state = EntryState::try_from(cursor.read_u8().unwrap())?; | |
55 |
let m |
|
53 | let mode = cursor.read_i32::<BigEndian>().unwrap(); | |
56 |
let |
|
54 | let size = cursor.read_i32::<BigEndian>().unwrap(); | |
|
55 | let mtime = cursor.read_i32::<BigEndian>().unwrap(); | |||
|
56 | let path_len = cursor.read_i32::<BigEndian>().unwrap() as usize; | |||
57 |
|
57 | |||
58 | if path_len > contents.len() - curr_pos { |
|
58 | if path_len > contents.len() - curr_pos { | |
59 |
return Err( |
|
59 | return Err(HgError::corrupted("Overflow in dirstate.")); | |
60 | } |
|
60 | } | |
61 |
|
61 | |||
62 | // Slice instead of allocating a Vec needed for `read_exact` |
|
62 | // Slice instead of allocating a Vec needed for `read_exact` |
@@ -51,33 +51,6 b' pub type LineNumber = usize;' | |||||
51 | /// write access to your repository, you have other issues. |
|
51 | /// write access to your repository, you have other issues. | |
52 | pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>; |
|
52 | pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>; | |
53 |
|
53 | |||
54 | #[derive(Clone, Debug, PartialEq)] |
|
|||
55 | pub enum DirstateParseError { |
|
|||
56 | TooLittleData, |
|
|||
57 | Overflow, |
|
|||
58 | // TODO refactor to use bytes instead of String |
|
|||
59 | CorruptedEntry(String), |
|
|||
60 | Damaged, |
|
|||
61 | } |
|
|||
62 |
|
||||
63 | impl From<std::io::Error> for DirstateParseError { |
|
|||
64 | fn from(e: std::io::Error) -> Self { |
|
|||
65 | DirstateParseError::CorruptedEntry(e.to_string()) |
|
|||
66 | } |
|
|||
67 | } |
|
|||
68 |
|
||||
69 | impl ToString for DirstateParseError { |
|
|||
70 | fn to_string(&self) -> String { |
|
|||
71 | use crate::DirstateParseError::*; |
|
|||
72 | match self { |
|
|||
73 | TooLittleData => "Too little data for dirstate.".to_string(), |
|
|||
74 | Overflow => "Overflow in dirstate.".to_string(), |
|
|||
75 | CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e), |
|
|||
76 | Damaged => "Dirstate appears to be damaged.".to_string(), |
|
|||
77 | } |
|
|||
78 | } |
|
|||
79 | } |
|
|||
80 |
|
||||
81 | #[derive(Debug, PartialEq)] |
|
54 | #[derive(Debug, PartialEq)] | |
82 | pub enum DirstateMapError { |
|
55 | pub enum DirstateMapError { | |
83 | PathNotFound(HgPathBuf), |
|
56 | PathNotFound(HgPathBuf), | |
@@ -99,9 +72,7 b' impl ToString for DirstateMapError {' | |||||
99 |
|
72 | |||
100 | #[derive(Debug, derive_more::From)] |
|
73 | #[derive(Debug, derive_more::From)] | |
101 | pub enum DirstateError { |
|
74 | pub enum DirstateError { | |
102 | Parse(DirstateParseError), |
|
|||
103 | Map(DirstateMapError), |
|
75 | Map(DirstateMapError), | |
104 | IO(std::io::Error), |
|
|||
105 | Common(errors::HgError), |
|
76 | Common(errors::HgError), | |
106 | } |
|
77 | } | |
107 |
|
78 |
@@ -6,24 +6,16 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::repo::Repo; |
|
10 | use crate::repo::Repo; | |
10 | use crate::revlog::changelog::Changelog; |
|
11 | use crate::revlog::changelog::Changelog; | |
11 | use crate::revlog::manifest::{Manifest, ManifestEntry}; |
|
12 | use crate::revlog::manifest::{Manifest, ManifestEntry}; | |
12 | use crate::revlog::node::Node; |
|
13 | use crate::revlog::node::Node; | |
13 | use crate::revlog::revlog::RevlogError; |
|
14 | use crate::revlog::revlog::RevlogError; | |
14 | use crate::utils::hg_path::HgPath; |
|
15 | use crate::utils::hg_path::HgPath; | |
15 |
use crate:: |
|
16 | use crate::EntryState; | |
16 | use rayon::prelude::*; |
|
17 | use rayon::prelude::*; | |
17 |
|
18 | |||
18 | /// Error type for `Dirstate` methods |
|
|||
19 | #[derive(Debug, derive_more::From)] |
|
|||
20 | pub enum ListDirstateTrackedFilesError { |
|
|||
21 | /// Error when reading the `dirstate` file |
|
|||
22 | IoError(std::io::Error), |
|
|||
23 | /// Error when parsing the `dirstate` file |
|
|||
24 | ParseError(DirstateParseError), |
|
|||
25 | } |
|
|||
26 |
|
||||
27 | /// List files under Mercurial control in the working directory |
|
19 | /// List files under Mercurial control in the working directory | |
28 | /// by reading the dirstate |
|
20 | /// by reading the dirstate | |
29 | pub struct Dirstate { |
|
21 | pub struct Dirstate { | |
@@ -32,16 +24,18 b' pub struct Dirstate {' | |||||
32 | } |
|
24 | } | |
33 |
|
25 | |||
34 | impl Dirstate { |
|
26 | impl Dirstate { | |
35 |
pub fn new(repo: &Repo) -> Result<Self, |
|
27 | pub fn new(repo: &Repo) -> Result<Self, HgError> { | |
36 |
let content = repo |
|
28 | let content = repo | |
|
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())?; | |||
37 | Ok(Self { content }) |
|
34 | Ok(Self { content }) | |
38 | } |
|
35 | } | |
39 |
|
36 | |||
40 | pub fn tracked_files( |
|
37 | pub fn tracked_files(&self) -> Result<Vec<&HgPath>, HgError> { | |
41 | &self, |
|
38 | let (_, entries, _) = parse_dirstate(&self.content)?; | |
42 | ) -> Result<Vec<&HgPath>, ListDirstateTrackedFilesError> { |
|
|||
43 | let (_, entries, _) = parse_dirstate(&self.content) |
|
|||
44 | .map_err(ListDirstateTrackedFilesError::ParseError)?; |
|
|||
45 | let mut files: Vec<&HgPath> = entries |
|
39 | let mut files: Vec<&HgPath> = entries | |
46 | .into_iter() |
|
40 | .into_iter() | |
47 | .filter_map(|(path, entry)| match entry.state { |
|
41 | .filter_map(|(path, entry)| match entry.state { |
@@ -10,5 +10,5 b' mod list_tracked_files;' | |||||
10 | pub use cat::cat; |
|
10 | pub use cat::cat; | |
11 | pub use debugdata::{debug_data, DebugDataKind}; |
|
11 | pub use debugdata::{debug_data, DebugDataKind}; | |
12 | pub use find_root::{find_root, find_root_from_path, FindRootError}; |
|
12 | pub use find_root::{find_root, find_root_from_path, FindRootError}; | |
|
13 | pub use list_tracked_files::Dirstate; | |||
13 | pub use list_tracked_files::{list_rev_tracked_files, FilesForRev}; |
|
14 | pub use list_tracked_files::{list_rev_tracked_files, FilesForRev}; | |
14 | pub use list_tracked_files::{Dirstate, ListDirstateTrackedFilesError}; |
|
@@ -24,10 +24,7 b' use cpython::{' | |||||
24 | exc, PyBytes, PyDict, PyErr, PyList, PyModule, PyObject, PyResult, |
|
24 | exc, PyBytes, PyDict, PyErr, PyList, PyModule, PyObject, PyResult, | |
25 | PySequence, Python, |
|
25 | PySequence, Python, | |
26 | }; |
|
26 | }; | |
27 | use hg::{ |
|
27 | use hg::{utils::hg_path::HgPathBuf, DirstateEntry, EntryState, StateMap}; | |
28 | utils::hg_path::HgPathBuf, DirstateEntry, DirstateParseError, EntryState, |
|
|||
29 | StateMap, |
|
|||
30 | }; |
|
|||
31 | use libc::{c_char, c_int}; |
|
28 | use libc::{c_char, c_int}; | |
32 | use std::convert::TryFrom; |
|
29 | use std::convert::TryFrom; | |
33 |
|
30 | |||
@@ -79,11 +76,10 b' pub fn extract_dirstate(py: Python, dmap' | |||||
79 | .map(|(filename, stats)| { |
|
76 | .map(|(filename, stats)| { | |
80 | let stats = stats.extract::<PySequence>(py)?; |
|
77 | let stats = stats.extract::<PySequence>(py)?; | |
81 | let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?; |
|
78 | let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?; | |
82 | let state = EntryState::try_from(state.data(py)[0]).map_err( |
|
79 | let state = | |
83 | |e: DirstateParseError| { |
|
80 | EntryState::try_from(state.data(py)[0]).map_err(|e| { | |
84 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
81 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
85 |
} |
|
82 | })?; | |
86 | )?; |
|
|||
87 | let mode = stats.get_item(py, 1)?.extract(py)?; |
|
83 | let mode = stats.get_item(py, 1)?.extract(py)?; | |
88 | let size = stats.get_item(py, 2)?.extract(py)?; |
|
84 | let size = stats.get_item(py, 2)?.extract(py)?; | |
89 | let mtime = stats.get_item(py, 3)?.extract(py)?; |
|
85 | let mtime = stats.get_item(py, 3)?.extract(py)?; |
@@ -18,9 +18,9 b' use cpython::{' | |||||
18 |
|
18 | |||
19 | use crate::dirstate::extract_dirstate; |
|
19 | use crate::dirstate::extract_dirstate; | |
20 | use hg::{ |
|
20 | use hg::{ | |
|
21 | errors::HgError, | |||
21 | utils::hg_path::{HgPath, HgPathBuf}, |
|
22 | utils::hg_path::{HgPath, HgPathBuf}, | |
22 |
DirsMultiset, DirsMultisetIter, DirstateMapError, |
|
23 | DirsMultiset, DirsMultisetIter, DirstateMapError, EntryState, | |
23 | EntryState, |
|
|||
24 | }; |
|
24 | }; | |
25 |
|
25 | |||
26 | py_class!(pub class Dirs |py| { |
|
26 | py_class!(pub class Dirs |py| { | |
@@ -38,7 +38,7 b' py_class!(pub class Dirs |py| {' | |||||
38 | skip_state = Some( |
|
38 | skip_state = Some( | |
39 | skip.extract::<PyBytes>(py)?.data(py)[0] |
|
39 | skip.extract::<PyBytes>(py)?.data(py)[0] | |
40 | .try_into() |
|
40 | .try_into() | |
41 |
.map_err(|e: |
|
41 | .map_err(|e: HgError| { | |
42 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
42 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
43 | })?, |
|
43 | })?, | |
44 | ); |
|
44 | ); | |
@@ -46,7 +46,7 b' py_class!(pub class Dirs |py| {' | |||||
46 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { |
|
46 | let inner = if let Ok(map) = map.cast_as::<PyDict>(py) { | |
47 | let dirstate = extract_dirstate(py, &map)?; |
|
47 | let dirstate = extract_dirstate(py, &map)?; | |
48 | DirsMultiset::from_dirstate(&dirstate, skip_state) |
|
48 | DirsMultiset::from_dirstate(&dirstate, skip_state) | |
49 | .map_err(|e| { |
|
49 | .map_err(|e: DirstateMapError| { | |
50 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
50 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
51 | })? |
|
51 | })? | |
52 | } else { |
|
52 | } else { |
@@ -26,10 +26,10 b' use crate::{' | |||||
26 | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, |
|
26 | dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, | |
27 | }; |
|
27 | }; | |
28 | use hg::{ |
|
28 | use hg::{ | |
|
29 | errors::HgError, | |||
29 | utils::hg_path::{HgPath, HgPathBuf}, |
|
30 | utils::hg_path::{HgPath, HgPathBuf}, | |
30 | DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap, |
|
31 | DirsMultiset, DirstateEntry, DirstateMap as RustDirstateMap, | |
31 |
DirstateMapError, DirstateParents, |
|
32 | DirstateMapError, DirstateParents, EntryState, StateMapIter, PARENT_SIZE, | |
32 | StateMapIter, PARENT_SIZE, |
|
|||
33 | }; |
|
33 | }; | |
34 |
|
34 | |||
35 | // TODO |
|
35 | // TODO | |
@@ -84,13 +84,13 b' py_class!(pub class DirstateMap |py| {' | |||||
84 | HgPath::new(f.extract::<PyBytes>(py)?.data(py)), |
|
84 | HgPath::new(f.extract::<PyBytes>(py)?.data(py)), | |
85 | oldstate.extract::<PyBytes>(py)?.data(py)[0] |
|
85 | oldstate.extract::<PyBytes>(py)?.data(py)[0] | |
86 | .try_into() |
|
86 | .try_into() | |
87 |
.map_err(|e: |
|
87 | .map_err(|e: HgError| { | |
88 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
88 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
89 | })?, |
|
89 | })?, | |
90 | DirstateEntry { |
|
90 | DirstateEntry { | |
91 | state: state.extract::<PyBytes>(py)?.data(py)[0] |
|
91 | state: state.extract::<PyBytes>(py)?.data(py)[0] | |
92 | .try_into() |
|
92 | .try_into() | |
93 |
.map_err(|e: |
|
93 | .map_err(|e: HgError| { | |
94 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
94 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
95 | })?, |
|
95 | })?, | |
96 | mode: mode.extract(py)?, |
|
96 | mode: mode.extract(py)?, | |
@@ -113,7 +113,7 b' py_class!(pub class DirstateMap |py| {' | |||||
113 | HgPath::new(f.extract::<PyBytes>(py)?.data(py)), |
|
113 | HgPath::new(f.extract::<PyBytes>(py)?.data(py)), | |
114 | oldstate.extract::<PyBytes>(py)?.data(py)[0] |
|
114 | oldstate.extract::<PyBytes>(py)?.data(py)[0] | |
115 | .try_into() |
|
115 | .try_into() | |
116 |
.map_err(|e: |
|
116 | .map_err(|e: HgError| { | |
117 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
117 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
118 | })?, |
|
118 | })?, | |
119 | size.extract(py)?, |
|
119 | size.extract(py)?, | |
@@ -137,7 +137,7 b' py_class!(pub class DirstateMap |py| {' | |||||
137 | HgPath::new(f.extract::<PyBytes>(py)?.data(py)), |
|
137 | HgPath::new(f.extract::<PyBytes>(py)?.data(py)), | |
138 | oldstate.extract::<PyBytes>(py)?.data(py)[0] |
|
138 | oldstate.extract::<PyBytes>(py)?.data(py)[0] | |
139 | .try_into() |
|
139 | .try_into() | |
140 |
.map_err(|e: |
|
140 | .map_err(|e: HgError| { | |
141 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) |
|
141 | PyErr::new::<exc::ValueError, _>(py, e.to_string()) | |
142 | })?, |
|
142 | })?, | |
143 | ) |
|
143 | ) |
@@ -15,7 +15,7 b' use cpython::{' | |||||
15 | }; |
|
15 | }; | |
16 | use hg::{ |
|
16 | use hg::{ | |
17 | pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, |
|
17 | pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, | |
18 |
DirstateParents |
|
18 | DirstateParents, FastHashMap, PARENT_SIZE, | |
19 | }; |
|
19 | }; | |
20 | use std::convert::TryInto; |
|
20 | use std::convert::TryInto; | |
21 |
|
21 | |||
@@ -58,21 +58,7 b' fn parse_dirstate_wrapper(' | |||||
58 | .to_py_object(py), |
|
58 | .to_py_object(py), | |
59 | ) |
|
59 | ) | |
60 | } |
|
60 | } | |
61 | Err(e) => Err(PyErr::new::<exc::ValueError, _>( |
|
61 | Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())), | |
62 | py, |
|
|||
63 | match e { |
|
|||
64 | DirstateParseError::TooLittleData => { |
|
|||
65 | "too little data for parents".to_string() |
|
|||
66 | } |
|
|||
67 | DirstateParseError::Overflow => { |
|
|||
68 | "overflow in dirstate".to_string() |
|
|||
69 | } |
|
|||
70 | DirstateParseError::CorruptedEntry(e) => e, |
|
|||
71 | DirstateParseError::Damaged => { |
|
|||
72 | "dirstate appears to be damaged".to_string() |
|
|||
73 | } |
|
|||
74 | }, |
|
|||
75 | )), |
|
|||
76 | } |
|
62 | } | |
77 | } |
|
63 | } | |
78 |
|
64 |
@@ -2,7 +2,8 b' use crate::exitcode;' | |||||
2 | use crate::ui::utf8_to_local; |
|
2 | use crate::ui::utf8_to_local; | |
3 | use crate::ui::UiError; |
|
3 | use crate::ui::UiError; | |
4 | use format_bytes::format_bytes; |
|
4 | use format_bytes::format_bytes; | |
5 | use hg::operations::{FindRootError, ListDirstateTrackedFilesError}; |
|
5 | use hg::errors::HgError; | |
|
6 | use hg::operations::FindRootError; | |||
6 | use hg::requirements::RequirementsError; |
|
7 | use hg::requirements::RequirementsError; | |
7 | use hg::revlog::revlog::RevlogError; |
|
8 | use hg::revlog::revlog::RevlogError; | |
8 | use hg::utils::files::get_bytes_from_path; |
|
9 | use hg::utils::files::get_bytes_from_path; | |
@@ -27,6 +28,9 b' pub enum CommandError {' | |||||
27 | Abort(Option<Vec<u8>>), |
|
28 | Abort(Option<Vec<u8>>), | |
28 | /// A mercurial capability as not been implemented. |
|
29 | /// A mercurial capability as not been implemented. | |
29 | Unimplemented, |
|
30 | Unimplemented, | |
|
31 | /// Common cases | |||
|
32 | #[from] | |||
|
33 | Other(HgError), | |||
30 | } |
|
34 | } | |
31 |
|
35 | |||
32 | impl CommandError { |
|
36 | impl CommandError { | |
@@ -42,6 +46,10 b' impl CommandError {' | |||||
42 | CommandError::StderrError => exitcode::ABORT, |
|
46 | CommandError::StderrError => exitcode::ABORT, | |
43 | CommandError::Abort(_) => exitcode::ABORT, |
|
47 | CommandError::Abort(_) => exitcode::ABORT, | |
44 | CommandError::Unimplemented => exitcode::UNIMPLEMENTED_COMMAND, |
|
48 | CommandError::Unimplemented => exitcode::UNIMPLEMENTED_COMMAND, | |
|
49 | CommandError::Other(HgError::UnsupportedFeature(_)) => { | |||
|
50 | exitcode::UNIMPLEMENTED_COMMAND | |||
|
51 | } | |||
|
52 | CommandError::Other(_) => exitcode::ABORT, | |||
45 | } |
|
53 | } | |
46 | } |
|
54 | } | |
47 |
|
55 | |||
@@ -141,21 +149,3 b' impl From<(RevlogError, &str)> for Comma' | |||||
141 | } |
|
149 | } | |
142 | } |
|
150 | } | |
143 | } |
|
151 | } | |
144 |
|
||||
145 | impl From<ListDirstateTrackedFilesError> for CommandError { |
|
|||
146 | fn from(err: ListDirstateTrackedFilesError) -> Self { |
|
|||
147 | match err { |
|
|||
148 | ListDirstateTrackedFilesError::IoError(err) => { |
|
|||
149 | CommandError::Abort(Some( |
|
|||
150 | utf8_to_local(&format!("abort: {}\n", err)).into(), |
|
|||
151 | )) |
|
|||
152 | } |
|
|||
153 | ListDirstateTrackedFilesError::ParseError(_) => { |
|
|||
154 | CommandError::Abort(Some( |
|
|||
155 | // TODO find a better error message |
|
|||
156 | b"abort: parse error\n".to_vec(), |
|
|||
157 | )) |
|
|||
158 | } |
|
|||
159 | } |
|
|||
160 | } |
|
|||
161 | } |
|
General Comments 0
You need to be logged in to leave comments.
Login now