annotate rust/hg-cpython/src/dirstate.rs @ 42764:7cae6bc29ff9

rust-parsers: switch to parse/pack_dirstate to mutate-on-loop Both `parse_dirstate` and `pack_dirstate` can operate directly on the data they're passed, which prevents the creation of intermediate data structures, simplifies the function signatures and reduces boilerplate. They are exposed directly to the Python for now, but a later patch will make use of them inside `hg-core`. Differential Revision: https://phab.mercurial-scm.org/D6628
author Rapha?l Gom?s <rgomes@octobus.net>
date Tue, 09 Jul 2019 11:49:49 +0200
parents 760a7851e9ba
children 7ceded4419a3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
1 // dirstate.rs
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
2 //
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
4 //
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
7
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
8 //! Bindings for the `hg::dirstate` module provided by the
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
9 //! `hg-core` package.
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
10 //!
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
11 //! From Python, this will be seen as `mercurial.rustext.dirstate`
42762
b3518b0baa47 rust-dirstate: create dirstate submodule in hg-cpython
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
12 mod dirs_multiset;
b3518b0baa47 rust-dirstate: create dirstate submodule in hg-cpython
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
13 use crate::dirstate::dirs_multiset::Dirs;
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
14 use cpython::{
42763
760a7851e9ba rust-parsers: move parser bindings to their own file and Python module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42762
diff changeset
15 PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence, Python,
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
16 };
42764
7cae6bc29ff9 rust-parsers: switch to parse/pack_dirstate to mutate-on-loop
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42763
diff changeset
17 use hg::{DirstateEntry, StateMap};
42609
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42561
diff changeset
18 use libc::{c_char, c_int};
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42561
diff changeset
19 #[cfg(feature = "python27")]
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42561
diff changeset
20 use python27_sys::PyCapsule_Import;
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42561
diff changeset
21 #[cfg(feature = "python3")]
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42561
diff changeset
22 use python3_sys::PyCapsule_Import;
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
23 use std::ffi::CStr;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
24 use std::mem::transmute;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
25
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
26 /// C code uses a custom `dirstate_tuple` type, checks in multiple instances
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
27 /// for this type, and raises a Python `Exception` if the check does not pass.
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
28 /// Because this type differs only in name from the regular Python tuple, it
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
29 /// would be a good idea in the near future to remove it entirely to allow
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
30 /// for a pure Python tuple of the same effective structure to be used,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
31 /// rendering this type and the capsule below useless.
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
32 type MakeDirstateTupleFn = extern "C" fn(
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
33 state: c_char,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
34 mode: c_int,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
35 size: c_int,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
36 mtime: c_int,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
37 ) -> PyObject;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
38
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
39 /// This is largely a copy/paste from cindex.rs, pending the merge of a
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
40 /// `py_capsule_fn!` macro in the rust-cpython project:
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
41 /// https://github.com/dgrunwald/rust-cpython/pull/169
42763
760a7851e9ba rust-parsers: move parser bindings to their own file and Python module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42762
diff changeset
42 pub fn decapsule_make_dirstate_tuple(
760a7851e9ba rust-parsers: move parser bindings to their own file and Python module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42762
diff changeset
43 py: Python,
760a7851e9ba rust-parsers: move parser bindings to their own file and Python module
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42762
diff changeset
44 ) -> PyResult<MakeDirstateTupleFn> {
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
45 unsafe {
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
46 let caps_name = CStr::from_bytes_with_nul_unchecked(
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
47 b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0",
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
48 );
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
49 let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0);
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
50 if from_caps.is_null() {
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
51 return Err(PyErr::fetch(py));
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
52 }
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
53 Ok(transmute(from_caps))
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
54 }
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
55 }
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
56
42764
7cae6bc29ff9 rust-parsers: switch to parse/pack_dirstate to mutate-on-loop
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42763
diff changeset
57 pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
42544
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
58 dmap.items(py)
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
59 .iter()
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
60 .map(|(filename, stats)| {
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
61 let stats = stats.extract::<PySequence>(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
62 let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
63 let state = state.data(py)[0] as i8;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
64 let mode = stats.get_item(py, 1)?.extract(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
65 let size = stats.get_item(py, 2)?.extract(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
66 let mtime = stats.get_item(py, 3)?.extract(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
67 let filename = filename.extract::<PyBytes>(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
68 let filename = filename.data(py);
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
69 Ok((
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
70 filename.to_owned(),
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
71 DirstateEntry {
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
72 state,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
73 mode,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
74 size,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
75 mtime,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
76 },
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
77 ))
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
78 })
42544
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
79 .collect()
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
80 }
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
81
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
82 /// Create the module, with `__package__` given from parent
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
83 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
84 let dotted_name = &format!("{}.dirstate", package);
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
85 let m = PyModule::new(py, dotted_name)?;
42544
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
86
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
87 m.add(py, "__package__", package)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
88 m.add(py, "__doc__", "Dirstate - Rust implementation")?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
89
42544
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
90 m.add_class::<Dirs>(py)?;
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42427
diff changeset
91
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
92 let sys = PyModule::import(py, "sys")?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
93 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
94 sys_modules.set_item(py, dotted_name, &m)?;
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
95
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
96 Ok(m)
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
97 }