##// END OF EJS Templates
rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara -
r43482:88a9930e default
parent child Browse files
Show More
@@ -1,132 +1,132
1 1 // dirstate.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for the `hg::dirstate` module provided by the
9 9 //! `hg-core` package.
10 10 //!
11 11 //! From Python, this will be seen as `mercurial.rustext.dirstate`
12 12 mod copymap;
13 13 mod dirs_multiset;
14 14 mod dirstate_map;
15 15 use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap};
16 16 use cpython::{
17 17 exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence,
18 18 Python,
19 19 };
20 20 use hg::{
21 21 utils::hg_path::HgPathBuf, DirstateEntry, DirstateParseError, EntryState,
22 22 StateMap,
23 23 };
24 24 use libc::{c_char, c_int};
25 25 #[cfg(feature = "python27")]
26 26 use python27_sys as python_sys;
27 27 #[cfg(feature = "python3")]
28 28 use python3_sys as python_sys;
29 29 use python_sys::PyCapsule_Import;
30 30 use std::convert::TryFrom;
31 31 use std::ffi::CStr;
32 32 use std::mem::transmute;
33 33
34 /// C code uses a custom `dirstate_tuple` type, checks in multiple instances
35 /// for this type, and raises a Python `Exception` if the check does not pass.
36 /// Because this type differs only in name from the regular Python tuple, it
37 /// would be a good idea in the near future to remove it entirely to allow
38 /// for a pure Python tuple of the same effective structure to be used,
39 /// rendering this type and the capsule below useless.
34 // C code uses a custom `dirstate_tuple` type, checks in multiple instances
35 // for this type, and raises a Python `Exception` if the check does not pass.
36 // Because this type differs only in name from the regular Python tuple, it
37 // would be a good idea in the near future to remove it entirely to allow
38 // for a pure Python tuple of the same effective structure to be used,
39 // rendering this type and the capsule below useless.
40 40 type MakeDirstateTupleFn = unsafe extern "C" fn(
41 41 state: c_char,
42 42 mode: c_int,
43 43 size: c_int,
44 44 mtime: c_int,
45 45 ) -> *mut python_sys::PyObject;
46 46
47 /// This is largely a copy/paste from cindex.rs, pending the merge of a
48 /// `py_capsule_fn!` macro in the rust-cpython project:
49 /// https://github.com/dgrunwald/rust-cpython/pull/169
47 // This is largely a copy/paste from cindex.rs, pending the merge of a
48 // `py_capsule_fn!` macro in the rust-cpython project:
49 // https://github.com/dgrunwald/rust-cpython/pull/169
50 50 fn decapsule_make_dirstate_tuple(py: Python) -> PyResult<MakeDirstateTupleFn> {
51 51 unsafe {
52 52 let caps_name = CStr::from_bytes_with_nul_unchecked(
53 53 b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0",
54 54 );
55 55 let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
56 56 if from_caps.is_null() {
57 57 return Err(PyErr::fetch(py));
58 58 }
59 59 Ok(transmute(from_caps))
60 60 }
61 61 }
62 62
63 63 pub fn make_dirstate_tuple(
64 64 py: Python,
65 65 entry: &DirstateEntry,
66 66 ) -> PyResult<PyObject> {
67 67 let make = decapsule_make_dirstate_tuple(py)?;
68 68
69 69 let &DirstateEntry {
70 70 state,
71 71 mode,
72 72 size,
73 73 mtime,
74 74 } = entry;
75 75 // Explicitly go through u8 first, then cast to platform-specific `c_char`
76 76 // because Into<u8> has a specific implementation while `as c_char` would
77 77 // just do a naive enum cast.
78 78 let state_code: u8 = state.into();
79 79
80 80 let maybe_obj = unsafe {
81 81 let ptr = make(state_code as c_char, mode, size, mtime);
82 82 PyObject::from_owned_ptr_opt(py, ptr)
83 83 };
84 84 maybe_obj.ok_or_else(|| PyErr::fetch(py))
85 85 }
86 86
87 87 pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
88 88 dmap.items(py)
89 89 .iter()
90 90 .map(|(filename, stats)| {
91 91 let stats = stats.extract::<PySequence>(py)?;
92 92 let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
93 93 let state = EntryState::try_from(state.data(py)[0]).map_err(
94 94 |e: DirstateParseError| {
95 95 PyErr::new::<exc::ValueError, _>(py, e.to_string())
96 96 },
97 97 )?;
98 98 let mode = stats.get_item(py, 1)?.extract(py)?;
99 99 let size = stats.get_item(py, 2)?.extract(py)?;
100 100 let mtime = stats.get_item(py, 3)?.extract(py)?;
101 101 let filename = filename.extract::<PyBytes>(py)?;
102 102 let filename = filename.data(py);
103 103 Ok((
104 104 HgPathBuf::from(filename.to_owned()),
105 105 DirstateEntry {
106 106 state,
107 107 mode,
108 108 size,
109 109 mtime,
110 110 },
111 111 ))
112 112 })
113 113 .collect()
114 114 }
115 115
116 116 /// Create the module, with `__package__` given from parent
117 117 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
118 118 let dotted_name = &format!("{}.dirstate", package);
119 119 let m = PyModule::new(py, dotted_name)?;
120 120
121 121 m.add(py, "__package__", package)?;
122 122 m.add(py, "__doc__", "Dirstate - Rust implementation")?;
123 123
124 124 m.add_class::<Dirs>(py)?;
125 125 m.add_class::<DirstateMap>(py)?;
126 126
127 127 let sys = PyModule::import(py, "sys")?;
128 128 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
129 129 sys_modules.set_item(py, dotted_name, &m)?;
130 130
131 131 Ok(m)
132 132 }
General Comments 0
You need to be logged in to leave comments. Login now