rust/hg-pyo3/src/revlog/mod.rs
changeset 52789 34f44aa5e844
parent 52788 e29e75e8328c
child 52791 0ac956db7ea7
equal deleted inserted replaced
52788:e29e75e8328c 52789:34f44aa5e844
     7 // This software may be used and distributed according to the terms of the
     7 // This software may be used and distributed according to the terms of the
     8 // GNU General Public License version 2 or any later version.
     8 // GNU General Public License version 2 or any later version.
     9 #![allow(non_snake_case)]
     9 #![allow(non_snake_case)]
    10 use pyo3::buffer::PyBuffer;
    10 use pyo3::buffer::PyBuffer;
    11 use pyo3::prelude::*;
    11 use pyo3::prelude::*;
    12 use pyo3::types::{PyBytes, PyBytesMethods, PyList};
    12 use pyo3::types::{PyBytes, PyBytesMethods, PyList, PyTuple};
    13 use pyo3_sharedref::PyShareable;
    13 use pyo3_sharedref::PyShareable;
    14 
    14 
    15 use std::sync::{
    15 use std::sync::{
    16     atomic::{AtomicUsize, Ordering},
    16     atomic::{AtomicUsize, Ordering},
    17     RwLock, RwLockReadGuard, RwLockWriteGuard,
    17     RwLock, RwLockReadGuard, RwLockWriteGuard,
    19 
    19 
    20 use hg::{
    20 use hg::{
    21     revlog::{
    21     revlog::{
    22         index::Index,
    22         index::Index,
    23         inner_revlog::InnerRevlog as CoreInnerRevlog,
    23         inner_revlog::InnerRevlog as CoreInnerRevlog,
    24         nodemap::{NodeMap, NodeTree as CoreNodeTree},
    24         nodemap::{NodeMap, NodeMapError, NodeTree as CoreNodeTree},
    25         options::RevlogOpenOptions,
    25         options::RevlogOpenOptions,
    26         RevlogIndex, RevlogType,
    26         RevlogIndex, RevlogType,
    27     },
    27     },
    28     utils::files::get_path_from_bytes,
    28     utils::files::get_path_from_bytes,
    29     vfs::FnCacheVfs,
    29     vfs::FnCacheVfs,
    30     BaseRevision, Revision,
    30     BaseRevision, Revision, UncheckedRevision,
    31 };
    31 };
    32 
    32 
    33 use crate::{
    33 use crate::{
    34     exceptions::{
    34     exceptions::{
    35         map_lock_error, map_try_lock_error, nodemap_error, revlog_error_bare,
    35         map_lock_error, map_try_lock_error, nodemap_error, revlog_error_bare,
    41     util::{new_submodule, take_buffer_with_slice},
    41     util::{new_submodule, take_buffer_with_slice},
    42 };
    42 };
    43 
    43 
    44 mod config;
    44 mod config;
    45 use config::*;
    45 use config::*;
       
    46 mod index;
       
    47 use index::py_tuple_to_revision_data_params;
    46 
    48 
    47 #[pyclass]
    49 #[pyclass]
    48 #[allow(dead_code)]
    50 #[allow(dead_code)]
    49 struct InnerRevlog {
    51 struct InnerRevlog {
    50     irl: PyShareable<CoreInnerRevlog>,
    52     irl: PyShareable<CoreInnerRevlog>,
   223                 .map_err(nodemap_error)?
   225                 .map_err(nodemap_error)?
   224                 .map(|rev| py_node_for_rev(slf.py(), idx, rev)))
   226                 .map(|rev| py_node_for_rev(slf.py(), idx, rev)))
   225         })
   227         })
   226     }
   228     }
   227 
   229 
       
   230     /// append an index entry
       
   231     fn _index_append(
       
   232         slf: &Bound<'_, Self>,
       
   233         tup: &Bound<'_, PyTuple>,
       
   234     ) -> PyResult<()> {
       
   235         // no need to check length: in PyO3 tup.get_item() does return
       
   236         // proper errors
       
   237         let node_bytes = tup.get_item(7)?.extract()?;
       
   238         let node = node_from_py_bytes(&node_bytes)?;
       
   239 
       
   240         Self::with_index_nt_write(slf, |idx, nt| {
       
   241             let rev = idx.len() as BaseRevision;
       
   242             // This is ok since we will immediately add the revision to the
       
   243             // index
       
   244             let rev = Revision(rev);
       
   245             idx.append(py_tuple_to_revision_data_params(tup)?)
       
   246                 .map_err(revlog_error_from_msg)?;
       
   247 
       
   248             nt.insert(idx, &node, rev).map_err(nodemap_error)?;
       
   249             Ok(())
       
   250         })
       
   251     }
       
   252 
       
   253     /// Removes one or several entries from the index.
       
   254     ///
       
   255     /// Historically, on the Mercurial revlog index, `__delitem__` has always
       
   256     /// been both for `del idx[r1]` and `del idx[r1:r2]`. In both cases,
       
   257     /// all entries starting from `r1` are removed anyway.
       
   258     fn _index___delitem__(
       
   259         slf: &Bound<'_, Self>,
       
   260         arg: &Bound<'_, PyAny>,
       
   261     ) -> PyResult<()> {
       
   262         let start = if let Ok(rev) = arg.extract() {
       
   263             UncheckedRevision(rev)
       
   264         } else {
       
   265             // here we could downcast to `PySlice` and use `indices()`, *but*
       
   266             // the rust-cpython based version could not do that, and
       
   267             // `indices()` does some resolving that makes it not equivalent,
       
   268             // e.g., `idx[-1::]` has `start=0`. As we are currently in
       
   269             // transition, we keep it the old way (hoping it was consistent
       
   270             // with the C index).
       
   271             let start = arg.getattr("start")?;
       
   272             UncheckedRevision(start.extract()?)
       
   273         };
       
   274 
       
   275         Self::with_index_nt_write(slf, |idx, nt| {
       
   276             // In the case of a slice, the check is possibly already done by
       
   277             // `slice.indices`, which is itself an FFI wrapper for CPython's
       
   278             // `PySlice_GetIndicesEx`
       
   279             // (Python integration tests will tell us)
       
   280             let start = idx.check_revision(start).ok_or_else(|| {
       
   281                 nodemap_error(NodeMapError::RevisionNotInIndex(start))
       
   282             })?;
       
   283             idx.remove(start).map_err(revlog_error_from_msg)?;
       
   284             nt.invalidate_all();
       
   285             Self::fill_nodemap(idx, nt)?;
       
   286             Ok(())
       
   287         })
       
   288     }
       
   289 
   228     fn _index___len__(slf: &Bound<'_, Self>) -> PyResult<usize> {
   290     fn _index___len__(slf: &Bound<'_, Self>) -> PyResult<usize> {
   229         Self::with_index_read(slf, |idx| Ok(idx.len()))
   291         Self::with_index_read(slf, |idx| Ok(idx.len()))
   230     }
   292     }
   231 }
   293 }
   232 
   294 
   256         let shareable_ref = unsafe { self_ref.irl.borrow_with_owner(slf) };
   318         let shareable_ref = unsafe { self_ref.irl.borrow_with_owner(slf) };
   257         let guard = shareable_ref.try_read().map_err(map_try_lock_error)?;
   319         let guard = shareable_ref.try_read().map_err(map_try_lock_error)?;
   258         f(&self_ref, guard)
   320         f(&self_ref, guard)
   259     }
   321     }
   260 
   322 
   261     #[allow(dead_code)]
       
   262     /// Take the lock on `slf.irl` for writing and call a closure.
   323     /// Take the lock on `slf.irl` for writing and call a closure.
   263     ///
   324     ///
   264     /// See [`Self::with_core_read`] for more explanations.
   325     /// See [`Self::with_core_read`] for more explanations.
   265     fn with_core_write<'py, T>(
   326     fn with_core_write<'py, T>(
   266         slf: &Bound<'py, Self>,
   327         slf: &Bound<'py, Self>,
   308             let nt = nt.as_ref().expect("nodetree should be set");
   369             let nt = nt.as_ref().expect("nodetree should be set");
   309             f(idx, nt)
   370             f(idx, nt)
   310         })
   371         })
   311     }
   372     }
   312 
   373 
   313     #[allow(dead_code)]
       
   314     fn with_index_nt_write<T>(
   374     fn with_index_nt_write<T>(
   315         slf: &Bound<'_, Self>,
   375         slf: &Bound<'_, Self>,
   316         f: impl FnOnce(&mut Index, &mut CoreNodeTree) -> PyResult<T>,
   376         f: impl FnOnce(&mut Index, &mut CoreNodeTree) -> PyResult<T>,
   317     ) -> PyResult<T> {
   377     ) -> PyResult<T> {
   318         Self::with_core_write(slf, |self_ref, mut guard| {
   378         Self::with_core_write(slf, |self_ref, mut guard| {