Skip to content

Commit

Permalink
manifest: add count_files() to Manifest trait
Browse files Browse the repository at this point in the history
Summary:
add count_files() to Manifest trait, this is a bit faster than calling files()
function, then count the files.

Reviewed By: muirdm

Differential Revision: D69528661

fbshipit-source-id: 7eefe9299841740afad1c00c4e502d8aace62591
  • Loading branch information
zzl0 authored and facebook-github-bot committed Feb 12, 2025
1 parent ae521ed commit 4c21a25
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 5 deletions.
13 changes: 13 additions & 0 deletions eden/scm/lib/manifest-tree/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,19 @@ impl Manifest for TreeManifest {
Box::new(files)
}

#[tracing::instrument(skip_all)]
fn count_files<'a, M: 'static + Matcher + Sync + Send>(&'a self, matcher: M) -> Result<u64> {
// PERF: the `bfs_iter()` can be optimized to avoid file path construction.
bfs_iter(self.store.clone(), &[&self.root], matcher).try_fold(0, |acc, result| {
let (_, metadata) = result?;
if let FsNodeMetadata::File(_) = metadata {
Ok(acc + 1)
} else {
Ok(acc)
}
})
}

/// Returns an iterator over all the directories that are present in the
/// tree.
///
Expand Down
8 changes: 8 additions & 0 deletions eden/scm/lib/manifest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ pub trait Manifest {
matcher: M,
) -> Box<dyn Iterator<Item = Result<File>> + 'a>;

/// Returns the number of files in the Manifest that satisfy the given Matcher.
fn count_files<'a, M: 'static + Matcher + Sync + Send>(&'a self, matcher: M) -> Result<u64> {
self.files(matcher).try_fold(0, |acc, result| {
let _ = result?;
Ok(acc + 1)
})
}

/// Returns an iterator over all directories found in the paths of the files in the Manifest
/// that satisfy the given Matcher.
// TODO: add default implementation
Expand Down
2 changes: 1 addition & 1 deletion eden/scm/sapling/utils/subtreeutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ def validate_file_count(repo, ctx, paths):
mf = ctx.manifest()
for p in paths:
matcher = matchmod.match(repo.root, "", [f"path:{p}"])
count = mf.count(matcher)
count = mf.countfiles(matcher)
if count > max_file_count:
raise error.Abort(
_("subtree path '%s' includes too many files: %d (max: %d)")
Expand Down
8 changes: 4 additions & 4 deletions eden/scm/saplingnative/bindings/modules/pymanifest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,14 @@ py_class!(pub class treemanifest |py| {
}

/// Count the number of files that match the predicate passed to the function.
def count(&self, pymatcher: PyObject) -> PyResult<u64> {
// PERF: the `tree.files()` can be optimized to avoid file path construction.
def countfiles(&self, pymatcher: PyObject) -> PyResult<u64> {
let tree = self.underlying(py);
let matcher = extract_matcher(py, pymatcher)?.0;
let count = py.allow_threads(move || -> u64 {
let result = py.allow_threads(move || -> Result<u64> {
let tree = tree.read();
tree.files(matcher).fold(0, |acc, _f| acc + 1)
tree.count_files(matcher)
});
let count = result.map_pyerr(py)?;
Ok(count)
}

Expand Down

0 comments on commit 4c21a25

Please sign in to comment.