in src/rust/engine/fs/src/glob_matching.rs [115:202]
fn expand(&self, path_globs: PathGlobs) -> BoxFuture<Vec<PathStat>, E> {
let PathGlobs {
include,
exclude,
strict_match_behavior,
conjunction,
} = path_globs;
if include.is_empty() {
return future::ok(vec![]).to_boxed();
}
let result = Arc::new(Mutex::new(Vec::new()));
let mut sources = Vec::new();
let mut roots = Vec::new();
for pgie in include {
let source = Arc::new(pgie.input);
for path_glob in pgie.globs {
sources.push(source.clone());
roots.push(self.expand_single(result.clone(), exclude.clone(), path_glob));
}
}
future::join_all(roots)
.and_then(move |matched| {
if strict_match_behavior.should_check_glob_matches() {
// Get all the inputs which didn't transitively expand to any files.
let matching_inputs = sources
.iter()
.zip(matched.into_iter())
.filter_map(
|(source, matched)| {
if matched {
Some(source.clone())
} else {
None
}
},
)
.collect::<HashSet<_>>();
let non_matching_inputs = sources
.into_iter()
.filter(|s| !matching_inputs.contains(s))
.collect::<HashSet<_>>();
let match_failed = match conjunction {
// All must match.
GlobExpansionConjunction::AllMatch => !non_matching_inputs.is_empty(),
// Only one needs to match.
GlobExpansionConjunction::AnyMatch => matching_inputs.is_empty(),
};
if match_failed {
// TODO(#5684): explain what global and/or target-specific option to set to
// modify this behavior!
let mut non_matching_inputs = non_matching_inputs
.iter()
.map(|parsed_source| parsed_source.0.clone())
.collect::<Vec<_>>();
non_matching_inputs.sort();
let msg = format!(
"Globs did not match. Excludes were: {:?}. Unmatched globs were: {:?}.",
exclude.exclude_patterns(),
non_matching_inputs,
);
if strict_match_behavior.should_throw_on_error() {
return future::err(Self::mk_error(&msg));
} else {
// TODO(#5683): this doesn't have any useful context (the stack trace) without
// being thrown -- this needs to be provided, otherwise this is far less useful.
warn!("{}", msg);
}
}
}
let mut path_stats = Arc::try_unwrap(result)
.unwrap_or_else(|_| panic!("expand violated its contract."))
.into_inner()
.into_iter()
.collect::<Vec<_>>();
path_stats.sort_by(|a, b| a.path().cmp(b.path()));
path_stats.dedup_by(|a, b| a.path() == b.path());
future::ok(path_stats)
})
.to_boxed()
}