search.rs (ripgrep-12.1.1) | : | search.rs (ripgrep-13.0.0) | ||
---|---|---|---|---|
skipping to change at line 118 | skipping to change at line 118 | |||
} | } | |||
/// Set the path to a preprocessor command. | /// Set the path to a preprocessor command. | |||
/// | /// | |||
/// When this is set, instead of searching files directly, the given | /// When this is set, instead of searching files directly, the given | |||
/// command will be run with the file path as the first argument, and the | /// command will be run with the file path as the first argument, and the | |||
/// output of that command will be searched instead. | /// output of that command will be searched instead. | |||
pub fn preprocessor( | pub fn preprocessor( | |||
&mut self, | &mut self, | |||
cmd: Option<PathBuf>, | cmd: Option<PathBuf>, | |||
) -> &mut SearchWorkerBuilder { | ) -> crate::Result<&mut SearchWorkerBuilder> { | |||
self.config.preprocessor = cmd; | if let Some(ref prog) = cmd { | |||
self | let bin = cli::resolve_binary(prog)?; | |||
self.config.preprocessor = Some(bin); | ||||
} else { | ||||
self.config.preprocessor = None; | ||||
} | ||||
Ok(self) | ||||
} | } | |||
/// Set the globs for determining which files should be run through the | /// Set the globs for determining which files should be run through the | |||
/// preprocessor. By default, with no globs and a preprocessor specified, | /// preprocessor. By default, with no globs and a preprocessor specified, | |||
/// every file is run through the preprocessor. | /// every file is run through the preprocessor. | |||
pub fn preprocessor_globs( | pub fn preprocessor_globs( | |||
&mut self, | &mut self, | |||
globs: Override, | globs: Override, | |||
) -> &mut SearchWorkerBuilder { | ) -> &mut SearchWorkerBuilder { | |||
self.config.preprocessor_globs = globs; | self.config.preprocessor_globs = globs; | |||
skipping to change at line 328 | skipping to change at line 333 | |||
} | } | |||
impl<W: WriteColor> SearchWorker<W> { | impl<W: WriteColor> SearchWorker<W> { | |||
/// Execute a search over the given subject. | /// Execute a search over the given subject. | |||
pub fn search(&mut self, subject: &Subject) -> io::Result<SearchResult> { | pub fn search(&mut self, subject: &Subject) -> io::Result<SearchResult> { | |||
let bin = if subject.is_explicit() { | let bin = if subject.is_explicit() { | |||
self.config.binary_explicit.clone() | self.config.binary_explicit.clone() | |||
} else { | } else { | |||
self.config.binary_implicit.clone() | self.config.binary_implicit.clone() | |||
}; | }; | |||
self.searcher.set_binary_detection(bin); | ||||
let path = subject.path(); | let path = subject.path(); | |||
log::trace!("{}: binary detection: {:?}", path.display(), bin); | ||||
self.searcher.set_binary_detection(bin); | ||||
if subject.is_stdin() { | if subject.is_stdin() { | |||
self.search_reader(path, io::stdin().lock()) | self.search_reader(path, &mut io::stdin().lock()) | |||
} else if self.should_preprocess(path) { | } else if self.should_preprocess(path) { | |||
self.search_preprocessor(path) | self.search_preprocessor(path) | |||
} else if self.should_decompress(path) { | } else if self.should_decompress(path) { | |||
self.search_decompress(path) | self.search_decompress(path) | |||
} else { | } else { | |||
self.search_path(path) | self.search_path(path) | |||
} | } | |||
} | } | |||
/// Return a mutable reference to the underlying printer. | /// Return a mutable reference to the underlying printer. | |||
skipping to change at line 396 | skipping to change at line 402 | |||
/// Search the given file path by first asking the preprocessor for the | /// Search the given file path by first asking the preprocessor for the | |||
/// data to search instead of opening the path directly. | /// data to search instead of opening the path directly. | |||
fn search_preprocessor( | fn search_preprocessor( | |||
&mut self, | &mut self, | |||
path: &Path, | path: &Path, | |||
) -> io::Result<SearchResult> { | ) -> io::Result<SearchResult> { | |||
let bin = self.config.preprocessor.as_ref().unwrap(); | let bin = self.config.preprocessor.as_ref().unwrap(); | |||
let mut cmd = Command::new(bin); | let mut cmd = Command::new(bin); | |||
cmd.arg(path).stdin(Stdio::from(File::open(path)?)); | cmd.arg(path).stdin(Stdio::from(File::open(path)?)); | |||
let rdr = self.command_builder.build(&mut cmd).map_err(|err| { | let mut rdr = self.command_builder.build(&mut cmd).map_err(|err| { | |||
io::Error::new( | io::Error::new( | |||
io::ErrorKind::Other, | io::ErrorKind::Other, | |||
format!( | format!( | |||
"preprocessor command could not start: '{:?}': {}", | "preprocessor command could not start: '{:?}': {}", | |||
cmd, err, | cmd, err, | |||
), | ), | |||
) | ) | |||
})?; | })?; | |||
self.search_reader(path, rdr).map_err(|err| { | let result = self.search_reader(path, &mut rdr).map_err(|err| { | |||
io::Error::new( | io::Error::new( | |||
io::ErrorKind::Other, | io::ErrorKind::Other, | |||
format!("preprocessor command failed: '{:?}': {}", cmd, err), | format!("preprocessor command failed: '{:?}': {}", cmd, err), | |||
) | ) | |||
}) | }); | |||
let close_result = rdr.close(); | ||||
let search_result = result?; | ||||
close_result?; | ||||
Ok(search_result) | ||||
} | } | |||
/// Attempt to decompress the data at the given file path and search the | /// Attempt to decompress the data at the given file path and search the | |||
/// result. If the given file path isn't recognized as a compressed file, | /// result. If the given file path isn't recognized as a compressed file, | |||
/// then search it without doing any decompression. | /// then search it without doing any decompression. | |||
fn search_decompress(&mut self, path: &Path) -> io::Result<SearchResult> { | fn search_decompress(&mut self, path: &Path) -> io::Result<SearchResult> { | |||
let rdr = self.decomp_builder.build(path)?; | let mut rdr = self.decomp_builder.build(path)?; | |||
self.search_reader(path, rdr) | let result = self.search_reader(path, &mut rdr); | |||
let close_result = rdr.close(); | ||||
let search_result = result?; | ||||
close_result?; | ||||
Ok(search_result) | ||||
} | } | |||
/// Search the contents of the given file path. | /// Search the contents of the given file path. | |||
fn search_path(&mut self, path: &Path) -> io::Result<SearchResult> { | fn search_path(&mut self, path: &Path) -> io::Result<SearchResult> { | |||
use self::PatternMatcher::*; | use self::PatternMatcher::*; | |||
let (searcher, printer) = (&mut self.searcher, &mut self.printer); | let (searcher, printer) = (&mut self.searcher, &mut self.printer); | |||
match self.matcher { | match self.matcher { | |||
RustRegex(ref m) => search_path(m, searcher, printer, path), | RustRegex(ref m) => search_path(m, searcher, printer, path), | |||
#[cfg(feature = "pcre2")] | #[cfg(feature = "pcre2")] | |||
skipping to change at line 445 | skipping to change at line 459 | |||
/// may actually cause something else to be searched (for example, when | /// may actually cause something else to be searched (for example, when | |||
/// a preprocessor is set or when decompression is enabled). In those | /// a preprocessor is set or when decompression is enabled). In those | |||
/// cases, the file path is used for visual purposes only. | /// cases, the file path is used for visual purposes only. | |||
/// | /// | |||
/// Generally speaking, this method should only be used when there is no | /// Generally speaking, this method should only be used when there is no | |||
/// other choice. Searching via `search_path` provides more opportunities | /// other choice. Searching via `search_path` provides more opportunities | |||
/// for optimizations (such as memory maps). | /// for optimizations (such as memory maps). | |||
fn search_reader<R: io::Read>( | fn search_reader<R: io::Read>( | |||
&mut self, | &mut self, | |||
path: &Path, | path: &Path, | |||
rdr: R, | rdr: &mut R, | |||
) -> io::Result<SearchResult> { | ) -> io::Result<SearchResult> { | |||
use self::PatternMatcher::*; | use self::PatternMatcher::*; | |||
let (searcher, printer) = (&mut self.searcher, &mut self.printer); | let (searcher, printer) = (&mut self.searcher, &mut self.printer); | |||
match self.matcher { | match self.matcher { | |||
RustRegex(ref m) => search_reader(m, searcher, printer, path, rdr), | RustRegex(ref m) => search_reader(m, searcher, printer, path, rdr), | |||
#[cfg(feature = "pcre2")] | #[cfg(feature = "pcre2")] | |||
PCRE2(ref m) => search_reader(m, searcher, printer, path, rdr), | PCRE2(ref m) => search_reader(m, searcher, printer, path, rdr), | |||
} | } | |||
} | } | |||
skipping to change at line 501 | skipping to change at line 515 | |||
} | } | |||
} | } | |||
/// Search the contents of the given reader using the given matcher, searcher | /// Search the contents of the given reader using the given matcher, searcher | |||
/// and printer. | /// and printer. | |||
fn search_reader<M: Matcher, R: io::Read, W: WriteColor>( | fn search_reader<M: Matcher, R: io::Read, W: WriteColor>( | |||
matcher: M, | matcher: M, | |||
searcher: &mut Searcher, | searcher: &mut Searcher, | |||
printer: &mut Printer<W>, | printer: &mut Printer<W>, | |||
path: &Path, | path: &Path, | |||
rdr: R, | mut rdr: R, | |||
) -> io::Result<SearchResult> { | ) -> io::Result<SearchResult> { | |||
match *printer { | match *printer { | |||
Printer::Standard(ref mut p) => { | Printer::Standard(ref mut p) => { | |||
let mut sink = p.sink_with_path(&matcher, path); | let mut sink = p.sink_with_path(&matcher, path); | |||
searcher.search_reader(&matcher, rdr, &mut sink)?; | searcher.search_reader(&matcher, &mut rdr, &mut sink)?; | |||
Ok(SearchResult { | Ok(SearchResult { | |||
has_match: sink.has_match(), | has_match: sink.has_match(), | |||
stats: sink.stats().map(|s| s.clone()), | stats: sink.stats().map(|s| s.clone()), | |||
}) | }) | |||
} | } | |||
Printer::Summary(ref mut p) => { | Printer::Summary(ref mut p) => { | |||
let mut sink = p.sink_with_path(&matcher, path); | let mut sink = p.sink_with_path(&matcher, path); | |||
searcher.search_reader(&matcher, rdr, &mut sink)?; | searcher.search_reader(&matcher, &mut rdr, &mut sink)?; | |||
Ok(SearchResult { | Ok(SearchResult { | |||
has_match: sink.has_match(), | has_match: sink.has_match(), | |||
stats: sink.stats().map(|s| s.clone()), | stats: sink.stats().map(|s| s.clone()), | |||
}) | }) | |||
} | } | |||
Printer::JSON(ref mut p) => { | Printer::JSON(ref mut p) => { | |||
let mut sink = p.sink_with_path(&matcher, path); | let mut sink = p.sink_with_path(&matcher, path); | |||
searcher.search_reader(&matcher, rdr, &mut sink)?; | searcher.search_reader(&matcher, &mut rdr, &mut sink)?; | |||
Ok(SearchResult { | Ok(SearchResult { | |||
has_match: sink.has_match(), | has_match: sink.has_match(), | |||
stats: Some(sink.stats().clone()), | stats: Some(sink.stats().clone()), | |||
}) | }) | |||
} | } | |||
} | } | |||
} | } | |||
/// Return the given duration as fractional seconds. | /// Return the given duration as fractional seconds. | |||
fn fractional_seconds(duration: Duration) -> f64 { | fn fractional_seconds(duration: Duration) -> f64 { | |||
End of changes. 13 change blocks. | ||||
16 lines changed or deleted | 30 lines changed or added |