rust/hg-cpython/src/dirstate.rs
author Yuya Nishihara <yuya@tcha.org>
Sun, 13 Oct 2019 17:07:44 +0900
changeset 43213 0246bbe1045d
parent 43211 88a9930e92e4
child 43273 478d0b1bf0c5
permissions -rw-r--r--
rust-cpython: leverage upstreamed py_capsule_fn!() macro
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42303
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`
42754
4e8f504424f3 rust-dirstate: rust-cpython bridge for dirstatemap
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42749
diff changeset
    12
mod copymap;
42746
b3518b0baa47 rust-dirstate: create dirstate submodule in hg-cpython
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42609
diff changeset
    13
mod dirs_multiset;
42754
4e8f504424f3 rust-dirstate: rust-cpython bridge for dirstatemap
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42749
diff changeset
    14
mod dirstate_map;
4e8f504424f3 rust-dirstate: rust-cpython bridge for dirstatemap
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42749
diff changeset
    15
use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap};
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    16
use cpython::{
42749
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    17
    exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence,
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    18
    Python,
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    19
};
42957
7a01778bc7b7 rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42754
diff changeset
    20
use hg::{
7a01778bc7b7 rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42754
diff changeset
    21
    utils::hg_path::HgPathBuf, DirstateEntry, DirstateParseError, EntryState,
7a01778bc7b7 rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42754
diff changeset
    22
    StateMap,
7a01778bc7b7 rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42754
diff changeset
    23
};
42609
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42558
diff changeset
    24
use libc::{c_char, c_int};
42749
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    25
use std::convert::TryFrom;
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    26
43211
88a9930e92e4 rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara <yuya@tcha.org>
parents: 43210
diff changeset
    27
// C code uses a custom `dirstate_tuple` type, checks in multiple instances
88a9930e92e4 rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara <yuya@tcha.org>
parents: 43210
diff changeset
    28
// for this type, and raises a Python `Exception` if the check does not pass.
88a9930e92e4 rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara <yuya@tcha.org>
parents: 43210
diff changeset
    29
// Because this type differs only in name from the regular Python tuple, it
88a9930e92e4 rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara <yuya@tcha.org>
parents: 43210
diff changeset
    30
// would be a good idea in the near future to remove it entirely to allow
88a9930e92e4 rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara <yuya@tcha.org>
parents: 43210
diff changeset
    31
// for a pure Python tuple of the same effective structure to be used,
88a9930e92e4 rust-cpython: turn inline comments into non-doc comments
Yuya Nishihara <yuya@tcha.org>
parents: 43210
diff changeset
    32
// rendering this type and the capsule below useless.
43213
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    33
py_capsule_fn!(
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    34
    from mercurial.cext.parsers import make_dirstate_tuple_CAPI
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    35
        as make_dirstate_tuple_capi
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    36
        signature (
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    37
            state: c_char,
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    38
            mode: c_int,
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    39
            size: c_int,
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    40
            mtime: c_int,
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    41
        ) -> *mut RawPyObject
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    42
);
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    43
43208
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    44
pub fn make_dirstate_tuple(
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    45
    py: Python,
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    46
    entry: &DirstateEntry,
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    47
) -> PyResult<PyObject> {
43213
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    48
    // might be silly to retrieve capsule function in hot loop
0246bbe1045d rust-cpython: leverage upstreamed py_capsule_fn!() macro
Yuya Nishihara <yuya@tcha.org>
parents: 43211
diff changeset
    49
    let make = make_dirstate_tuple_capi::retrieve(py)?;
43208
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    50
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    51
    let &DirstateEntry {
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    52
        state,
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    53
        mode,
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    54
        size,
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    55
        mtime,
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    56
    } = entry;
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    57
    // Explicitly go through u8 first, then cast to platform-specific `c_char`
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    58
    // because Into<u8> has a specific implementation while `as c_char` would
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    59
    // just do a naive enum cast.
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    60
    let state_code: u8 = state.into();
43209
8b355cbef16d rust-cpython: mark capsule function as unsafe
Yuya Nishihara <yuya@tcha.org>
parents: 43208
diff changeset
    61
43210
3fec5244aff1 rust-cpython: fix signature of make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 43209
diff changeset
    62
    let maybe_obj = unsafe {
43209
8b355cbef16d rust-cpython: mark capsule function as unsafe
Yuya Nishihara <yuya@tcha.org>
parents: 43208
diff changeset
    63
        let ptr = make(state_code as c_char, mode, size, mtime);
43210
3fec5244aff1 rust-cpython: fix signature of make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 43209
diff changeset
    64
        PyObject::from_owned_ptr_opt(py, ptr)
3fec5244aff1 rust-cpython: fix signature of make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 43209
diff changeset
    65
    };
3fec5244aff1 rust-cpython: fix signature of make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 43209
diff changeset
    66
    maybe_obj.ok_or_else(|| PyErr::fetch(py))
43208
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    67
}
1ca3823aeefd rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
Yuya Nishihara <yuya@tcha.org>
parents: 42957
diff changeset
    68
42748
7cae6bc29ff9 rust-parsers: switch to parse/pack_dirstate to mutate-on-loop
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42747
diff changeset
    69
pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
42537
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
    70
    dmap.items(py)
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    71
        .iter()
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    72
        .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
    73
            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
    74
            let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
42749
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    75
            let state = EntryState::try_from(state.data(py)[0]).map_err(
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    76
                |e: DirstateParseError| {
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    77
                    PyErr::new::<exc::ValueError, _>(py, e.to_string())
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    78
                },
7ceded4419a3 rust-dirstate: use EntryState enum instead of literals
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42748
diff changeset
    79
            )?;
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    80
            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
    81
            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
    82
            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
    83
            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
    84
            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
    85
            Ok((
42957
7a01778bc7b7 rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42754
diff changeset
    86
                HgPathBuf::from(filename.to_owned()),
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    87
                DirstateEntry {
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    88
                    state,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    89
                    mode,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    90
                    size,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    91
                    mtime,
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    92
                },
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    93
            ))
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    94
        })
42537
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
    95
        .collect()
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
    96
}
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
    97
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
    98
/// 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
    99
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
   100
    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
   101
    let m = PyModule::new(py, dotted_name)?;
42537
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
   102
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   103
    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
   104
    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
   105
42537
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
   106
    m.add_class::<Dirs>(py)?;
42754
4e8f504424f3 rust-dirstate: rust-cpython bridge for dirstatemap
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42749
diff changeset
   107
    m.add_class::<DirstateMap>(py)?;
42537
ce94f9622acd rust-dirstate: add "dirs" rust-cpython binding
Rapha?l Gom?s <rgomes@octobus.net>
parents: 42408
diff changeset
   108
42303
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   109
    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
   110
    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
   111
    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
   112
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff changeset
   113
    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
   114
}