diff -r 652149ed64f0 -r 28a0eb21ff04 rust/hg-cpython/src/utils.rs --- a/rust/hg-cpython/src/utils.rs Tue Oct 01 13:20:40 2024 +0200 +++ b/rust/hg-cpython/src/utils.rs Tue Oct 01 13:45:18 2024 +0200 @@ -1,6 +1,12 @@ use cpython::exc::ValueError; use cpython::{PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, Python}; +use hg::config::Config; +use hg::errors::HgError; +use hg::repo::{Repo, RepoError}; use hg::revlog::Node; +use hg::utils::files::get_path_from_bytes; + +use crate::exceptions::FallbackError; #[allow(unused)] pub fn print_python_trace(py: Python) -> PyResult { @@ -14,6 +20,47 @@ traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) } +pub fn hgerror_to_pyerr( + py: Python, + error: Result, +) -> PyResult { + error.map_err(|e| match e { + HgError::IoError { .. } => { + PyErr::new::(py, e.to_string()) + } + HgError::UnsupportedFeature(e) => { + let as_string = e.to_string(); + log::trace!("Update from null fallback: {}", as_string); + PyErr::new::(py, &as_string) + } + HgError::RaceDetected(_) => { + unreachable!("must not surface to the user") + } + e => PyErr::new::(py, e.to_string()), + }) +} + +pub fn repo_error_to_pyerr( + py: Python, + error: Result, +) -> PyResult { + hgerror_to_pyerr(py, error.map_err(HgError::from)) +} + +/// Get a repository from a given [`PyObject`] path, and bubble up any error +/// that comes up. +pub fn repo_from_path(py: Python, repo_path: PyObject) -> Result { + let config = + hgerror_to_pyerr(py, Config::load_non_repo().map_err(HgError::from))?; + let py_bytes = &repo_path.extract::(py)?; + let repo_path = py_bytes.data(py); + let repo = repo_error_to_pyerr( + py, + Repo::find(&config, Some(get_path_from_bytes(repo_path).to_owned())), + )?; + Ok(repo) +} + // Necessary evil for the time being, could maybe be moved to // a TryFrom in Node itself const NODE_BYTES_LENGTH: usize = 20;