Mercurial > public > mercurial-scm > hg-stable
comparison rust/hg-cpython/src/utils.rs @ 52070:28a0eb21ff04
rust-cpython: add a util to get a `Repo` from a python path
I suspect this will not be the last time we need to do something like this.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 01 Oct 2024 13:45:18 +0200 |
parents | c7fb9b74e753 |
children | de317a87ea6a |
comparison
equal
deleted
inserted
replaced
52069:652149ed64f0 | 52070:28a0eb21ff04 |
---|---|
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; |