static bool dir_generator( w_query *query, w_root_t *root, struct w_query_ctx *ctx, struct watchman_dir *dir, uint32_t depth) { w_ht_iter_t i; if (w_ht_first(dir->files, &i)) do { struct watchman_file *file = w_ht_val_ptr(i.value); if (!w_query_process_file(query, ctx, file)) { return false; } } while (w_ht_next(dir->files, &i)); if (depth > 0 && w_ht_first(dir->dirs, &i)) do { struct watchman_dir *child = w_ht_val_ptr(i.value); if (!dir_generator(query, root, ctx, child, depth - 1)) { return false; } } while (w_ht_next(dir->dirs, &i)); return true; }
static bool dir_generator( w_query *query, w_root_t *root, struct w_query_ctx *ctx, struct watchman_dir *dir, uint32_t depth, int64_t *num_walked) { w_ht_iter_t i; int64_t n = 0; bool result = true; if (w_ht_first(dir->files, &i)) do { struct watchman_file *file = w_ht_val_ptr(i.value); ++n; if (!w_query_process_file(query, ctx, file)) { result = false; goto done; } } while (w_ht_next(dir->files, &i)); if (depth > 0 && w_ht_first(dir->dirs, &i)) do { struct watchman_dir *child = w_ht_val_ptr(i.value); int64_t child_walked = 0; result = dir_generator(query, root, ctx, child, depth - 1, &child_walked); n += child_walked; if (!result) { goto done; } } while (w_ht_next(dir->dirs, &i)); done: *num_walked = n; return result; }
static bool path_generator( w_query *query, w_root_t *root, struct w_query_ctx *ctx) { struct watchman_file *f; uint32_t i; for (i = 0; i < query->npaths; i++) { struct watchman_dir *dir; w_string_t *dir_name, *file_name, *full_name; // Compose path with root full_name = w_string_path_cat(root->root_path, query->paths[i].name); // special case of root dir itself if (w_string_equal(root->root_path, full_name)) { // dirname on the root is outside the root, which is useless dir = w_root_resolve_dir(root, full_name, false); goto is_dir; } // Ideally, we'd just resolve it directly as a dir and be done. // It's not quite so simple though, because we may resolve a dir // that had been deleted and replaced by a file. // We prefer to resolve the parent and walk down. dir_name = w_string_dirname(full_name); if (!dir_name) { w_string_delref(full_name); continue; } dir = w_root_resolve_dir(root, dir_name, false); w_string_delref(dir_name); if (!dir) { // Doesn't exist, and never has w_string_delref(full_name); continue; } if (dir->files) { file_name = w_string_basename(query->paths[i].name); f = w_ht_val_ptr(w_ht_get(dir->files, w_ht_ptr_val(file_name))); w_string_delref(file_name); // If it's a file (but not an existent dir) if (f && (!f->exists || !S_ISDIR(f->st.st_mode))) { w_string_delref(full_name); if (!w_query_process_file(query, ctx, f)) { return false; } continue; } } // Is it a dir? dir = w_ht_val_ptr(w_ht_get(dir->dirs, w_ht_ptr_val(full_name))); w_string_delref(full_name); is_dir: // We got a dir; process recursively to specified depth if (dir && !dir_generator(query, root, ctx, dir, query->paths[i].depth)) { return false; } } return true; }