##// END OF EJS Templates
rust-cpython: add a util to get a `Repo` from a python path...
Raphaël Gomès -
r52939:28a0eb21 default
parent child Browse files
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