##// END OF EJS Templates
packaging: support building Inno installer with PyOxidizer...
packaging: support building Inno installer with PyOxidizer We want to start distributing Mercurial on Python 3 on Windows. PyOxidizer will be our vehicle for achieving that. This commit implements basic support for producing Inno installers using PyOxidizer. While it is an eventual goal of PyOxidizer to produce installers, those features aren't yet implemented. So our strategy for producing Mercurial installers is similar to what we've been doing with py2exe: invoke a build system to produce files then stage those files into a directory so they can be turned into an installer. We had to make significant alterations to the pyoxidizer.bzl config file to get it to produce the files that we desire for a Windows install. This meant differentiating the build targets so we can target Windows specifically. We've added a new module to hgpackaging to deal with interacting with PyOxidizer. It is similar to pyexe: we invoke a build process then copy files to a staging directory. Ideally these extra files would be defined in pyoxidizer.bzl. But I don't think it is worth doing at this time, as PyOxidizer's config files are lacking some features to make this turnkey. The rest of the change is introducing a variant of the Inno installer code that invokes PyOxidizer instead of py2exe. Comparing the Python 2.7 based Inno installers with this one, the following changes were observed: * No lib/*.{pyd, dll} files * No Microsoft.VC90.CRT.manifest * No msvc{m,p,r}90.dll files * python27.dll replaced with python37.dll * Add vcruntime140.dll file The disappearance of the .pyd and .dll files is acceptable, as PyOxidizer has embedded these in hg.exe and loads them from memory. The disappearance of the *90* files is acceptable because those provide the Visual C++ 9 runtime, as required by Python 2.7. Similarly, the appearance of vcruntime140.dll is a requirement of Python 3.7. Differential Revision: https://phab.mercurial-scm.org/D8473

File last commit:

r44278:5ac243a9 default
r45256:9965d6c3 default
Show More
parsers.rs
175 lines | 5.2 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 // parsers.rs
//
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//! Bindings for the `hg::dirstate::parsers` module provided by the
//! `hg-core` package.
//!
//! From Python, this will be seen as `mercurial.rustext.parsers`
use cpython::{
exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
Yuya Nishihara
rust-parsers: fix unboxing of PyInt on Python 3...
r43061 PythonObject, ToPyObject,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 };
use hg::{
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf,
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 DirstatePackError, DirstateParents, DirstateParseError, FastHashMap,
PARENT_SIZE,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 };
Yuya Nishihara
rust: simply use TryInto to convert slice to array...
r43067 use std::convert::TryInto;
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 use crate::dirstate::{extract_dirstate, make_dirstate_tuple};
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 use std::time::Duration;
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992
fn parse_dirstate_wrapper(
py: Python,
dmap: PyDict,
copymap: PyDict,
st: PyBytes,
) -> PyResult<PyTuple> {
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let mut dirstate_map = FastHashMap::default();
let mut copies = FastHashMap::default();
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993
match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) {
Ok(parents) => {
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 for (filename, entry) in &dirstate_map {
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 dmap.set_item(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 PyBytes::new(py, filename.as_ref()),
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 make_dirstate_tuple(py, entry)?,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 )?;
}
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 for (path, copy_path) in copies {
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 copymap.set_item(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 PyBytes::new(py, path.as_ref()),
PyBytes::new(py, copy_path.as_ref()),
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 )?;
}
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 Ok(
(PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2))
.to_py_object(py),
)
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 }
Err(e) => Err(PyErr::new::<exc::ValueError, _>(
py,
match e {
DirstateParseError::TooLittleData => {
"too little data for parents".to_string()
}
DirstateParseError::Overflow => {
"overflow in dirstate".to_string()
}
DirstateParseError::CorruptedEntry(e) => e,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 DirstateParseError::Damaged => {
"dirstate appears to be damaged".to_string()
}
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 },
)),
}
}
fn pack_dirstate_wrapper(
py: Python,
dmap: PyDict,
copymap: PyDict,
pl: PyTuple,
now: PyInt,
) -> PyResult<PyBytes> {
let p1 = pl.get_item(py, 0).extract::<PyBytes>(py)?;
let p1: &[u8] = p1.data(py);
let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?;
let p2: &[u8] = p2.data(py);
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let mut dirstate_map = extract_dirstate(py, &dmap)?;
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992
Raphaël Gomès
rust-performance: introduce FastHashMap type alias for HashMap...
r44278 let copies: Result<FastHashMap<HgPathBuf, HgPathBuf>, PyErr> = copymap
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 .items(py)
.iter()
.map(|(key, value)| {
Ok((
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(key.extract::<PyBytes>(py)?.data(py)),
HgPathBuf::from_bytes(value.extract::<PyBytes>(py)?.data(py)),
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 ))
})
.collect();
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 if p1.len() != PARENT_SIZE || p2.len() != PARENT_SIZE {
return Err(PyErr::new::<exc::ValueError, _>(
py,
"expected a 20-byte hash".to_string(),
));
}
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 match pack_dirstate(
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 &mut dirstate_map,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 &copies?,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 DirstateParents {
Yuya Nishihara
rust: simply use TryInto to convert slice to array...
r43067 p1: p1.try_into().unwrap(),
p2: p2.try_into().unwrap(),
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 },
Yuya Nishihara
rust-parsers: fix unboxing of PyInt on Python 3...
r43061 Duration::from_secs(now.as_object().extract::<u64>(py)?),
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 ) {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 Ok(packed) => {
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 for (filename, entry) in &dirstate_map {
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 dmap.set_item(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 PyBytes::new(py, filename.as_ref()),
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 make_dirstate_tuple(py, entry)?,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 )?;
}
Ok(PyBytes::new(py, &packed))
}
Err(error) => Err(PyErr::new::<exc::ValueError, _>(
py,
match error {
DirstatePackError::CorruptedParent => {
"expected a 20-byte hash".to_string()
}
DirstatePackError::CorruptedEntry(e) => e,
DirstatePackError::BadSize(expected, actual) => {
format!("bad dirstate size: {} != {}", actual, expected)
}
},
)),
}
}
/// Create the module, with `__package__` given from parent
pub fn init_parsers_module(py: Python, package: &str) -> PyResult<PyModule> {
let dotted_name = &format!("{}.parsers", package);
let m = PyModule::new(py, dotted_name)?;
m.add(py, "__package__", package)?;
m.add(py, "__doc__", "Parsers - Rust implementation")?;
m.add(
py,
"parse_dirstate",
py_fn!(
py,
parse_dirstate_wrapper(dmap: PyDict, copymap: PyDict, st: PyBytes)
),
)?;
m.add(
py,
"pack_dirstate",
py_fn!(
py,
pack_dirstate_wrapper(
dmap: PyDict,
copymap: PyDict,
pl: PyTuple,
now: PyInt
)
),
)?;
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)
}