mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-01-19 05:49:14 +02:00
ripgrep: use 'ignore' for skipping stdout
This removes ripgrep-specific code for filtering files that correspond to stdout and instead uses the 'ignore' crate's functionality for doing the same.
This commit is contained in:
parent
e5bb750995
commit
87b745454d
27
src/args.rs
27
src/args.rs
@ -308,9 +308,7 @@ impl Args {
|
|||||||
/// file or a stream such as stdin.
|
/// file or a stream such as stdin.
|
||||||
pub fn subject_builder(&self) -> SubjectBuilder {
|
pub fn subject_builder(&self) -> SubjectBuilder {
|
||||||
let mut builder = SubjectBuilder::new();
|
let mut builder = SubjectBuilder::new();
|
||||||
builder
|
builder.strip_dot_prefix(self.using_default_path());
|
||||||
.strip_dot_prefix(self.using_default_path())
|
|
||||||
.skip(self.matches().stdout_handle());
|
|
||||||
builder
|
builder
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,6 +777,7 @@ impl ArgMatches {
|
|||||||
.max_filesize(self.max_file_size()?)
|
.max_filesize(self.max_file_size()?)
|
||||||
.threads(self.threads()?)
|
.threads(self.threads()?)
|
||||||
.same_file_system(self.is_present("one-file-system"))
|
.same_file_system(self.is_present("one-file-system"))
|
||||||
|
.skip_stdout(true)
|
||||||
.overrides(self.overrides()?)
|
.overrides(self.overrides()?)
|
||||||
.types(self.types()?)
|
.types(self.types()?)
|
||||||
.hidden(!self.hidden())
|
.hidden(!self.hidden())
|
||||||
@ -1375,28 +1374,6 @@ impl ArgMatches {
|
|||||||
self.output_kind() == OutputKind::JSON || self.is_present("stats")
|
self.output_kind() == OutputKind::JSON || self.is_present("stats")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a handle to stdout for filtering search.
|
|
||||||
///
|
|
||||||
/// A handle is returned if and only if ripgrep's stdout is being
|
|
||||||
/// redirected to a file. The handle returned corresponds to that file.
|
|
||||||
///
|
|
||||||
/// This can be used to ensure that we do not attempt to search a file
|
|
||||||
/// that ripgrep is writing to.
|
|
||||||
fn stdout_handle(&self) -> Option<Handle> {
|
|
||||||
let h = match Handle::stdout() {
|
|
||||||
Err(_) => return None,
|
|
||||||
Ok(h) => h,
|
|
||||||
};
|
|
||||||
let md = match h.as_file().metadata() {
|
|
||||||
Err(_) => return None,
|
|
||||||
Ok(md) => md,
|
|
||||||
};
|
|
||||||
if !md.is_file() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(h)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// When the output format is `Summary`, this returns the type of summary
|
/// When the output format is `Summary`, this returns the type of summary
|
||||||
/// output to show.
|
/// output to show.
|
||||||
///
|
///
|
||||||
|
@ -1,26 +1,17 @@
|
|||||||
use std::io;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use ignore::{self, DirEntry};
|
use ignore::{self, DirEntry};
|
||||||
use same_file::Handle;
|
|
||||||
|
|
||||||
/// A configuration for describing how subjects should be built.
|
/// A configuration for describing how subjects should be built.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Config {
|
struct Config {
|
||||||
skip: Option<Arc<Handle>>,
|
|
||||||
strip_dot_prefix: bool,
|
strip_dot_prefix: bool,
|
||||||
separator: Option<u8>,
|
|
||||||
terminator: Option<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Config {
|
fn default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
skip: None,
|
|
||||||
strip_dot_prefix: false,
|
strip_dot_prefix: false,
|
||||||
separator: None,
|
|
||||||
terminator: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,26 +62,6 @@ impl SubjectBuilder {
|
|||||||
if subj.dent.is_stdin() {
|
if subj.dent.is_stdin() {
|
||||||
return Some(subj);
|
return Some(subj);
|
||||||
}
|
}
|
||||||
// If we're supposed to skip a particular file, then skip it.
|
|
||||||
if let Some(ref handle) = self.config.skip {
|
|
||||||
match subj.equals(handle) {
|
|
||||||
Ok(false) => {} // fallthrough
|
|
||||||
Ok(true) => {
|
|
||||||
debug!(
|
|
||||||
"ignoring {}: (probably same file as stdout)",
|
|
||||||
subj.dent.path().display()
|
|
||||||
);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
debug!(
|
|
||||||
"ignoring {}: got error: {}",
|
|
||||||
subj.dent.path().display(), err
|
|
||||||
);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If this subject has a depth of 0, then it was provided explicitly
|
// If this subject has a depth of 0, then it was provided explicitly
|
||||||
// by an end user (or via a shell glob). In this case, we always want
|
// by an end user (or via a shell glob). In this case, we always want
|
||||||
// to search it if it even smells like a file (e.g., a symlink).
|
// to search it if it even smells like a file (e.g., a symlink).
|
||||||
@ -119,22 +90,6 @@ impl SubjectBuilder {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When provided, subjects that represent the same file as the handle
|
|
||||||
/// given will be skipped.
|
|
||||||
///
|
|
||||||
/// Typically, it is useful to pass a handle referring to stdout, such
|
|
||||||
/// that the file being written to isn't searched, which can lead to
|
|
||||||
/// an unbounded feedback mechanism.
|
|
||||||
///
|
|
||||||
/// Only one handle to skip can be provided.
|
|
||||||
pub fn skip(
|
|
||||||
&mut self,
|
|
||||||
handle: Option<Handle>,
|
|
||||||
) -> &mut SubjectBuilder {
|
|
||||||
self.config.skip = handle.map(Arc::new);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// When enabled, if the subject's file path starts with `./` then it is
|
/// When enabled, if the subject's file path starts with `./` then it is
|
||||||
/// stripped.
|
/// stripped.
|
||||||
///
|
///
|
||||||
@ -180,26 +135,4 @@ impl Subject {
|
|||||||
fn is_file(&self) -> bool {
|
fn is_file(&self) -> bool {
|
||||||
self.dent.file_type().map_or(false, |ft| ft.is_file())
|
self.dent.file_type().map_or(false, |ft| ft.is_file())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if and only if this subject is believed to be equivalent
|
|
||||||
/// to the given handle. If there was a problem querying this subject for
|
|
||||||
/// information to determine equality, then that error is returned.
|
|
||||||
fn equals(&self, handle: &Handle) -> io::Result<bool> {
|
|
||||||
#[cfg(unix)]
|
|
||||||
fn never_equal(dent: &DirEntry, handle: &Handle) -> bool {
|
|
||||||
dent.ino() != Some(handle.ino())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
fn never_equal(_: &DirEntry, _: &Handle) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we know for sure that these two things aren't equal, then avoid
|
|
||||||
// the costly extra stat call to determine equality.
|
|
||||||
if self.dent.is_stdin() || never_equal(&self.dent, handle) {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
Handle::from_path(self.path()).map(|h| &h == handle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user