# HG changeset patch # User Raphaël Gomès # Date 1727893788 -7200 # Node ID de317a87ea6a6765408786e45e0900986875a5a6 # Parent a8cf6a852f1124f4bb96484449edd3843dce84ed rust-pathauditor: match more of Python's behavior and display messages We will make use of the path auditor when running our update fast-path, and we want to output of it to be close enough. diff -r a8cf6a852f11 -r de317a87ea6a rust/hg-core/src/errors.rs --- a/rust/hg-core/src/errors.rs Wed Oct 02 18:31:32 2024 +0200 +++ b/rust/hg-core/src/errors.rs Wed Oct 02 20:29:48 2024 +0200 @@ -1,5 +1,6 @@ use crate::config::ConfigValueParseError; use crate::exit_codes; +use crate::utils::hg_path::HgPathError; use std::fmt; /// Common error cases that can happen in many different APIs @@ -49,6 +50,8 @@ /// A race condition has been detected. This *must* be handled locally /// and not directly surface to the user. RaceDetected(String), + /// An invalid path was found + Path(HgPathError), } /// Details about where an I/O error happened @@ -117,6 +120,7 @@ HgError::RaceDetected(context) => { write!(f, "encountered a race condition {context}") } + HgError::Path(hg_path_error) => write!(f, "{}", hg_path_error), } } } diff -r a8cf6a852f11 -r de317a87ea6a rust/hg-core/src/utils/hg_path.rs --- a/rust/hg-core/src/utils/hg_path.rs Wed Oct 02 18:31:32 2024 +0200 +++ b/rust/hg-core/src/utils/hg_path.rs Wed Oct 02 20:29:48 2024 +0200 @@ -5,6 +5,7 @@ // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. +use crate::errors::HgError; use crate::utils::SliceExt; use std::borrow::Borrow; use std::borrow::Cow; @@ -48,6 +49,12 @@ }, } +impl From for HgError { + fn from(value: HgPathError) -> Self { + HgError::Path(value) + } +} + impl fmt::Display for HgPathError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -76,41 +83,34 @@ bytes ), HgPathError::EndsWithSlash(path) => { - write!(f, "Audit failed for '{}': ends with a slash.", path) + write!(f, "path '{}': ends with a slash", path) } - HgPathError::ContainsIllegalComponent(path) => write!( - f, - "Audit failed for '{}': contains an illegal component.", - path - ), - HgPathError::InsideDotHg(path) => write!( - f, - "Audit failed for '{}': is inside the '.hg' folder.", - path - ), + HgPathError::ContainsIllegalComponent(path) => { + write!(f, "path contains illegal component: {}", path) + } + HgPathError::InsideDotHg(path) => { + write!(f, "path '{}' is inside the '.hg' folder", path) + } HgPathError::IsInsideNestedRepo { path, nested_repo: nested, } => { - write!(f, - "Audit failed for '{}': is inside a nested repository '{}'.", - path, nested - ) + write!(f, "path '{}' is inside nested repo '{}'", path, nested) } HgPathError::TraversesSymbolicLink { path, symlink } => write!( f, - "Audit failed for '{}': traverses symbolic link '{}'.", + "path '{}' traverses symbolic link '{}'", path, symlink ), HgPathError::NotFsCompliant(path) => write!( f, - "Audit failed for '{}': cannot be turned into a \ - filesystem path.", + "path '{}' cannot be turned into a \ + filesystem path", path ), HgPathError::NotUnderRoot { path, root } => write!( f, - "Audit failed for '{}': not under root {}.", + "path '{}' not under root {}", path.display(), root.display() ), diff -r a8cf6a852f11 -r de317a87ea6a rust/hg-cpython/src/utils.rs --- a/rust/hg-cpython/src/utils.rs Wed Oct 02 18:31:32 2024 +0200 +++ b/rust/hg-cpython/src/utils.rs Wed Oct 02 20:29:48 2024 +0200 @@ -1,5 +1,8 @@ use cpython::exc::ValueError; -use cpython::{PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, Python}; +use cpython::{ + ObjectProtocol, PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, + Python, ToPyObject, +}; use hg::config::Config; use hg::errors::HgError; use hg::repo::{Repo, RepoError}; @@ -36,6 +39,17 @@ HgError::RaceDetected(_) => { unreachable!("must not surface to the user") } + HgError::Path(path_error) => { + let msg = PyBytes::new(py, path_error.to_string().as_bytes()); + let cls = py + .import("mercurial.error") + .and_then(|m| m.get(py, "InputError")) + .unwrap(); + PyErr::from_instance( + py, + cls.call(py, (msg,), None).ok().into_py_object(py), + ) + } e => PyErr::new::(py, e.to_string()), }) }