Mercurial > public > mercurial-scm > hg
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 |
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 } |