# HG changeset patch # User Arseniy Alekseyev # Date 1638194867 0 # Node ID 6d4daf51283cd5b628116a46fbbf634852edfd21 # Parent 2009e3c64a539fa965e2aa6de5b1ac3c5c6d3071 rhg: implement the debugignorerhg subcommand This can be used to inspect the generated pattern, but also to benchmark the time it takes to parse hgignore. Differential Revision: https://phab.mercurial-scm.org/D11722 diff -r 2009e3c64a53 -r 6d4daf51283c rust/hg-core/src/matchers.rs --- a/rust/hg-core/src/matchers.rs Mon Nov 29 14:06:41 2021 +0000 +++ b/rust/hg-core/src/matchers.rs Mon Nov 29 14:07:47 2021 +0000 @@ -561,11 +561,11 @@ /// Parses all "ignore" files with their recursive includes and returns a /// function that checks whether a given file (in the general sense) should be /// ignored. -pub fn get_ignore_function<'a>( +pub fn get_ignore_matcher<'a>( mut all_pattern_files: Vec, root_dir: &Path, inspect_pattern_bytes: &mut impl FnMut(&[u8]), -) -> PatternResult<(IgnoreFnType<'a>, Vec)> { +) -> PatternResult<(IncludeMatcher<'a>, Vec)> { let mut all_patterns = vec![]; let mut all_warnings = vec![]; @@ -588,10 +588,25 @@ all_warnings.extend(warnings); } let matcher = IncludeMatcher::new(all_patterns)?; - Ok(( - Box::new(move |path: &HgPath| matcher.matches(path)), - all_warnings, - )) + Ok((matcher, all_warnings)) +} + +/// Parses all "ignore" files with their recursive includes and returns a +/// function that checks whether a given file (in the general sense) should be +/// ignored. +pub fn get_ignore_function<'a>( + all_pattern_files: Vec, + root_dir: &Path, + inspect_pattern_bytes: &mut impl FnMut(&[u8]), +) -> PatternResult<(IgnoreFnType<'a>, Vec)> { + let res = + get_ignore_matcher(all_pattern_files, root_dir, inspect_pattern_bytes); + res.map(|(matcher, all_warnings)| { + let res: IgnoreFnType<'a> = + Box::new(move |path: &HgPath| matcher.matches(path)); + + (res, all_warnings) + }) } impl<'a> IncludeMatcher<'a> { @@ -626,6 +641,10 @@ .chain(self.parents.iter()); DirsChildrenMultiset::new(thing, Some(&self.parents)) } + + pub fn debug_get_patterns(&self) -> &[u8] { + self.patterns.as_ref() + } } impl<'a> Display for IncludeMatcher<'a> { diff -r 2009e3c64a53 -r 6d4daf51283c rust/rhg/src/commands/debugignorerhg.rs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/rhg/src/commands/debugignorerhg.rs Mon Nov 29 14:07:47 2021 +0000 @@ -0,0 +1,40 @@ +use crate::error::CommandError; +use clap::SubCommand; +use hg; +use hg::matchers::get_ignore_matcher; +use hg::StatusError; +use log::warn; + +pub const HELP_TEXT: &str = " +Show effective hgignore patterns used by rhg. + +This is a pure Rust version of `hg debugignore`. + +Some options might be missing, check the list below. +"; + +pub fn args() -> clap::App<'static, 'static> { + SubCommand::with_name("debugignorerhg").about(HELP_TEXT) +} + +pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { + let repo = invocation.repo?; + + let ignore_file = repo.working_directory_vfs().join(".hgignore"); // TODO hardcoded + + let (ignore_matcher, warnings) = get_ignore_matcher( + vec![ignore_file], + &repo.working_directory_path().to_owned(), + &mut |_pattern_bytes| (), + ) + .map_err(|e| StatusError::from(e))?; + + if !warnings.is_empty() { + warn!("Pattern warnings: {:?}", &warnings); + } + + let patterns = ignore_matcher.debug_get_patterns(); + invocation.ui.write_stdout(patterns)?; + invocation.ui.write_stdout(b"\n")?; + Ok(()) +} diff -r 2009e3c64a53 -r 6d4daf51283c rust/rhg/src/main.rs --- a/rust/rhg/src/main.rs Mon Nov 29 14:06:41 2021 +0000 +++ b/rust/rhg/src/main.rs Mon Nov 29 14:07:47 2021 +0000 @@ -480,6 +480,7 @@ cat debugdata debugrequirements + debugignorerhg files root config