Details
Details
- Reviewers
Alphare - Group Reviewers
hg-reviewers - Commits
- rHG68a15b5a7e58: rust: Replace DirstatePackError with HgError
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Branch
- default
- Lint
No Linters Available - Unit
No Unit Test Coverage
| Alphare |
| hg-reviewers |
| No Linters Available |
| No Unit Test Coverage |
| Path | Packages | |||
|---|---|---|---|---|
| M | rust/hg-core/src/dirstate/parsers.rs (24 lines) | |||
| M | rust/hg-core/src/lib.rs (15 lines) | |||
| M | rust/hg-cpython/src/parsers.rs (18 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| fae0c8053fb9 | d09510b9d837 | Simon Sapin | Jan 27 2021, 7:41 AM |
| Status | Author | Revision | |
|---|---|---|---|
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin | ||
| Closed | SimonSapin |
| // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> | ||||
| // | // | ||||
| // This software may be used and distributed according to the terms of the | // This software may be used and distributed according to the terms of the | ||||
| // GNU General Public License version 2 or any later version. | // GNU General Public License version 2 or any later version. | ||||
| use crate::errors::HgError; | |||||
| use crate::utils::hg_path::HgPath; | use crate::utils::hg_path::HgPath; | ||||
| use crate::{ | use crate::{ | ||||
| dirstate::{CopyMap, EntryState, StateMap}, | dirstate::{CopyMap, EntryState, StateMap}, | ||||
| DirstateEntry, DirstatePackError, DirstateParents, DirstateParseError, | DirstateEntry, DirstateParents, DirstateParseError, | ||||
| }; | }; | ||||
| use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; | use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; | ||||
| use micro_timer::timed; | use micro_timer::timed; | ||||
| use std::convert::{TryFrom, TryInto}; | use std::convert::{TryFrom, TryInto}; | ||||
| use std::io::Cursor; | use std::io::Cursor; | ||||
| use std::time::Duration; | use std::time::Duration; | ||||
| /// Parents are stored in the dirstate as byte hashes. | /// Parents are stored in the dirstate as byte hashes. | ||||
| /// `now` is the duration in seconds since the Unix epoch | /// `now` is the duration in seconds since the Unix epoch | ||||
| #[cfg(not(feature = "dirstate-tree"))] | #[cfg(not(feature = "dirstate-tree"))] | ||||
| pub fn pack_dirstate( | pub fn pack_dirstate( | ||||
| state_map: &mut StateMap, | state_map: &mut StateMap, | ||||
| copy_map: &CopyMap, | copy_map: &CopyMap, | ||||
| parents: DirstateParents, | parents: DirstateParents, | ||||
| now: Duration, | now: Duration, | ||||
| ) -> Result<Vec<u8>, DirstatePackError> { | ) -> Result<Vec<u8>, HgError> { | ||||
| // TODO move away from i32 before 2038. | // TODO move away from i32 before 2038. | ||||
| let now: i32 = now.as_secs().try_into().expect("time overflow"); | let now: i32 = now.as_secs().try_into().expect("time overflow"); | ||||
| let expected_size: usize = state_map | let expected_size: usize = state_map | ||||
| .iter() | .iter() | ||||
| .map(|(filename, _)| { | .map(|(filename, _)| { | ||||
| let mut length = MIN_ENTRY_SIZE + filename.len(); | let mut length = MIN_ENTRY_SIZE + filename.len(); | ||||
| if let Some(copy) = copy_map.get(filename) { | if let Some(copy) = copy_map.get(filename) { | ||||
| }; | }; | ||||
| } | } | ||||
| let mut new_filename = new_filename.into_vec(); | let mut new_filename = new_filename.into_vec(); | ||||
| if let Some(copy) = copy_map.get(filename) { | if let Some(copy) = copy_map.get(filename) { | ||||
| new_filename.push(b'\0'); | new_filename.push(b'\0'); | ||||
| new_filename.extend(copy.bytes()); | new_filename.extend(copy.bytes()); | ||||
| } | } | ||||
| packed.write_u8(entry.state.into())?; | // Unwrapping because `impl std::io::Write for Vec<u8>` never errors | ||||
| packed.write_i32::<BigEndian>(entry.mode)?; | packed.write_u8(entry.state.into()).unwrap(); | ||||
| packed.write_i32::<BigEndian>(entry.size)?; | packed.write_i32::<BigEndian>(entry.mode).unwrap(); | ||||
| packed.write_i32::<BigEndian>(new_mtime)?; | packed.write_i32::<BigEndian>(entry.size).unwrap(); | ||||
| packed.write_i32::<BigEndian>(new_filename.len() as i32)?; | packed.write_i32::<BigEndian>(new_mtime).unwrap(); | ||||
| packed | |||||
| .write_i32::<BigEndian>(new_filename.len() as i32) | |||||
| .unwrap(); | |||||
| packed.extend(new_filename) | packed.extend(new_filename) | ||||
| } | } | ||||
| if packed.len() != expected_size { | if packed.len() != expected_size { | ||||
| return Err(DirstatePackError::BadSize(expected_size, packed.len())); | return Err(HgError::CorruptedRepository(format!( | ||||
| "bad dirstate size: {} != {}", | |||||
| expected_size, | |||||
| packed.len() | |||||
| ))); | |||||
| } | } | ||||
| Ok(packed) | Ok(packed) | ||||
| } | } | ||||
| /// `now` is the duration in seconds since the Unix epoch | /// `now` is the duration in seconds since the Unix epoch | ||||
| #[cfg(feature = "dirstate-tree")] | #[cfg(feature = "dirstate-tree")] | ||||
| pub fn pack_dirstate( | pub fn pack_dirstate( | ||||
| state_map: &mut StateMap, | state_map: &mut StateMap, | ||||
| Overflow => "Overflow in dirstate.".to_string(), | Overflow => "Overflow in dirstate.".to_string(), | ||||
| CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e), | CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e), | ||||
| Damaged => "Dirstate appears to be damaged.".to_string(), | Damaged => "Dirstate appears to be damaged.".to_string(), | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #[derive(Debug, PartialEq)] | #[derive(Debug, PartialEq)] | ||||
| pub enum DirstatePackError { | |||||
| CorruptedEntry(String), | |||||
| CorruptedParent, | |||||
| BadSize(usize, usize), | |||||
| } | |||||
| impl From<std::io::Error> for DirstatePackError { | |||||
| fn from(e: std::io::Error) -> Self { | |||||
| DirstatePackError::CorruptedEntry(e.to_string()) | |||||
| } | |||||
| } | |||||
| #[derive(Debug, PartialEq)] | |||||
| pub enum DirstateMapError { | pub enum DirstateMapError { | ||||
| PathNotFound(HgPathBuf), | PathNotFound(HgPathBuf), | ||||
| EmptyPath, | EmptyPath, | ||||
| InvalidPath(HgPathError), | InvalidPath(HgPathError), | ||||
| } | } | ||||
| impl ToString for DirstateMapError { | impl ToString for DirstateMapError { | ||||
| fn to_string(&self) -> String { | fn to_string(&self) -> String { | ||||
| match self { | match self { | ||||
| DirstateMapError::PathNotFound(_) => { | DirstateMapError::PathNotFound(_) => { | ||||
| "expected a value, found none".to_string() | "expected a value, found none".to_string() | ||||
| } | } | ||||
| DirstateMapError::EmptyPath => "Overflow in dirstate.".to_string(), | DirstateMapError::EmptyPath => "Overflow in dirstate.".to_string(), | ||||
| DirstateMapError::InvalidPath(e) => e.to_string(), | DirstateMapError::InvalidPath(e) => e.to_string(), | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #[derive(Debug, derive_more::From)] | #[derive(Debug, derive_more::From)] | ||||
| pub enum DirstateError { | pub enum DirstateError { | ||||
| Parse(DirstateParseError), | Parse(DirstateParseError), | ||||
| Pack(DirstatePackError), | |||||
| Map(DirstateMapError), | Map(DirstateMapError), | ||||
| IO(std::io::Error), | IO(std::io::Error), | ||||
| Common(errors::HgError), | |||||
| } | } | ||||
| #[derive(Debug, derive_more::From)] | #[derive(Debug, derive_more::From)] | ||||
| pub enum PatternError { | pub enum PatternError { | ||||
| #[from] | #[from] | ||||
| Path(HgPathError), | Path(HgPathError), | ||||
| UnsupportedSyntax(String), | UnsupportedSyntax(String), | ||||
| UnsupportedSyntaxInFile(String, String, usize), | UnsupportedSyntaxInFile(String, String, usize), | ||||
| //! | //! | ||||
| //! From Python, this will be seen as `mercurial.rustext.parsers` | //! From Python, this will be seen as `mercurial.rustext.parsers` | ||||
| use cpython::{ | use cpython::{ | ||||
| exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python, | exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python, | ||||
| PythonObject, ToPyObject, | PythonObject, ToPyObject, | ||||
| }; | }; | ||||
| use hg::{ | use hg::{ | ||||
| pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, | pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, | ||||
| DirstatePackError, DirstateParents, DirstateParseError, FastHashMap, | DirstateParents, DirstateParseError, FastHashMap, PARENT_SIZE, | ||||
| PARENT_SIZE, | |||||
| }; | }; | ||||
| use std::convert::TryInto; | use std::convert::TryInto; | ||||
| use crate::dirstate::{extract_dirstate, make_dirstate_tuple}; | use crate::dirstate::{extract_dirstate, make_dirstate_tuple}; | ||||
| use std::time::Duration; | use std::time::Duration; | ||||
| fn parse_dirstate_wrapper( | fn parse_dirstate_wrapper( | ||||
| py: Python, | py: Python, | ||||
| dmap.set_item( | dmap.set_item( | ||||
| py, | py, | ||||
| PyBytes::new(py, filename.as_bytes()), | PyBytes::new(py, filename.as_bytes()), | ||||
| make_dirstate_tuple(py, &entry)?, | make_dirstate_tuple(py, &entry)?, | ||||
| )?; | )?; | ||||
| } | } | ||||
| Ok(PyBytes::new(py, &packed)) | Ok(PyBytes::new(py, &packed)) | ||||
| } | } | ||||
| Err(error) => Err(PyErr::new::<exc::ValueError, _>( | Err(error) => { | ||||
| py, | Err(PyErr::new::<exc::ValueError, _>(py, error.to_string())) | ||||
| match error { | |||||
| DirstatePackError::CorruptedParent => { | |||||
| "expected a 20-byte hash".to_string() | |||||
| } | |||||
| DirstatePackError::CorruptedEntry(e) => e, | |||||
| DirstatePackError::BadSize(expected, actual) => { | |||||
| format!("bad dirstate size: {} != {}", actual, expected) | |||||
| } | } | ||||
| }, | |||||
| )), | |||||
| } | } | ||||
| } | } | ||||
| /// Create the module, with `__package__` given from parent | /// Create the module, with `__package__` given from parent | ||||
| pub fn init_parsers_module(py: Python, package: &str) -> PyResult<PyModule> { | pub fn init_parsers_module(py: Python, package: &str) -> PyResult<PyModule> { | ||||
| let dotted_name = &format!("{}.parsers", package); | let dotted_name = &format!("{}.parsers", package); | ||||
| let m = PyModule::new(py, dotted_name)?; | let m = PyModule::new(py, dotted_name)?; | ||||