mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
sparse: add bindings for Rust sparse library
Summary: Add bindings the Python sparse extension can use to create treematchers representing the sparse profile. We return a list of treematchers and rule details instead of a single matcher because the sparse "explain" functionality only exists at the Python matcher level, so passing a single Rust matcher would lose that information. Reviewed By: quark-zju Differential Revision: D49928284 fbshipit-source-id: 828c931f4d6c1f17a43a506bee0e7b2227817900
This commit is contained in:
parent
82d1faa01d
commit
0078dd4c3c
@ -463,6 +463,10 @@ impl Matcher {
|
||||
|
||||
Ok((false, "no rules matched".to_string()))
|
||||
}
|
||||
|
||||
pub fn into_matchers(self) -> Vec<(TreeMatcher, Vec<String>)> {
|
||||
self.matchers.into_iter().zip(self.rule_origins).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl MatcherTrait for Matcher {
|
||||
|
@ -85,7 +85,7 @@ pub fn repo_matcher_with_overrides(
|
||||
Ok(Some((matcher, hasher.finish())))
|
||||
}
|
||||
|
||||
fn build_matcher(
|
||||
pub fn build_matcher(
|
||||
prof: &sparse::Root,
|
||||
manifest: impl Manifest + Send + Sync + 'static,
|
||||
store: Arc<dyn ReadFileContents<Error = anyhow::Error> + Send + Sync>,
|
||||
@ -180,7 +180,7 @@ pub fn config_overrides(config: impl Config) -> HashMap<String, String> {
|
||||
overrides
|
||||
}
|
||||
|
||||
fn disk_overrides(dot_path: &Path) -> anyhow::Result<HashMap<String, String>> {
|
||||
pub fn disk_overrides(dot_path: &Path) -> anyhow::Result<HashMap<String, String>> {
|
||||
match util::file::open(dot_path.join(CONFIG_OVERRIDE_CACHE), "r") {
|
||||
Ok(f) => Ok(serde_json::from_reader(f)?),
|
||||
Err(err) if err.kind() != std::io::ErrorKind::NotFound => Err(err.into()),
|
||||
|
@ -78,6 +78,7 @@ pub struct WorkingCopy {
|
||||
format: StorageFormat,
|
||||
treestate: Arc<Mutex<TreeState>>,
|
||||
tree_resolver: ArcReadTreeManifest,
|
||||
filestore: ArcReadFileContents,
|
||||
filesystem: Mutex<FileSystem>,
|
||||
ignore_matcher: Arc<GitignoreMatcher>,
|
||||
locker: Arc<RepoLocker>,
|
||||
@ -112,7 +113,7 @@ impl WorkingCopy {
|
||||
file_system_type,
|
||||
treestate.clone(),
|
||||
tree_resolver.clone(),
|
||||
filestore,
|
||||
filestore.clone(),
|
||||
locker.clone(),
|
||||
)?);
|
||||
|
||||
@ -131,6 +132,7 @@ impl WorkingCopy {
|
||||
ident,
|
||||
treestate,
|
||||
tree_resolver,
|
||||
filestore,
|
||||
filesystem,
|
||||
ignore_matcher,
|
||||
locker,
|
||||
@ -167,6 +169,14 @@ impl WorkingCopy {
|
||||
self.treestate.lock().set_parents(parents)
|
||||
}
|
||||
|
||||
pub fn filestore(&self) -> ArcReadFileContents {
|
||||
self.filestore.clone()
|
||||
}
|
||||
|
||||
pub fn tree_resolver(&self) -> ArcReadTreeManifest {
|
||||
self.tree_resolver.clone()
|
||||
}
|
||||
|
||||
pub(crate) fn current_manifests(
|
||||
treestate: &TreeState,
|
||||
tree_resolver: &ArcReadTreeManifest,
|
||||
|
@ -16,4 +16,7 @@ pyconfigloader = { version = "0.1.0", path = "../pyconfigloader" }
|
||||
pypathmatcher = { version = "0.1.0", path = "../pypathmatcher" }
|
||||
pystatus = { version = "0.1.0", path = "../pystatus" }
|
||||
pytreestate = { version = "0.1.0", path = "../pytreestate" }
|
||||
sparse = { version = "0.1.0", path = "../../../../lib/sparse" }
|
||||
types = { version = "0.1.0", path = "../../../../lib/types" }
|
||||
util = { version = "0.1.0", path = "../../../../lib/util" }
|
||||
workingcopy = { version = "0.1.0", path = "../../../../lib/workingcopy" }
|
||||
|
@ -17,6 +17,7 @@ use std::time::SystemTime;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Error;
|
||||
use cpython::*;
|
||||
use cpython_ext::convert::Serde;
|
||||
use cpython_ext::error::ResultPyErrExt;
|
||||
use cpython_ext::PyPathBuf;
|
||||
use io::IO;
|
||||
@ -25,10 +26,12 @@ use pathmatcher::Matcher;
|
||||
use pyconfigloader::config;
|
||||
use pypathmatcher::extract_matcher;
|
||||
use pypathmatcher::extract_option_matcher;
|
||||
use pypathmatcher::treematcher;
|
||||
use pytreestate::treestate;
|
||||
use rsworkingcopy::walker::WalkError;
|
||||
use rsworkingcopy::walker::Walker;
|
||||
use rsworkingcopy::workingcopy::WorkingCopy;
|
||||
use types::HgId;
|
||||
|
||||
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
|
||||
let name = [package, "workingcopy"].join(".");
|
||||
@ -117,6 +120,53 @@ py_class!(pub class workingcopy |py| {
|
||||
}).map_pyerr(py)?
|
||||
)
|
||||
}
|
||||
|
||||
// Fetch list of (treematcher, rule_details) to be unioned together.
|
||||
// rule_details drive the sparse "explain" functionality.
|
||||
def sparsematchers(
|
||||
&self,
|
||||
nodes: Serde<Vec<HgId>>,
|
||||
raw_config: Option<(String, String)>,
|
||||
debug_version: Option<String>,
|
||||
no_catch_all: bool,
|
||||
) -> PyResult<Vec<(treematcher, Vec<String>)>> {
|
||||
let wc = self.inner(py).read();
|
||||
|
||||
let mut prof = match raw_config {
|
||||
Some((contents, source)) => sparse::Root::from_bytes(contents.into_bytes(), source).map_pyerr(py)?,
|
||||
None => {
|
||||
let repo_sparse_path = wc.dot_hg_path().join("sparse");
|
||||
match util::file::read(&repo_sparse_path) {
|
||||
Ok(contents) => sparse::Root::from_bytes(contents, repo_sparse_path.display().to_string()).map_pyerr(py)?,
|
||||
Err(e) if e.is_not_found() => return Ok(Vec::new()),
|
||||
Err(e) => return Err(e).map_pyerr(py),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if debug_version.is_some() {
|
||||
prof.set_version_override(debug_version);
|
||||
}
|
||||
|
||||
prof.set_skip_catch_all(no_catch_all);
|
||||
|
||||
let overrides = rsworkingcopy::sparse::disk_overrides(wc.dot_hg_path()).map_pyerr(py)?;
|
||||
|
||||
let mut all_tree_matchers = Vec::new();
|
||||
for node in &*nodes {
|
||||
let mf = wc.tree_resolver().get(node).map_pyerr(py)?;
|
||||
let matcher = rsworkingcopy::sparse::build_matcher(&prof, mf.read().clone(), wc.filestore(), &overrides).map_pyerr(py)?.0;
|
||||
let tree_matchers = matcher.into_matchers();
|
||||
if tree_matchers.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
all_tree_matchers.extend(tree_matchers.into_iter());
|
||||
}
|
||||
all_tree_matchers
|
||||
.into_iter()
|
||||
.map(|(tm, origins)| Ok((treematcher::create_instance(py, Arc::new(tm))?, origins)))
|
||||
.collect::<PyResult<Vec<_>>>()
|
||||
}
|
||||
});
|
||||
|
||||
fn parse_git_submodules(py: Python, data: &PyBytes) -> PyResult<Vec<(String, String, String)>> {
|
||||
|
Loading…
Reference in New Issue
Block a user