// Produces a string like: "`foo`, `bar`, and `baz`" std::string cfg_pretty_print_root_files(const json_ref& root_files) { std::string result; for (unsigned int i = 0; i < root_files.array().size(); ++i) { const auto& r = root_files.array()[i]; if (i > 1 && i == root_files.array().size() - 1) { // We are last in a list of multiple items result.append(", and "); } else if (i > 0) { result.append(", "); } result.append("`"); result.append(json_string_value(r)); result.append("`"); } return result; }
bool w_cmd_realpath_root(json_ref& args, char** errmsg) { const char *path; if (json_array_size(args) < 2) { ignore_result(asprintf(errmsg, "wrong number of arguments")); return false; } path = json_string_value(json_array_get(args, 1)); if (!path) { ignore_result(asprintf(errmsg, "second argument must be a string")); return false; } try { auto resolved = realPath(path); args.array()[1] = w_string_to_json(resolved); return true; } catch (const std::exception &exc) { watchman::log(watchman::DBG, "w_cmd_realpath_root: path ", path, " does not resolve: ", exc.what(), "\n"); // We don't treat this as an error; the caller will subsequently // fail and perform their usual error handling return true; } }
static std::vector<w_string_piece> json_args_to_string_vec( const json_ref& args) { std::vector<w_string_piece> vec; for (auto& arg : args.array()) { vec.emplace_back(json_to_w_string(arg)); } return vec; }
static std::unique_ptr<QueryExpr> parse( w_query* query, const json_ref& term) { std::unique_ptr<w_clockspec> spec; auto selected_field = since_what::SINCE_OCLOCK; const char* fieldname = "oclock"; if (!json_is_array(term)) { query->errmsg = strdup("\"since\" term must be an array"); return nullptr; } if (json_array_size(term) < 2 || json_array_size(term) > 3) { query->errmsg = strdup("\"since\" term has invalid number of parameters"); return nullptr; } const auto& jval = term.at(1); spec = w_clockspec_parse(jval); if (!spec) { query->errmsg = strdup("invalid clockspec for \"since\" term"); return nullptr; } if (spec->tag == w_cs_named_cursor) { query->errmsg = strdup("named cursors are not allowed in \"since\" terms"); return nullptr; } if (term.array().size() == 3) { const auto& field = term.at(2); size_t i; bool valid = false; fieldname = json_string_value(field); if (!fieldname) { query->errmsg = strdup("field name for \"since\" term must be a string"); return nullptr; } for (i = 0; i < sizeof(allowed_fields) / sizeof(allowed_fields[0]); ++i) { if (!strcmp(allowed_fields[i].label, fieldname)) { selected_field = allowed_fields[i].value; valid = true; break; } } if (!valid) { ignore_result(asprintf( &query->errmsg, "invalid field name \"%s\" for \"since\" term", fieldname)); return nullptr; } } switch (selected_field) { case since_what::SINCE_CTIME: case since_what::SINCE_MTIME: if (spec->tag != w_cs_timestamp) { ignore_result(asprintf( &query->errmsg, "field \"%s\" requires a timestamp value " "for comparison in \"since\" term", fieldname)); return nullptr; } break; case since_what::SINCE_OCLOCK: case since_what::SINCE_CCLOCK: /* we'll work with clocks or timestamps */ break; } return watchman::make_unique<SinceExpr>(std::move(spec), selected_field); }