##// END OF EJS Templates
sharesafe: add functionality to automatically downgrade shares...
sharesafe: add functionality to automatically downgrade shares Reasoning is same as previous patch which adds automatic upgrade support. Downgrade is required as if automatic upgrade is enabled, all shares upgrade and then source repository downgrades, shares won't work. We need to downgrade them. Differential Revision: https://phab.mercurial-scm.org/D9680

File last commit:

r46764:294d5aca default
r46853:eec47efe default
Show More
copy_tracing.rs
148 lines | 4.9 KiB | application/rls-services+xml | RustLexer
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 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;
copies-rust: parse the changed-file sidedata directly in rust...
r46674 use hg::copy_tracing::DataHolder;
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 use hg::copy_tracing::RevInfo;
copies-rust: parse the changed-file sidedata directly in rust...
r46674 use hg::copy_tracing::RevInfoMaker;
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 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,
copies: iterate over children directly (instead of parents)...
r46764 children_count: PyDict,
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 target_rev: Revision,
rev_info: PyObject,
is_ancestor: PyObject,
) -> PyResult<PyDict> {
let revs: PyResult<_> =
revs.iter(py).map(|r| Ok(r.extract(py)?)).collect();
// Wrap the `is_ancestor` python callback as a Rust closure
//
// No errors are expected from the Python side, and they will should only
// happens in case of programing error or severe data corruption. Such
// errors will raise panic and the rust-cpython harness will turn them into
// Python exception.
let is_ancestor_wrap = |anc: Revision, desc: Revision| -> bool {
is_ancestor
.call(py, (anc, desc), None)
.expect(
"rust-copy-tracing: python call to `is_ancestor` \
failed",
)
.cast_into::<PyBool>(py)
.expect(
"rust-copy-tracing: python call to `is_ancestor` \
returned unexpected non-Bool value",
)
.is_true()
};
// Wrap the `rev_info_maker` python callback as a Rust closure
//
// No errors are expected from the Python side, and they will should only
// happens in case of programing error or severe data corruption. Such
// errors will raise panic and the rust-cpython harness will turn them into
// Python exception.
copies-rust: parse the changed-file sidedata directly in rust...
r46674 let rev_info_maker: RevInfoMaker<PyBytes> =
Box::new(|rev: Revision, d: &mut DataHolder<PyBytes>| -> RevInfo {
let res: PyTuple = rev_info
.call(py, (rev,), None)
.expect("rust-copy-tracing: python call to `rev_info` failed")
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 .cast_into(py)
.expect(
copies-rust: parse the changed-file sidedata directly in rust...
r46674 "rust-copy_tracing: python call to `rev_info` returned \
unexpected non-Tuple value",
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 );
copies-rust: parse the changed-file sidedata directly in rust...
r46674 let p1 = res.get_item(py, 0).extract(py).expect(
"rust-copy-tracing: rev_info return is invalid, first item \
is a not a revision",
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 );
copies-rust: parse the changed-file sidedata directly in rust...
r46674 let p2 = res.get_item(py, 1).extract(py).expect(
"rust-copy-tracing: rev_info return is invalid, first item \
is a not a revision",
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 );
copies-rust: parse the changed-file sidedata directly in rust...
r46674 let files = match res.get_item(py, 2).extract::<PyBytes>(py) {
Ok(raw) => {
// Give responsability for the raw bytes lifetime to
// hg-core
d.data = Some(raw);
let addrs = d.data.as_ref().expect(
"rust-copy-tracing: failed to get a reference to the \
raw bytes for copy data").data(py);
ChangedFiles::new(addrs)
}
// value was presumably None, meaning they was no copy data.
Err(_) => ChangedFiles::new_empty(),
};
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557
copies-rust: parse the changed-file sidedata directly in rust...
r46674 (p1, p2, files)
});
copies: iterate over children directly (instead of parents)...
r46764 let children_count: PyResult<_> = children_count
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 .items(py)
.iter()
copies: iterate over children directly (instead of parents)...
r46764 .map(|(k, v)| Ok((k.extract(py)?, v.extract(py)?)))
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 .collect();
let res = combine_changeset_copies(
revs?,
copies: iterate over children directly (instead of parents)...
r46764 children_count?,
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 target_rev,
copies-rust: parse the changed-file sidedata directly in rust...
r46674 rev_info_maker,
copies: introduce the hg-cpython wrapper for `combine_changeset_copies`...
r46557 &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)
}