rust/hg-cpython/src/dagops.rs
author Rapha?l Gom?s <rgomes@octobus.net>
Wed, 28 Jun 2023 16:43:39 +0200
changeset 51192 f6403bcd9f96
parent 50976 4c5f6e95df84
child 51238 578c049f0408
permissions -rw-r--r--
rust-index: synchronize remove to Rust index Future steps will bring the two indexes further together until we can rip the C index entirely when running Rust code.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     1
// dagops.rs
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     2
//
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     3
// Copyright 2019 Georges Racinet <georges.racinet@octobus.net>
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     4
//
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     7
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     8
//! Bindings for the `hg::dagops` module provided by the
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
     9
//! `hg-core` package.
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    10
//!
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    11
//! From Python, this will be seen as `mercurial.rustext.dagop`
50976
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    12
use crate::PyRevision;
43945
f98f0e3ddaa1 rust-index: add a function to convert PyObject index for hg-core
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43269
diff changeset
    13
use crate::{conversion::rev_pyiter_collect, exceptions::GraphError};
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    14
use cpython::{PyDict, PyModule, PyObject, PyResult, Python};
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    15
use hg::dagops;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    16
use hg::Revision;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    17
use std::collections::HashSet;
48854
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    18
use vcsgraph::ancestors::node_rank;
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    19
use vcsgraph::graph::{Parents, Rank};
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    20
43945
f98f0e3ddaa1 rust-index: add a function to convert PyObject index for hg-core
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43269
diff changeset
    21
use crate::revlog::pyindex_to_graph;
f98f0e3ddaa1 rust-index: add a function to convert PyObject index for hg-core
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43269
diff changeset
    22
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    23
/// Using the the `index`, return heads out of any Python iterable of Revisions
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    24
///
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    25
/// This is the Rust counterpart for `mercurial.dagop.headrevs`
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    26
pub fn headrevs(
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    27
    py: Python,
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    28
    index: PyObject,
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    29
    revs: PyObject,
50976
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    30
) -> PyResult<HashSet<PyRevision>> {
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    31
    let index = pyindex_to_graph(py, index)?;
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    32
    let mut as_set: HashSet<Revision> = rev_pyiter_collect(py, &revs, &index)?;
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    33
    dagops::retain_heads(&index, &mut as_set)
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    34
        .map_err(|e| GraphError::pynew(py, e))?;
50976
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    35
    Ok(as_set.into_iter().map(Into::into).collect())
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    36
}
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    37
48854
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    38
/// Computes the rank, i.e. the number of ancestors including itself,
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    39
/// of a node represented by its parents.
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    40
pub fn rank(
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    41
    py: Python,
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    42
    index: PyObject,
50976
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    43
    p1r: PyRevision,
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    44
    p2r: PyRevision,
48854
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    45
) -> PyResult<Rank> {
50976
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    46
    node_rank(&pyindex_to_graph(py, index)?, &Parents([p1r.0, p2r.0]))
48854
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    47
        .map_err(|e| GraphError::pynew_from_vcsgraph(py, e))
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    48
}
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    49
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    50
/// Create the module, with `__package__` given from parent
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    51
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    52
    let dotted_name = &format!("{}.dagop", package);
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    53
    let m = PyModule::new(py, dotted_name)?;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    54
    m.add(py, "__package__", package)?;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    55
    m.add(py, "__doc__", "DAG operations - Rust implementation")?;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    56
    m.add(
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    57
        py,
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    58
        "headrevs",
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    59
        py_fn!(py, headrevs(index: PyObject, revs: PyObject)),
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    60
    )?;
48854
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    61
    m.add(
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    62
        py,
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    63
        "rank",
50976
4c5f6e95df84 rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48854
diff changeset
    64
        py_fn!(py, rank(index: PyObject, p1r: PyRevision, p2r: PyRevision)),
48854
8b8054b8e5a7 rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents: 43945
diff changeset
    65
    )?;
41694
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    66
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    67
    let sys = PyModule::import(py, "sys")?;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    68
    let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    69
    sys_modules.set_item(py, dotted_name, &m)?;
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    70
    // Example C code (see pyexpat.c and import.c) will "give away the
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    71
    // reference", but we won't because it will be consumed once the
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    72
    // Rust PyObject is dropped.
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    73
    Ok(m)
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff changeset
    74
}