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;