rust/hg-cpython/src/revlog.rs
changeset 51205 002b49905aac
parent 51204 297fa956b6c4
child 51206 952e3cd7568f
equal deleted inserted replaced
51204:297fa956b6c4 51205:002b49905aac
    15     exc::{IndexError, ValueError},
    15     exc::{IndexError, ValueError},
    16     ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyInt, PyModule,
    16     ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyInt, PyModule,
    17     PyObject, PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject,
    17     PyObject, PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject,
    18 };
    18 };
    19 use hg::{
    19 use hg::{
    20     index::IndexHeader,
    20     index::{IndexHeader, RevisionDataParams},
    21     index::{RevisionDataParams, COMPRESSION_MODE_INLINE},
       
    22     nodemap::{Block, NodeMapError, NodeTree},
    21     nodemap::{Block, NodeMapError, NodeTree},
    23     revlog::{nodemap::NodeMap, NodePrefix, RevlogIndex},
    22     revlog::{nodemap::NodeMap, NodePrefix, RevlogIndex},
    24     BaseRevision, Revision, UncheckedRevision,
    23     BaseRevision, Revision, UncheckedRevision, NULL_REVISION,
    25 };
    24 };
    26 use std::cell::RefCell;
    25 use std::cell::RefCell;
    27 
    26 
    28 /// Return a Struct implementing the Graph trait
    27 /// Return a Struct implementing the Graph trait
    29 pub(crate) fn pyindex_to_graph(
    28 pub(crate) fn pyindex_to_graph(
   235         let c_res = self.call_cindex(py, "pack_header", args, kw)?;
   234         let c_res = self.call_cindex(py, "pack_header", args, kw)?;
   236         assert_py_eq(py, "pack_header", &rust_res, &c_res)?;
   235         assert_py_eq(py, "pack_header", &rust_res, &c_res)?;
   237         Ok(rust_res)
   236         Ok(rust_res)
   238     }
   237     }
   239 
   238 
   240     /// get an index entry
       
   241     def get(&self, *args, **kw) -> PyResult<PyObject> {
       
   242         self.call_cindex(py, "get", args, kw)
       
   243     }
       
   244 
       
   245     /// compute phases
   239     /// compute phases
   246     def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> {
   240     def computephasesmapsets(&self, *args, **kw) -> PyResult<PyObject> {
   247         self.call_cindex(py, "computephasesmapsets", args, kw)
   241         self.call_cindex(py, "computephasesmapsets", args, kw)
   248     }
   242     }
   249 
   243 
   290     // index_sequence_methods and index_mapping_methods.
   284     // index_sequence_methods and index_mapping_methods.
   291     //
   285     //
   292     // Since we call back through the high level Python API,
   286     // Since we call back through the high level Python API,
   293     // there's no point making a distinction between index_get
   287     // there's no point making a distinction between index_get
   294     // and index_getitem.
   288     // and index_getitem.
       
   289     // gracinet 2023: this above is no longer true for the pure Rust impl
   295 
   290 
   296     def __len__(&self) -> PyResult<usize> {
   291     def __len__(&self) -> PyResult<usize> {
   297         self.len(py)
   292         self.len(py)
   298     }
   293     }
   299 
   294 
   300     def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
   295     def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
       
   296         let rust_res = self.inner_getitem(py, key.clone_ref(py))?;
       
   297 
   301         // this conversion seems needless, but that's actually because
   298         // this conversion seems needless, but that's actually because
   302         // `index_getitem` does not handle conversion from PyLong,
   299         // `index_getitem` does not handle conversion from PyLong,
   303         // which expressions such as [e for e in index] internally use.
   300         // which expressions such as [e for e in index] internally use.
   304         // Note that we don't seem to have a direct way to call
   301         // Note that we don't seem to have a direct way to call
   305         // PySequence_GetItem (does the job), which would possibly be better
   302         // PySequence_GetItem (does the job), which would possibly be better
   306         // for performance
   303         // for performance
   307         let key = match key.extract::<i32>(py) {
   304         // gracinet 2023: the above comment can be removed when we use
       
   305         // the pure Rust impl only. Note also that `key` can be a binary
       
   306         // node id.
       
   307         let c_key = match key.extract::<BaseRevision>(py) {
   308             Ok(rev) => rev.to_py_object(py).into_object(),
   308             Ok(rev) => rev.to_py_object(py).into_object(),
   309             Err(_) => key,
   309             Err(_) => key,
   310         };
   310         };
   311         self.cindex(py).borrow().inner().get_item(py, key)
   311         let c_res = self.cindex(py).borrow().inner().get_item(py, c_key)?;
       
   312 
       
   313         assert_py_eq(py, "__getitem__", &rust_res, &c_res)?;
       
   314         Ok(rust_res)
   312     }
   315     }
   313 
   316 
   314     def __contains__(&self, item: PyObject) -> PyResult<bool> {
   317     def __contains__(&self, item: PyObject) -> PyResult<bool> {
   315         // ObjectProtocol does not seem to provide contains(), so
   318         // ObjectProtocol does not seem to provide contains(), so
   316         // this is an equivalent implementation of the index_contains()
   319         // this is an equivalent implementation of the index_contains()
   424         data_delta_base: tuple.get_item(py, 3).extract(py)?,
   427         data_delta_base: tuple.get_item(py, 3).extract(py)?,
   425         link_rev: tuple.get_item(py, 4).extract(py)?,
   428         link_rev: tuple.get_item(py, 4).extract(py)?,
   426         parent_rev_1: tuple.get_item(py, 5).extract(py)?,
   429         parent_rev_1: tuple.get_item(py, 5).extract(py)?,
   427         parent_rev_2: tuple.get_item(py, 6).extract(py)?,
   430         parent_rev_2: tuple.get_item(py, 6).extract(py)?,
   428         node_id,
   431         node_id,
   429         _sidedata_offset: 0,
   432         ..Default::default()
   430         _sidedata_compressed_length: 0,
       
   431         data_compression_mode: COMPRESSION_MODE_INLINE,
       
   432         _sidedata_compression_mode: COMPRESSION_MODE_INLINE,
       
   433         _rank: -1,
       
   434     })
   433     })
       
   434 }
       
   435 fn revision_data_params_to_py_tuple(
       
   436     py: Python,
       
   437     params: RevisionDataParams,
       
   438 ) -> PyTuple {
       
   439     PyTuple::new(
       
   440         py,
       
   441         &[
       
   442             params.data_offset.into_py_object(py).into_object(),
       
   443             params
       
   444                 .data_compressed_length
       
   445                 .into_py_object(py)
       
   446                 .into_object(),
       
   447             params
       
   448                 .data_uncompressed_length
       
   449                 .into_py_object(py)
       
   450                 .into_object(),
       
   451             params.data_delta_base.into_py_object(py).into_object(),
       
   452             params.link_rev.into_py_object(py).into_object(),
       
   453             params.parent_rev_1.into_py_object(py).into_object(),
       
   454             params.parent_rev_2.into_py_object(py).into_object(),
       
   455             PyBytes::new(py, &params.node_id)
       
   456                 .into_py_object(py)
       
   457                 .into_object(),
       
   458             params._sidedata_offset.into_py_object(py).into_object(),
       
   459             params
       
   460                 ._sidedata_compressed_length
       
   461                 .into_py_object(py)
       
   462                 .into_object(),
       
   463             params
       
   464                 .data_compression_mode
       
   465                 .into_py_object(py)
       
   466                 .into_object(),
       
   467             params
       
   468                 ._sidedata_compression_mode
       
   469                 .into_py_object(py)
       
   470                 .into_object(),
       
   471             params._rank.into_py_object(py).into_object(),
       
   472         ],
       
   473     )
   435 }
   474 }
   436 
   475 
   437 impl MixedIndex {
   476 impl MixedIndex {
   438     fn new(
   477     fn new(
   439         py: Python,
   478         py: Python,
   598         }
   637         }
   599 
   638 
   600         *self.nt(py).borrow_mut() = Some(nt);
   639         *self.nt(py).borrow_mut() = Some(nt);
   601 
   640 
   602         Ok(py.None())
   641         Ok(py.None())
       
   642     }
       
   643 
       
   644     fn inner_getitem(&self, py: Python, key: PyObject) -> PyResult<PyObject> {
       
   645         let idx = self.index(py).borrow();
       
   646         Ok(match key.extract::<BaseRevision>(py) {
       
   647             Ok(key_as_int) => {
       
   648                 let entry_params = if key_as_int == NULL_REVISION.0 {
       
   649                     RevisionDataParams::default()
       
   650                 } else {
       
   651                     let rev = UncheckedRevision(key_as_int);
       
   652                     match idx.entry_as_params(rev) {
       
   653                         Some(e) => e,
       
   654                         None => {
       
   655                             return Err(PyErr::new::<IndexError, _>(
       
   656                                 py,
       
   657                                 "revlog index out of range",
       
   658                             ));
       
   659                         }
       
   660                     }
       
   661                 };
       
   662                 revision_data_params_to_py_tuple(py, entry_params)
       
   663                     .into_object()
       
   664             }
       
   665             _ => self.get_rev(py, key.extract::<PyBytes>(py)?)?.map_or_else(
       
   666                 || py.None(),
       
   667                 |py_rev| py_rev.into_py_object(py).into_object(),
       
   668             ),
       
   669         })
   603     }
   670     }
   604 }
   671 }
   605 
   672 
   606 fn revlog_error(py: Python) -> PyErr {
   673 fn revlog_error(py: Python) -> PyErr {
   607     match py
   674     match py