Mercurial > public > mercurial-scm > hg
changeset 52868:8e94b32de84b
rust-pyo3-dirstate: Dirs methods not involving iterators
We hesitated on this one: was it worth it to introduce the `with_inner_*`
helpers? Finally quickness and uniformity decided we should.
At this point it would be interesting to do something in `pyo3-sharedref`
to provide them automatically, but some callers will need the self reference
(as in `revlog`), some would not.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Wed, 05 Feb 2025 11:11:05 +0100 |
parents | aa2cfeed65c9 |
children | 8c11ec902e73 |
files | rust/hg-pyo3/src/dirstate/dirs_multiset.rs rust/hg-pyo3/src/dirstate/dirstate_map.rs |
diffstat | 2 files changed, 69 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-pyo3/src/dirstate/dirs_multiset.rs Tue Feb 04 19:37:22 2025 +0100 +++ b/rust/hg-pyo3/src/dirstate/dirs_multiset.rs Wed Feb 05 11:11:05 2025 +0100 @@ -9,15 +9,19 @@ //! `hg-core` package. use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; -use pyo3::types::PyDict; +use pyo3::types::{PyBytes, PyDict}; use pyo3_sharedref::PyShareable; -use hg::{dirstate::dirs_multiset::DirsMultiset, utils::hg_path::HgPathBuf}; +use std::sync::{RwLockReadGuard, RwLockWriteGuard}; -use crate::exceptions::to_string_value_error; +use hg::{ + dirstate::dirs_multiset::DirsMultiset, + utils::hg_path::{HgPath, HgPathBuf}, +}; + +use crate::exceptions::{map_try_lock_error, to_string_value_error}; #[pyclass(mapping)] -#[allow(dead_code)] pub struct Dirs { pub(super) inner: PyShareable<DirsMultiset>, } @@ -43,4 +47,63 @@ .into(), }) } + + fn addpath( + slf: &Bound<'_, Self>, + path: &Bound<'_, PyBytes>, + ) -> PyResult<()> { + let path = HgPath::new(path.as_bytes()); + Self::with_inner_write(slf, |mut inner| { + inner.add_path(path).map_err(to_string_value_error) + }) + } + + fn delpath( + slf: &Bound<'_, Self>, + path: &Bound<'_, PyBytes>, + ) -> PyResult<()> { + let path = HgPath::new(path.as_bytes()); + Self::with_inner_write(slf, |mut inner| { + inner.delete_path(path).map_err(to_string_value_error) + }) + } + + fn __contains__( + slf: &Bound<'_, Self>, + key: &Bound<'_, PyAny>, + ) -> PyResult<bool> { + let path = if let Ok(k) = key.extract::<&[u8]>() { + HgPath::new(k) + } else { + return Ok(false); + }; + + Self::with_inner_read(slf, |inner| Ok(inner.contains(path))) + } } + +impl Dirs { + pub(super) fn with_inner_read<T>( + slf: &Bound<'_, Self>, + f: impl FnOnce(RwLockReadGuard<DirsMultiset>) -> PyResult<T>, + ) -> PyResult<T> { + let self_ref = slf.borrow(); + // Safety: the owner is the right one. We will anyway + // not actually `share` it. + let shareable_ref = unsafe { self_ref.inner.borrow_with_owner(slf) }; + let guard = shareable_ref.try_read().map_err(map_try_lock_error)?; + f(guard) + } + + pub(super) fn with_inner_write<T>( + slf: &Bound<'_, Self>, + f: impl FnOnce(RwLockWriteGuard<DirsMultiset>) -> PyResult<T>, + ) -> PyResult<T> { + let self_ref = slf.borrow(); + // Safety: the owner is the right one. We will anyway + // not actually `share` it. + let shareable_ref = unsafe { self_ref.inner.borrow_with_owner(slf) }; + let guard = shareable_ref.try_write().map_err(map_try_lock_error)?; + f(guard) + } +}
--- a/rust/hg-pyo3/src/dirstate/dirstate_map.rs Tue Feb 04 19:37:22 2025 +0100 +++ b/rust/hg-pyo3/src/dirstate/dirstate_map.rs Wed Feb 05 11:11:05 2025 +0100 @@ -346,6 +346,8 @@ fn __contains__( slf: &Bound<'_, Self>, + // TODO we should accept PyAny and return false if wrong type + // review similar "protocol" methods (see example in dirs_multiset) key: &Bound<'_, PyBytes>, ) -> PyResult<bool> { Self::with_inner_read(slf, |_self_ref, inner| {