Show More
@@ -8,7 +8,7 | |||||
8 | // GNU General Public License version 2 or any later version. |
|
8 | // GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
10 | use crate::errors::HgError; |
|
10 | use crate::errors::HgError; | |
11 | use crate::exit_codes::CONFIG_PARSE_ERROR_ABORT; |
|
11 | use crate::exit_codes::{CONFIG_ERROR_ABORT, CONFIG_PARSE_ERROR_ABORT}; | |
12 | use crate::utils::files::{get_bytes_from_path, get_path_from_bytes}; |
|
12 | use crate::utils::files::{get_bytes_from_path, get_path_from_bytes}; | |
13 | use format_bytes::{format_bytes, write_bytes, DisplayBytes}; |
|
13 | use format_bytes::{format_bytes, write_bytes, DisplayBytes}; | |
14 | use lazy_static::lazy_static; |
|
14 | use lazy_static::lazy_static; | |
@@ -324,9 +324,7 impl DisplayBytes for ConfigOrigin { | |||||
324 | ConfigOrigin::Tweakdefaults => { |
|
324 | ConfigOrigin::Tweakdefaults => { | |
325 | write_bytes!(out, b"ui.tweakdefaults") |
|
325 | write_bytes!(out, b"ui.tweakdefaults") | |
326 | } |
|
326 | } | |
327 |
ConfigOrigin::Defaults => |
|
327 | ConfigOrigin::Defaults => write_bytes!(out, b"configitems.toml"), | |
328 | write_bytes!(out, b"configitems.toml") |
|
|||
329 | } |
|
|||
330 | } |
|
328 | } | |
331 | } |
|
329 | } | |
332 | } |
|
330 | } | |
@@ -338,12 +336,49 pub struct ConfigParseError { | |||||
338 | pub message: Vec<u8>, |
|
336 | pub message: Vec<u8>, | |
339 | } |
|
337 | } | |
340 |
|
338 | |||
|
339 | impl From<ConfigParseError> for HgError { | |||
|
340 | fn from(error: ConfigParseError) -> Self { | |||
|
341 | let ConfigParseError { | |||
|
342 | origin, | |||
|
343 | line, | |||
|
344 | message, | |||
|
345 | } = error; | |||
|
346 | let line_message = if let Some(line_number) = line { | |||
|
347 | format_bytes!(b":{}", line_number.to_string().into_bytes()) | |||
|
348 | } else { | |||
|
349 | Vec::new() | |||
|
350 | }; | |||
|
351 | HgError::Abort { | |||
|
352 | message: String::from_utf8_lossy(&format_bytes!( | |||
|
353 | b"config error at {}{}: {}", | |||
|
354 | origin, | |||
|
355 | line_message, | |||
|
356 | message | |||
|
357 | )) | |||
|
358 | .to_string(), | |||
|
359 | detailed_exit_code: CONFIG_ERROR_ABORT, | |||
|
360 | hint: None, | |||
|
361 | } | |||
|
362 | } | |||
|
363 | } | |||
|
364 | ||||
341 | #[derive(Debug, derive_more::From)] |
|
365 | #[derive(Debug, derive_more::From)] | |
342 | pub enum ConfigError { |
|
366 | pub enum ConfigError { | |
343 | Parse(ConfigParseError), |
|
367 | Parse(ConfigParseError), | |
344 | Other(HgError), |
|
368 | Other(HgError), | |
345 | } |
|
369 | } | |
346 |
|
370 | |||
|
371 | impl From<ConfigError> for HgError { | |||
|
372 | fn from(error: ConfigError) -> Self { | |||
|
373 | match error { | |||
|
374 | ConfigError::Parse(config_parse_error) => { | |||
|
375 | Self::from(config_parse_error) | |||
|
376 | } | |||
|
377 | ConfigError::Other(hg_error) => hg_error, | |||
|
378 | } | |||
|
379 | } | |||
|
380 | } | |||
|
381 | ||||
347 | fn make_regex(pattern: &'static str) -> Regex { |
|
382 | fn make_regex(pattern: &'static str) -> Regex { | |
348 | Regex::new(pattern).expect("expected a valid regex") |
|
383 | Regex::new(pattern).expect("expected a valid regex") | |
349 | } |
|
384 | } |
@@ -20,7 +20,7 use crate::utils::hg_path::HgPath; | |||||
20 | use crate::utils::SliceExt; |
|
20 | use crate::utils::SliceExt; | |
21 | use crate::vfs::{is_dir, is_file, VfsImpl}; |
|
21 | use crate::vfs::{is_dir, is_file, VfsImpl}; | |
22 | use crate::{ |
|
22 | use crate::{ | |
23 | requirements, NodePrefix, RevlogDataConfig, RevlogDeltaConfig, |
|
23 | exit_codes, requirements, NodePrefix, RevlogDataConfig, RevlogDeltaConfig, | |
24 | RevlogFeatureConfig, RevlogType, RevlogVersionOptions, UncheckedRevision, |
|
24 | RevlogFeatureConfig, RevlogType, RevlogVersionOptions, UncheckedRevision, | |
25 | }; |
|
25 | }; | |
26 | use crate::{DirstateError, RevlogOpenOptions}; |
|
26 | use crate::{DirstateError, RevlogOpenOptions}; | |
@@ -68,6 +68,32 impl From<ConfigError> for RepoError { | |||||
68 | } |
|
68 | } | |
69 | } |
|
69 | } | |
70 |
|
70 | |||
|
71 | impl From<RepoError> for HgError { | |||
|
72 | fn from(value: RepoError) -> Self { | |||
|
73 | match value { | |||
|
74 | RepoError::NotFound { at } => HgError::abort( | |||
|
75 | format!( | |||
|
76 | "abort: no repository found in '{}' (.hg not found)!", | |||
|
77 | at.display() | |||
|
78 | ), | |||
|
79 | exit_codes::ABORT, | |||
|
80 | None, | |||
|
81 | ), | |||
|
82 | RepoError::ConfigParseError(config_parse_error) => { | |||
|
83 | HgError::Abort { | |||
|
84 | message: String::from_utf8_lossy( | |||
|
85 | &config_parse_error.message, | |||
|
86 | ) | |||
|
87 | .to_string(), | |||
|
88 | detailed_exit_code: exit_codes::CONFIG_PARSE_ERROR_ABORT, | |||
|
89 | hint: None, | |||
|
90 | } | |||
|
91 | } | |||
|
92 | RepoError::Other(hg_error) => hg_error, | |||
|
93 | } | |||
|
94 | } | |||
|
95 | } | |||
|
96 | ||||
71 | impl Repo { |
|
97 | impl Repo { | |
72 | /// tries to find nearest repository root in current working directory or |
|
98 | /// tries to find nearest repository root in current working directory or | |
73 | /// its ancestors |
|
99 | /// its ancestors |
@@ -1,6 +1,12 | |||||
1 | use cpython::exc::ValueError; |
|
1 | use cpython::exc::ValueError; | |
2 | use cpython::{PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, Python}; |
|
2 | use cpython::{PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, Python}; | |
|
3 | use hg::config::Config; | |||
|
4 | use hg::errors::HgError; | |||
|
5 | use hg::repo::{Repo, RepoError}; | |||
3 | use hg::revlog::Node; |
|
6 | use hg::revlog::Node; | |
|
7 | use hg::utils::files::get_path_from_bytes; | |||
|
8 | ||||
|
9 | use crate::exceptions::FallbackError; | |||
4 |
|
10 | |||
5 | #[allow(unused)] |
|
11 | #[allow(unused)] | |
6 | pub fn print_python_trace(py: Python) -> PyResult<PyObject> { |
|
12 | pub fn print_python_trace(py: Python) -> PyResult<PyObject> { | |
@@ -14,6 +20,47 pub fn print_python_trace(py: Python) -> | |||||
14 | traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) |
|
20 | traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) | |
15 | } |
|
21 | } | |
16 |
|
22 | |||
|
23 | pub fn hgerror_to_pyerr<T>( | |||
|
24 | py: Python, | |||
|
25 | error: Result<T, HgError>, | |||
|
26 | ) -> PyResult<T> { | |||
|
27 | error.map_err(|e| match e { | |||
|
28 | HgError::IoError { .. } => { | |||
|
29 | PyErr::new::<cpython::exc::IOError, _>(py, e.to_string()) | |||
|
30 | } | |||
|
31 | HgError::UnsupportedFeature(e) => { | |||
|
32 | let as_string = e.to_string(); | |||
|
33 | log::trace!("Update from null fallback: {}", as_string); | |||
|
34 | PyErr::new::<FallbackError, _>(py, &as_string) | |||
|
35 | } | |||
|
36 | HgError::RaceDetected(_) => { | |||
|
37 | unreachable!("must not surface to the user") | |||
|
38 | } | |||
|
39 | e => PyErr::new::<cpython::exc::RuntimeError, _>(py, e.to_string()), | |||
|
40 | }) | |||
|
41 | } | |||
|
42 | ||||
|
43 | pub fn repo_error_to_pyerr<T>( | |||
|
44 | py: Python, | |||
|
45 | error: Result<T, RepoError>, | |||
|
46 | ) -> PyResult<T> { | |||
|
47 | hgerror_to_pyerr(py, error.map_err(HgError::from)) | |||
|
48 | } | |||
|
49 | ||||
|
50 | /// Get a repository from a given [`PyObject`] path, and bubble up any error | |||
|
51 | /// that comes up. | |||
|
52 | pub fn repo_from_path(py: Python, repo_path: PyObject) -> Result<Repo, PyErr> { | |||
|
53 | let config = | |||
|
54 | hgerror_to_pyerr(py, Config::load_non_repo().map_err(HgError::from))?; | |||
|
55 | let py_bytes = &repo_path.extract::<PyBytes>(py)?; | |||
|
56 | let repo_path = py_bytes.data(py); | |||
|
57 | let repo = repo_error_to_pyerr( | |||
|
58 | py, | |||
|
59 | Repo::find(&config, Some(get_path_from_bytes(repo_path).to_owned())), | |||
|
60 | )?; | |||
|
61 | Ok(repo) | |||
|
62 | } | |||
|
63 | ||||
17 | // Necessary evil for the time being, could maybe be moved to |
|
64 | // Necessary evil for the time being, could maybe be moved to | |
18 | // a TryFrom in Node itself |
|
65 | // a TryFrom in Node itself | |
19 | const NODE_BYTES_LENGTH: usize = 20; |
|
66 | const NODE_BYTES_LENGTH: usize = 20; |
General Comments 0
You need to be logged in to leave comments.
Login now