Mercurial > public > mercurial-scm > hg
annotate rust/hg-cpython/src/dagops.rs @ 52167:7be39c5110c9
hg-core: add a complete VFS
This will be used from Python in a later change.
More changes are needed in hg-core and rhg to properly clean up the APIs
of the old VFS implementation but it can be done when the dust settles
and we start adding more functionality to the pure Rust VFS.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Mon, 29 Jul 2024 20:47:43 +0200 |
parents | 24d3298189d7 |
children |
rev | line source |
---|---|
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; |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
18 use vcsgraph::graph::Rank; |
41694
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
19 |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
20 use crate::revlog::py_rust_index_to_graph; |
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 |
41694
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
22 /// 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
|
23 /// |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
24 /// This is the Rust counterpart for `mercurial.dagop.headrevs` |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
25 pub fn headrevs( |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
26 py: Python, |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
27 index: PyObject, |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
28 revs: PyObject, |
50976
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48854
diff
changeset
|
29 ) -> PyResult<HashSet<PyRevision>> { |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
30 let py_leaked = py_rust_index_to_graph(py, index)?; |
51252
24d3298189d7
rust-index: document safety invariants being upheld for every `unsafe` block
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51238
diff
changeset
|
31 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
32 let index = &*unsafe { py_leaked.try_borrow(py)? }; |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
33 let mut as_set: HashSet<Revision> = rev_pyiter_collect(py, &revs, index)?; |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
34 dagops::retain_heads(index, &mut as_set) |
41694
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
35 .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
|
36 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
|
37 } |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
38 |
48854
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
39 /// 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
|
40 /// of a node represented by its parents. |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
41 /// |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
42 /// Currently, the pure Rust index supports only the REVLOGV1 format, hence |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
43 /// the only possible return value is that the rank is unknown. |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
44 /// |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
45 /// References: |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
46 /// - C implementation, function `index_fast_rank()`. |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
47 /// - `impl vcsgraph::graph::RankedGraph for Index` in `crate::cindex`. |
48854
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
48 pub fn rank( |
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
49 py: Python, |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
50 _index: PyObject, |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
51 _p1r: PyRevision, |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
52 _p2r: PyRevision, |
48854
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
53 ) -> PyResult<Rank> { |
51238
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
54 Err(GraphError::pynew_from_vcsgraph( |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
55 py, |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
56 vcsgraph::graph::GraphReadError::InconsistentGraphData, |
578c049f0408
rust-index: using `hg::index::Index` in `hg-cpython::dagops`
Georges Racinet <georges.racinet@octobus.net>
parents:
50976
diff
changeset
|
57 )) |
48854
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
58 } |
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
59 |
41694
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
60 /// Create the module, with `__package__` given from parent |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
61 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
|
62 let dotted_name = &format!("{}.dagop", package); |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
63 let m = PyModule::new(py, dotted_name)?; |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
64 m.add(py, "__package__", package)?; |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
65 m.add(py, "__doc__", "DAG operations - Rust implementation")?; |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
66 m.add( |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
67 py, |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
68 "headrevs", |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
69 py_fn!(py, headrevs(index: PyObject, revs: PyObject)), |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
70 )?; |
48854
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
71 m.add( |
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
72 py, |
8b8054b8e5a7
rust: expose rank computation function to python
pacien <pacien.trangirard@pacien.net>
parents:
43945
diff
changeset
|
73 "rank", |
50976
4c5f6e95df84
rust: make `Revision` a newtype
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48854
diff
changeset
|
74 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
|
75 )?; |
41694
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
76 |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
77 let sys = PyModule::import(py, "sys")?; |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
78 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
|
79 sys_modules.set_item(py, dotted_name, &m)?; |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
80 // 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
|
81 // 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
|
82 // Rust PyObject is dropped. |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
83 Ok(m) |
0c7b353ce100
rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents:
diff
changeset
|
84 } |