bindings: split the crate into multiple crates

Summary:
Split the crate to improve build time.

Before this change, a naive change on any of the simple modules can still take
20+ seconds to compile, even with incremental compilation enabled.

This diff splits the crate into multiple smaller crates. A simple change to a
simple crate can take < 10 seconds to re-compile.

Different from pre-D13923866 state, there is still only one single Python
extension.

Reviewed By: xavierd

Differential Revision: D17345706

fbshipit-source-id: c7e2e6f0e1b86071c863cfb8989070a581825956
This commit is contained in:
Jun Wu 2019-09-12 10:47:39 -07:00 committed by Facebook Github Bot
parent e14b09a08c
commit 07184f2bb8
45 changed files with 294 additions and 131 deletions

View File

@ -1,53 +0,0 @@
[package]
name = "bindings"
version = "0.1.0"
authors = ["Facebook Source Control Team <sourcecontrol-dev@fb.com>"]
edition = "2018"
[lib]
name = "bindings"
crate-type = ["cdylib"]
[profile.release]
lto = false
[dependencies]
blackbox = { path = "../../../../lib/blackbox" }
bookmarkstore = { path = "../../../../lib/bookmarkstore" }
byteorder = "1.2.7"
bytes = { version = "0.4.11" }
clidispatch = { path = "../../../../lib/clidispatch" }
configparser = { path = "../../../../lib/configparser" }
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython-failure = { path = "../../../../lib/cpython-failure" }
dag = { path = "../../../../lib/dag" }
edenapi = { path = "../../../../lib/edenapi" }
encoding = { path = "../../../../lib/encoding" }
env_logger = "0.5.13"
failure = "0.1.3"
hgcommands = { path = "../../../../lib/hgcommands" }
log = "0.4.6"
lz4-pyframe = { path = "../../../../lib/lz4-pyframe" }
manifest = { path = "../../../../lib/manifest" }
mutationstore = { path = "../../../../lib/mutationstore" }
nodemap = { path = "../../../../lib/nodemap" }
pathmatcher = { path = "../../../../lib/pathmatcher" }
revisionstore = { path = "../../../../lib/revisionstore" }
shlex = "0.1"
stackdesc = { path = "../../../../lib/stackdesc/" }
treestate = { path = "../../../../lib/treestate" }
types = { path = "../../../../lib/types" }
util = { path = "../../../../lib/util" }
vlqencoding = { path = "../../../../lib/vlqencoding" }
zstd = "0.4.18"
zstdelta = { path = "../../../../lib/zstdelta/" }
[dependencies.cpython]
version = "0.3"
default-features = false
features = ["python27-sys", "extension-module-2-7"]
[dependencies.cliparser]
version = "0.0.1"
path = "../../../../lib/cliparser"
features = ["python"]

View File

@ -1,9 +0,0 @@
// Copyright 2018 Facebook, Inc.
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
/// Perform any initialization necessesary for Mercurial's Rust extensions.
pub(crate) fn init_rust() {
env_logger::init();
}

View File

@ -1,51 +0,0 @@
// Copyright Facebook, Inc. 2017
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
#![allow(non_camel_case_types)]
use cpython::py_module_initializer;
pub mod blackbox;
pub mod bookmarkstore;
pub mod cliparser;
pub mod commands;
pub mod configparser;
pub mod dag;
pub mod edenapi;
mod init;
pub mod lz4;
pub mod manifest;
pub mod mutationstore;
pub mod nodemap;
pub mod pathmatcher;
pub mod revisionstore;
pub mod stackdesc;
pub mod treestate;
pub mod vlq;
pub mod zstd;
py_module_initializer!(bindings, initbindings, PyInit_bindings, |py, m| {
init::init_rust();
let name = m.get(py, "__name__")?.extract::<String>(py)?;
m.add(py, "__doc__", "Mercurial Rust Bindings")?;
m.add(py, "blackbox", blackbox::init_module(py, &name)?)?;
m.add(py, "bookmarkstore", bookmarkstore::init_module(py, &name)?)?;
m.add(py, "cliparser", cliparser::init_module(py, &name)?)?;
m.add(py, "commands", commands::init_module(py, &name)?)?;
m.add(py, "configparser", configparser::init_module(py, &name)?)?;
m.add(py, "dag", dag::init_module(py, &name)?)?;
m.add(py, "edenapi", edenapi::init_module(py, &name)?)?;
m.add(py, "lz4", lz4::init_module(py, &name)?)?;
m.add(py, "manifest", manifest::init_module(py, &name)?)?;
m.add(py, "mutationstore", mutationstore::init_module(py, &name)?)?;
m.add(py, "nodemap", nodemap::init_module(py, &name)?)?;
m.add(py, "pathmatcher", pathmatcher::init_module(py, &name)?)?;
m.add(py, "revisionstore", revisionstore::init_module(py, &name)?)?;
m.add(py, "stackdesc", stackdesc::init_module(py, &name)?)?;
m.add(py, "treestate", treestate::init_module(py, &name)?)?;
m.add(py, "vlq", vlq::init_module(py, &name)?)?;
m.add(py, "zstd", zstd::init_module(py, &name)?)?;
Ok(())
});

View File

@ -0,0 +1,34 @@
[package]
name = "bindings"
version = "0.1.0"
edition = "2018"
[lib]
name = "bindings"
crate-type = ["cdylib"]
[profile.release]
debug = true
incremental = true
lto = false
[dependencies]
cpython = { version = "0.3", features = ["python27-sys", "extension-module-2-7"], default-features = false }
env_logger = "0.5"
pyblackbox = { path = "modules/pyblackbox" }
pybookmarkstore = { path = "modules/pybookmarkstore" }
pycliparser = { path = "modules/pycliparser" }
pycommands = { path = "modules/pycommands" }
pyconfigparser = { path = "modules/pyconfigparser" }
pydag = { path = "modules/pydag" }
pyedenapi = { path = "modules/pyedenapi" }
pylz4 = { path = "modules/pylz4" }
pymanifest = { path = "modules/pymanifest" }
pymutationstore = { path = "modules/pymutationstore" }
pynodemap = { path = "modules/pynodemap" }
pypathmatcher = { path = "modules/pypathmatcher" }
pyrevisionstore = { path = "modules/pyrevisionstore" }
pystackdesc = { path = "modules/pystackdesc" }
pytreestate = { path = "modules/pytreestate" }
pyvlq = { path = "modules/pyvlq" }
pyzstd = { path = "modules/pyzstd" }

View File

@ -0,0 +1,10 @@
[package]
name = "pyblackbox"
version = "0.1.0"
edition = "2018"
[dependencies]
blackbox = { path = "../../../../lib/blackbox" }
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }

View File

@ -0,0 +1,10 @@
[package]
name = "pybookmarkstore"
version = "0.1.0"
edition = "2018"
[dependencies]
bookmarkstore = { path = "../../../../lib/bookmarkstore" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
types = { path = "../../../../lib/types" }

View File

@ -3,6 +3,8 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
#![allow(non_camel_case_types)]
use std::cell::RefCell;
use cpython::exc::UnicodeDecodeError;

View File

@ -0,0 +1,11 @@
[package]
name = "pycliparser"
version = "0.1.0"
edition = "2018"
[dependencies]
clidispatch = { path = "../../../../lib/clidispatch" }
cliparser = { path = "../../../../lib/cliparser", features = ["python"] }
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
pyconfigparser = { path = "../pyconfigparser" }

View File

@ -3,12 +3,12 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
use crate::configparser::config;
use clidispatch::global_flags::HgGlobalOpts;
use cliparser::alias::{expand_aliases, expand_prefix};
use cliparser::parser::*;
use cpython::*;
use cpython_ext::Bytes;
use pyconfigparser::config;
use std::collections::{BTreeMap, HashMap};
mod exceptions {

View File

@ -0,0 +1,10 @@
[package]
name = "pycommands"
version = "0.1.0"
edition = "2018"
[dependencies]
clidispatch = { path = "../../../../lib/clidispatch" }
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
hgcommands = { path = "../../../../lib/hgcommands" }

View File

@ -0,0 +1,11 @@
[package]
name = "pyconfigparser"
version = "0.1.0"
edition = "2018"
[dependencies]
bytes = "0.4.11"
configparser = { path = "../../../../lib/configparser" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
util = { path = "../../../../lib/util" }

View File

@ -0,0 +1,11 @@
[package]
name = "pydag"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
dag = { path = "../../../../lib/dag" }
encoding = { path = "../../../../lib/encoding" }
failure = "0.1.3"

View File

@ -0,0 +1,14 @@
[package]
name = "pyedenapi"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
edenapi = { path = "../../../../lib/edenapi" }
encoding = { path = "../../../../lib/encoding" }
failure = "0.1.3"
pyrevisionstore = { path = "../pyrevisionstore" }
revisionstore = { path = "../../../../lib/revisionstore" }
types = { path = "../../../../lib/types" }

View File

@ -13,11 +13,10 @@ use edenapi::{
ProgressStats,
};
use encoding::local_bytes_to_path;
use pyrevisionstore::{mutabledeltastore, mutablehistorystore};
use revisionstore::{MutableDeltaStore, MutableHistoryStore};
use types::{Key, Node, RepoPath, RepoPathBuf};
use crate::revisionstore::{mutabledeltastore, mutablehistorystore};
mod exceptions {
use super::*;

View File

@ -0,0 +1,10 @@
[package]
name = "pylz4"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
lz4-pyframe = { path = "../../../../lib/lz4-pyframe" }

View File

@ -0,0 +1,18 @@
[package]
name = "pymanifest"
version = "0.1.0"
edition = "2018"
[dependencies]
bytes = { version = "0.4.11" }
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
failure = "0.1.3"
manifest = { path = "../../../../lib/manifest" }
pathmatcher = { path = "../../../../lib/pathmatcher" }
pypathmatcher = { path = "../pypathmatcher" }
pyrevisionstore = { path = "../pyrevisionstore" }
revisionstore = { path = "../../../../lib/revisionstore" }
types = { path = "../../../../lib/types" }

View File

@ -3,6 +3,8 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
#![allow(non_camel_case_types)]
use std::{borrow::Borrow, cell::RefCell, ops::Deref, str, sync::Arc};
use bytes::Bytes;
@ -14,12 +16,11 @@ use cpython_failure::ResultPyErrExt;
use encoding::{local_bytes_to_repo_path, repo_path_to_local_bytes};
use manifest::{self, DiffType, FileMetadata, FileType, FsNode, Manifest};
use pathmatcher::{AlwaysMatcher, Matcher};
use pypathmatcher::PythonMatcher;
use pyrevisionstore::PythonDataStore;
use revisionstore::DataStore;
use types::{Key, Node, RepoPath, RepoPathBuf};
use crate::pathmatcher::PythonMatcher;
use crate::revisionstore::PythonDataStore;
struct ManifestStore<T> {
underlying: T,
}

View File

@ -0,0 +1,15 @@
[package]
name = "pymutationstore"
version = "0.1.0"
edition = "2018"
[dependencies]
byteorder = "1.2.7"
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
failure = "0.1.3"
mutationstore = { path = "../../../../lib/mutationstore" }
types = { path = "../../../../lib/types" }
vlqencoding = { path = "../../../../lib/vlqencoding" }

View File

@ -3,6 +3,8 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
#![allow(non_camel_case_types)]
use std::{cell::RefCell, io::Cursor};
use byteorder::{ReadBytesExt, WriteBytesExt};

View File

@ -0,0 +1,10 @@
[package]
name = "pynodemap"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
nodemap = { path = "../../../../lib/nodemap" }
types = { path = "../../../../lib/types" }

View File

@ -3,6 +3,8 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
#![allow(non_camel_case_types)]
use std::cell::RefCell;
use cpython::*;

View File

@ -0,0 +1,11 @@
[package]
name = "pypathmatcher"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
pathmatcher = { path = "../../../../lib/pathmatcher" }
types = { path = "../../../../lib/types" }

View File

@ -0,0 +1,11 @@
[package]
name = "pyrevisionstore"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
failure = "0.1"
revisionstore = { path = "../../../../lib/revisionstore" }
types = { path = "../../../../lib/types" }

View File

@ -12,7 +12,7 @@ use failure::Fallible;
use revisionstore::{DataStore, MutableDeltaStore, ToKeys};
use types::{Key, Node};
use crate::revisionstore::pythonutil::{
use crate::pythonutil::{
from_base, from_delta_to_tuple, from_key, from_key_to_tuple, from_tuple_to_key, to_delta,
to_key, to_metadata, to_pyerr,
};

View File

@ -12,7 +12,7 @@ use failure::Fallible;
use revisionstore::{HistoryStore, MutableHistoryStore, ToKeys};
use types::{Key, NodeInfo};
use crate::revisionstore::pythonutil::{
use crate::pythonutil::{
from_key, from_key_to_tuple, from_tuple_to_key, to_key, to_node, to_path, to_pyerr,
};

View File

@ -20,13 +20,11 @@ use revisionstore::{
};
use types::{Key, NodeInfo};
use crate::revisionstore::datastorepyext::{
DataStorePyExt, IterableDataStorePyExt, MutableDeltaStorePyExt,
};
use crate::revisionstore::historystorepyext::{
use crate::datastorepyext::{DataStorePyExt, IterableDataStorePyExt, MutableDeltaStorePyExt};
use crate::historystorepyext::{
HistoryStorePyExt, IterableHistoryStorePyExt, MutableHistoryStorePyExt,
};
use crate::revisionstore::pythonutil::to_pyerr;
use crate::pythonutil::to_pyerr;
mod datastorepyext;
mod historystorepyext;
@ -34,7 +32,7 @@ mod pyerror;
mod pythondatastore;
mod pythonutil;
pub use crate::revisionstore::pythondatastore::PythonDataStore;
pub use crate::pythondatastore::PythonDataStore;
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
let name = [package, "revisionstore"].join(".");

View File

@ -11,8 +11,8 @@ use failure::Fallible;
use revisionstore::{DataStore, Delta, LocalStore, Metadata};
use types::Key;
use crate::revisionstore::pyerror::pyerr_to_error;
use crate::revisionstore::pythonutil::{
use crate::pyerror::pyerr_to_error;
use crate::pythonutil::{
bytes_from_tuple, from_key_to_tuple, from_tuple_to_delta, from_tuple_to_key, to_key,
to_metadata,
};

View File

@ -15,7 +15,7 @@ use revisionstore::datastore::{Delta, Metadata};
use revisionstore::error::KeyError;
use types::{Key, Node, RepoPath, RepoPathBuf};
use crate::revisionstore::pyerror::pyerr_to_error;
use crate::pyerror::pyerr_to_error;
pub fn to_pyerr(py: Python, error: &Error) -> PyErr {
if let Some(io_error) = error.downcast_ref::<io::Error>() {

View File

@ -0,0 +1,8 @@
[package]
name = "pystackdesc"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
stackdesc = { path = "../../../../lib/stackdesc/" }

View File

@ -0,0 +1,11 @@
[package]
name = "pytreestate"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython-failure = { path = "../../../../lib/cpython-failure" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
encoding = { path = "../../../../lib/encoding" }
failure = "0.1"
treestate = { path = "../../../../lib/treestate" }

View File

@ -1,4 +1,7 @@
// Copyright Facebook, Inc. 2017
#![allow(non_camel_case_types)]
//! Python bindings for treedirstate and treestate.
//!
//! This is a Rust implementation of the dirstate concept for Mercurial, using a tree structure

View File

@ -0,0 +1,9 @@
[package]
name = "pyvlq"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
cpython-failure = { path = "../../../../lib/cpython-failure" }
vlqencoding = { path = "../../../../lib/vlqencoding" }

View File

@ -0,0 +1,10 @@
[package]
name = "pyzstd"
version = "0.1.0"
edition = "2018"
[dependencies]
cpython-ext = { path = "../../../../lib/cpython-ext" }
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
zstd = "0.4.18"
zstdelta = { path = "../../../../lib/zstdelta/" }

View File

@ -0,0 +1,45 @@
// Copyright Facebook, Inc. 2017
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
#![allow(non_camel_case_types)]
use cpython::py_module_initializer;
py_module_initializer!(bindings, initbindings, PyInit_bindings, |py, m| {
env_logger::init();
let name = m.get(py, "__name__")?.extract::<String>(py)?;
m.add(py, "__doc__", "Mercurial Rust Bindings")?;
m.add(py, "blackbox", pyblackbox::init_module(py, &name)?)?;
m.add(
py,
"bookmarkstore",
pybookmarkstore::init_module(py, &name)?,
)?;
m.add(py, "cliparser", pycliparser::init_module(py, &name)?)?;
m.add(py, "commands", pycommands::init_module(py, &name)?)?;
m.add(py, "configparser", pyconfigparser::init_module(py, &name)?)?;
m.add(py, "dag", pydag::init_module(py, &name)?)?;
m.add(py, "edenapi", pyedenapi::init_module(py, &name)?)?;
m.add(py, "lz4", pylz4::init_module(py, &name)?)?;
m.add(py, "manifest", pymanifest::init_module(py, &name)?)?;
m.add(
py,
"mutationstore",
pymutationstore::init_module(py, &name)?,
)?;
m.add(py, "nodemap", pynodemap::init_module(py, &name)?)?;
m.add(py, "pathmatcher", pypathmatcher::init_module(py, &name)?)?;
m.add(
py,
"revisionstore",
pyrevisionstore::init_module(py, &name)?,
)?;
m.add(py, "stackdesc", pystackdesc::init_module(py, &name)?)?;
m.add(py, "treestate", pytreestate::init_module(py, &name)?)?;
m.add(py, "vlq", pyvlq::init_module(py, &name)?)?;
m.add(py, "zstd", pyzstd::init_module(py, &name)?)?;
Ok(())
});

View File

@ -2056,7 +2056,7 @@ rustextmodules = [
RustExtension(
"bindings",
package="edenscmnative",
manifest="edenscm/mercurial/rust/bindings/Cargo.toml",
manifest="edenscmnative/bindings/Cargo.toml",
),
RustExtension(
"indexes",