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.
--- 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),
}
}
}
--- 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<HgPathError> 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()
),
--- 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::<cpython::exc::RuntimeError, _>(py, e.to_string()),
})
}