annotate rust/hg-cpython/src/cindex.rs @ 41228:3b35ebdb9f8c

narrow: include working copy narrowspec in transaction journal Now that we have separate narrowspecs for the store and the working copy, we need to include both in the transaction journal. Differential Revision: https://phab.mercurial-scm.org/D5505
author Martin von Zweigbergk <martinvonz@google.com>
date Sat, 29 Dec 2018 22:34:38 -0800
parents ef54bd33b476
children ab0d762d89ef
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
41052
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
1 // cindex.rs
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
2 //
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
3 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
4 //
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
7
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
8 //! Bindings to use the Index defined by the parsers C extension
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
9 //!
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
10 //! Ideally, we should use an Index entirely implemented in Rust,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
11 //! but this will take some time to get there.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
12 #[cfg(feature = "python27")]
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
13 extern crate python27_sys as python_sys;
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
14 #[cfg(feature = "python3")]
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
15 extern crate python3_sys as python_sys;
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
16
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
17 use self::python_sys::PyCapsule_Import;
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
18 use cpython::{PyClone, PyErr, PyObject, PyResult, Python};
41052
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
19 use hg::{Graph, GraphError, Revision};
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
20 use libc::c_int;
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
21 use std::ffi::CStr;
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
22 use std::mem::transmute;
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
23
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
24 type IndexParentsFn = unsafe extern "C" fn(
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
25 index: *mut python_sys::PyObject,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
26 rev: c_int,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
27 ps: *mut [c_int; 2],
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
28 ) -> c_int;
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
29
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
30 /// A `Graph` backed up by objects and functions from revlog.c
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
31 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
32 /// This implementation of the `Graph` trait, relies on (pointers to)
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
33 /// - the C index object (`index` member)
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
34 /// - the `index_get_parents()` function (`parents` member)
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
35 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
36 /// # Safety
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
37 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
38 /// The C index itself is mutable, and this Rust exposition is **not
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
39 /// protected by the GIL**, meaning that this construct isn't safe with respect
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
40 /// to Python threads.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
41 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
42 /// All callers of this `Index` must acquire the GIL and must not release it
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
43 /// while working.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
44 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
45 /// # TODO find a solution to make it GIL safe again.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
46 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
47 /// This is non trivial, and can wait until we have a clearer picture with
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
48 /// more Rust Mercurial constructs.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
49 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
50 /// One possibility would be to a `GILProtectedIndex` wrapper enclosing
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
51 /// a `Python<'p>` marker and have it be the one implementing the
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
52 /// `Graph` trait, but this would mean the `Graph` implementor would become
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
53 /// likely to change between subsequent method invocations of the `hg-core`
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
54 /// objects (a serious change of the `hg-core` API):
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
55 /// either exposing ways to mutate the `Graph`, or making it a non persistent
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
56 /// parameter in the relevant methods that need one.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
57 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
58 /// Another possibility would be to introduce an abstract lock handle into
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
59 /// the core API, that would be tied to `GILGuard` / `Python<'p>`
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
60 /// in the case of the `cpython` crate bindings yet could leave room for other
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
61 /// mechanisms in other contexts.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
62 pub struct Index {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
63 index: PyObject,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
64 parents: IndexParentsFn,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
65 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
66
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
67 impl Index {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
68 pub fn new(py: Python, index: PyObject) -> PyResult<Self> {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
69 Ok(Index {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
70 index: index,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
71 parents: decapsule_parents_fn(py)?,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
72 })
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
73 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
74 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
75
41054
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
76 impl Clone for Index {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
77 fn clone(&self) -> Self {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
78 let guard = Python::acquire_gil();
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
79 Index {
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
80 index: self.index.clone_ref(guard.python()),
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
81 parents: self.parents.clone(),
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
82 }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
83 }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
84 }
ef54bd33b476 rust: core implementation for lazyancestors
Georges Racinet <gracinet@anybox.fr>
parents: 41052
diff changeset
85
41052
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
86 impl Graph for Index {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
87 /// wrap a call to the C extern parents function
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
88 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
89 let mut res: [c_int; 2] = [0; 2];
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
90 let code = unsafe {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
91 (self.parents)(
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
92 self.index.as_ptr(),
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
93 rev as c_int,
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
94 &mut res as *mut [c_int; 2],
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
95 )
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
96 };
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
97 match code {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
98 0 => Ok(res),
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
99 _ => Err(GraphError::ParentOutOfRange(rev)),
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
100 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
101 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
102 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
103
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
104 /// Return the `index_get_parents` function of the parsers C Extension module.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
105 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
106 /// A pointer to the function is stored in the `parsers` module as a
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
107 /// standard [Python capsule](https://docs.python.org/2/c-api/capsule.html).
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
108 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
109 /// This function retrieves the capsule and casts the function pointer
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
110 ///
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
111 /// Casting function pointers is one of the rare cases of
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
112 /// legitimate use cases of `mem::transmute()` (see
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
113 /// https://doc.rust-lang.org/std/mem/fn.transmute.html of
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
114 /// `mem::transmute()`.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
115 /// It is inappropriate for architectures where
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
116 /// function and data pointer sizes differ (so-called "Harvard
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
117 /// architectures"), but these are nowadays mostly DSPs
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
118 /// and microcontrollers, hence out of our scope.
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
119 fn decapsule_parents_fn(py: Python) -> PyResult<IndexParentsFn> {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
120 unsafe {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
121 let caps_name = CStr::from_bytes_with_nul_unchecked(
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
122 b"mercurial.cext.parsers.index_get_parents_CAPI\0",
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
123 );
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
124 let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
125 if from_caps.is_null() {
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
126 return Err(PyErr::fetch(py));
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
127 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
128 Ok(transmute(from_caps))
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
129 }
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
130 }