Mercurial > public > mercurial-scm > hg-stable
view rust/hg-cpython/src/copy_tracing.rs @ 46626:cb4b0b0c6de4
copies-rust: split up combine_changeset_copies function into a struct
? such that each iteration of its former loop is now a method call,
with the caller driving the loop.
This entirely removes the need for the `DataHolder` hack:
the method now takes a `ChangedFiles<'_>` parameter that borrows
a bytes buffer that can be owned by the caller?s stack frame,
just for the duration of that call.
Differential Revision: https://phab.mercurial-scm.org/D9683
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Tue, 05 Jan 2021 21:02:00 +0100 |
parents | 34827c95092c |
children | 47557ea79fc7 |
line wrap: on
line source
use cpython::ObjectProtocol; use cpython::PyBytes; use cpython::PyDict; use cpython::PyList; use cpython::PyModule; use cpython::PyObject; use cpython::PyResult; use cpython::PyTuple; use cpython::Python; use hg::copy_tracing::ChangedFiles; use hg::copy_tracing::CombineChangesetCopies; use hg::Revision; /// Combines copies information contained into revision `revs` to build a copy /// map. /// /// See mercurial/copies.py for details pub fn combine_changeset_copies_wrapper( py: Python, revs: PyList, children_count: PyDict, target_rev: Revision, rev_info: PyObject, ) -> PyResult<PyDict> { let children_count = children_count .items(py) .iter() .map(|(k, v)| Ok((k.extract(py)?, v.extract(py)?))) .collect::<PyResult<_>>()?; /// (Revision number, parent 1, parent 2, copy data for this revision) type RevInfo = (Revision, Revision, Revision, Option<PyBytes>); let revs_info = revs.iter(py).map(|rev_py| -> PyResult<RevInfo> { let rev = rev_py.extract(py)?; let tuple: PyTuple = rev_info.call(py, (rev_py,), None)?.cast_into(py)?; let p1 = tuple.get_item(py, 0).extract(py)?; let p2 = tuple.get_item(py, 1).extract(py)?; let opt_bytes = tuple.get_item(py, 2).extract(py)?; Ok((rev, p1, p2, opt_bytes)) }); let mut combine_changeset_copies = CombineChangesetCopies::new(children_count); for rev_info in revs_info { let (rev, p1, p2, opt_bytes) = rev_info?; let files = match &opt_bytes { Some(bytes) => ChangedFiles::new(bytes.data(py)), // value was presumably None, meaning they was no copy data. None => ChangedFiles::new_empty(), }; combine_changeset_copies.add_revision(rev, p1, p2, files) } let path_copies = combine_changeset_copies.finish(target_rev); let out = PyDict::new(py); for (dest, source) in path_copies.into_iter() { out.set_item( py, PyBytes::new(py, &dest.into_vec()), PyBytes::new(py, &source.into_vec()), )?; } Ok(out) } /// Create the module, with `__package__` given from parent pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> { let dotted_name = &format!("{}.copy_tracing", package); let m = PyModule::new(py, dotted_name)?; m.add(py, "__package__", package)?; m.add(py, "__doc__", "Copy tracing - Rust implementation")?; m.add( py, "combine_changeset_copies", py_fn!( py, combine_changeset_copies_wrapper( revs: PyList, children: PyDict, target_rev: Revision, rev_info: PyObject ) ), )?; let sys = PyModule::import(py, "sys")?; let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?; sys_modules.set_item(py, dotted_name, &m)?; Ok(m) }