Skip to content
Snippets Groups Projects
Commit 8de45771ff4e authored by Pierre-Yves David's avatar Pierre-Yves David :octopus:
Browse files

copies: introduce the hg-cpython wrapper for `combine_changeset_copies`

This patch focus on the `hg-cpython` part of this work. Bridging the python code
with the new rust code in `hg-core`. The next patch will actually plug this in
the python code.
parent 5c2994783d1e
No related branches found
No related tags found
1 merge request!55Draft: Topic/default/path copies rust
use cpython::ObjectProtocol;
use cpython::PyBool;
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::combine_changeset_copies;
use hg::copy_tracing::ChangedFiles;
use hg::copy_tracing::RevInfo;
use hg::utils::hg_path::HgPathBuf;
use hg::Revision;
pub fn combine_changeset_copies_wrapper(
py: Python,
revs: PyList,
children: PyDict,
target_rev: Revision,
rev_info: PyObject,
is_ancestor: PyObject,
) -> PyResult<PyDict> {
let revs: PyResult<_> =
revs.iter(py).map(|r| Ok(r.extract(py)?)).collect();
let is_ancestor_wrap = |anc: Revision, desc: Revision| -> bool {
is_ancestor
.call(py, (anc, desc), None)
.unwrap()
.cast_into::<PyBool>(py)
.expect("is_ancestor broke")
.is_true()
};
let rev_info_maker = |rev: Revision| -> RevInfo {
let res: PyTuple = rev_info
.call(py, (rev,), None)
.unwrap()
.cast_into(py)
.expect("res broke");
let p1 = res.get_item(py, 0).extract(py).unwrap();
let p2 = res.get_item(py, 1).extract(py).unwrap();
let changes = res.get_item(py, 2);
let files;
if !changes
.hasattr(py, "copied_from_p1")
.expect("hasattr failed")
{
files = ChangedFiles::new_empty();
} else {
let p1_copies: PyDict = changes
.getattr(py, "copied_from_p1")
.expect("getting `copied_from_p1` attribute broke")
.cast_into(py)
.expect("casting `copied_from_p1` broke");
let p1_copies: PyResult<_> = p1_copies
.items(py)
.iter()
.map(|(key, value)| {
let key = key.extract::<PyBytes>(py)?;
let key = key.data(py);
let value = value.extract::<PyBytes>(py)?;
let value = value.data(py);
Ok((
HgPathBuf::from_bytes(key),
HgPathBuf::from_bytes(value),
))
})
.collect();
let p2_copies: PyDict = changes
.getattr(py, "copied_from_p2")
.expect("getting `copied_from_p2` attribute broke")
.cast_into(py)
.expect("casting `copied_from_p2` broke");
let p2_copies: PyResult<_> = p2_copies
.items(py)
.iter()
.map(|(key, value)| {
let key = key.extract::<PyBytes>(py)?;
let key = key.data(py);
let value = value.extract::<PyBytes>(py)?;
let value = value.data(py);
Ok((
HgPathBuf::from_bytes(key),
HgPathBuf::from_bytes(value),
))
})
.collect();
let removed: PyObject = changes
.getattr(py, "removed")
.expect("getting `removed` attribute broke");
let removed: PyResult<_> = removed
.iter(py)
.expect("interating on `removed` broke")
.map(|filename| {
let filename = filename
.expect("getting filename for `removed` broke")
.extract::<PyBytes>(py)?;
let filename = filename.data(py);
Ok(HgPathBuf::from_bytes(filename))
})
.collect();
let merged: PyObject = changes
.getattr(py, "merged")
.expect("getting `merged` attribute broke");
let merged: PyResult<_> = merged
.iter(py)
.expect("interating on `merged` broke")
.map(|filename| {
let filename = filename
.expect("getting filename for `merged` broke")
.extract::<PyBytes>(py)?;
let filename = filename.data(py);
Ok(HgPathBuf::from_bytes(filename))
})
.collect();
let salvaged: PyObject = changes
.getattr(py, "salvaged")
.expect("getting `salvaged` attribute broke");
let salvaged: PyResult<_> = salvaged
.iter(py)
.expect("interating on `salvaged` broke")
.map(|filename| {
let filename = filename
.expect("getting filename for `salvaged` broke")
.extract::<PyBytes>(py)?;
let filename = filename.data(py);
Ok(HgPathBuf::from_bytes(filename))
})
.collect();
files = ChangedFiles::new(
removed.unwrap(),
merged.unwrap(),
salvaged.unwrap(),
p1_copies.unwrap(),
p2_copies.unwrap(),
);
}
(p1, p2, files)
};
let children: PyResult<_> = children
.items(py)
.iter()
.map(|(k, v)| {
let v: &PyList = v.cast_as(py)?;
let v: PyResult<_> =
v.iter(py).map(|child| Ok(child.extract(py)?)).collect();
Ok((k.extract(py)?, v?))
})
.collect();
let res = combine_changeset_copies(
revs?,
children?,
target_rev,
&rev_info_maker,
&is_ancestor_wrap,
);
let out = PyDict::new(py);
for (dest, source) in res.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,
is_ancestor: 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)
}
......@@ -29,6 +29,7 @@
mod conversion;
#[macro_use]
pub mod ref_sharing;
pub mod copy_tracing;
pub mod dagops;
pub mod debug;
pub mod dirstate;
......@@ -49,6 +50,11 @@
m.add(py, "ancestor", ancestors::init_module(py, &dotted_name)?)?;
m.add(py, "dagop", dagops::init_module(py, &dotted_name)?)?;
m.add(py, "debug", debug::init_module(py, &dotted_name)?)?;
m.add(
py,
"copy_tracing",
copy_tracing::init_module(py, &dotted_name)?,
)?;
m.add(py, "discovery", discovery::init_module(py, &dotted_name)?)?;
m.add(py, "dirstate", dirstate::init_module(py, &dotted_name)?)?;
m.add(py, "revlog", revlog::init_module(py, &dotted_name)?)?;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment