in watchman/InMemoryView.cpp [778:878]
void InMemoryView::globGeneratorTree(
QueryContext* ctx,
const GlobTree* node,
const struct watchman_dir* dir) const {
if (!node->doublestar_children.empty()) {
globGeneratorDoublestar(ctx, dir, node, nullptr, 0);
}
for (const auto& child_node : node->children) {
w_assert(!child_node->is_doublestar, "should not get here with ** glob");
// If there are child dirs, consider them for recursion.
// Note that we don't restrict this to !leaf because the user may have
// set their globs list to something like ["some_dir", "some_dir/file"]
// and we don't want to preclude matching the latter.
if (!dir->dirs.empty()) {
// Attempt direct lookup if possible
if (!child_node->had_specials &&
ctx->query->case_sensitive == CaseSensitivity::CaseSensitive) {
w_string_piece component(
child_node->pattern.data(), child_node->pattern.size());
const auto child_dir = dir->getChildDir(component);
if (child_dir) {
globGeneratorTree(ctx, child_node.get(), child_dir);
}
} else {
// Otherwise we have to walk and match
for (auto& it : dir->dirs) {
const auto child_dir = it.second.get();
if (!child_dir->last_check_existed) {
// Globs can only match files in dirs that exist
continue;
}
if (wildmatch(
child_node->pattern.c_str(),
child_dir->name.c_str(),
ctx->query->glob_flags |
(ctx->query->case_sensitive ==
CaseSensitivity::CaseSensitive
? 0
: WM_CASEFOLD),
0) == WM_MATCH) {
globGeneratorTree(ctx, child_node.get(), child_dir);
}
}
}
}
// If the node is a leaf we are in a position to match files.
if (child_node->is_leaf && !dir->files.empty()) {
// Attempt direct lookup if possible
if (!child_node->had_specials &&
ctx->query->case_sensitive == CaseSensitivity::CaseSensitive) {
w_string_piece component(
child_node->pattern.data(), child_node->pattern.size());
auto file = dir->getChildFile(component);
if (file) {
ctx->bumpNumWalked();
if (file->exists) {
// Globs can only match files that exist
w_query_process_file(
ctx->query,
ctx,
std::make_unique<InMemoryFileResult>(file, caches_));
}
}
} else {
for (auto& it : dir->files) {
// Otherwise we have to walk and match
auto file = it.second.get();
auto file_name = file->getName();
ctx->bumpNumWalked();
if (!file->exists) {
// Globs can only match files that exist
continue;
}
if (wildmatch(
child_node->pattern.c_str(),
file_name.data(),
ctx->query->glob_flags |
(ctx->query->case_sensitive ==
CaseSensitivity::CaseSensitive
? 0
: WM_CASEFOLD),
0) == WM_MATCH) {
w_query_process_file(
ctx->query,
ctx,
std::make_unique<InMemoryFileResult>(file, caches_));
}
}
}
}
}
}