file_source/
paths_provider.rs1use std::path::PathBuf;
4
5use file_source_common::internal_events::FileSourceInternalEvents;
6pub use glob::MatchOptions;
7use glob::Pattern;
8
9pub trait PathsProvider {
27 type IntoIter: IntoIterator<Item = PathBuf>;
29
30 fn paths(&self) -> Self::IntoIter;
32}
33
34pub struct Glob<E: FileSourceInternalEvents> {
39 include_patterns: Vec<String>,
40 exclude_patterns: Vec<Pattern>,
41 glob_match_options: MatchOptions,
42 emitter: E,
43}
44
45impl<E: FileSourceInternalEvents> Glob<E> {
46 pub fn new(
50 include_patterns: &[PathBuf],
51 exclude_patterns: &[PathBuf],
52 glob_match_options: MatchOptions,
53 emitter: E,
54 ) -> Option<Self> {
55 let include_patterns = include_patterns
56 .iter()
57 .map(|path| path.to_str().map(ToOwned::to_owned))
58 .collect::<Option<_>>()?;
59
60 let exclude_patterns = exclude_patterns
61 .iter()
62 .filter_map(|path| path.to_str().map(|path| Pattern::new(path).ok()))
63 .collect::<Option<Vec<_>>>()?;
64
65 Some(Self {
66 include_patterns,
67 exclude_patterns,
68 glob_match_options,
69 emitter,
70 })
71 }
72}
73
74impl<E: FileSourceInternalEvents> PathsProvider for Glob<E> {
75 type IntoIter = Vec<PathBuf>;
76
77 fn paths(&self) -> Self::IntoIter {
78 self.include_patterns
79 .iter()
80 .flat_map(|include_pattern| {
81 glob::glob_with(include_pattern.as_str(), self.glob_match_options)
82 .expect("failed to read glob pattern")
83 .filter_map(|val| {
84 val.map_err(|error| {
85 self.emitter
86 .emit_path_globbing_failed(error.path(), error.error())
87 })
88 .ok()
89 })
90 })
91 .filter(|candidate_path: &PathBuf| -> bool {
92 !self.exclude_patterns.iter().any(|exclude_pattern| {
93 let candidate_path_str = candidate_path.to_str().unwrap();
94 exclude_pattern.matches(candidate_path_str)
95 })
96 })
97 .collect()
98 }
99}