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> { |
7 eprintln!("==============================="); |
13 eprintln!("==============================="); |
8 eprintln!("Printing Python stack from Rust"); |
14 eprintln!("Printing Python stack from Rust"); |
10 let traceback = py.import("traceback")?; |
16 let traceback = py.import("traceback")?; |
11 let sys = py.import("sys")?; |
17 let sys = py.import("sys")?; |
12 let kwargs = PyDict::new(py); |
18 let kwargs = PyDict::new(py); |
13 kwargs.set_item(py, "file", sys.get(py, "stderr")?)?; |
19 kwargs.set_item(py, "file", sys.get(py, "stderr")?)?; |
14 traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) |
20 traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) |
|
21 } |
|
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) |
15 } |
62 } |
16 |
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; |