Пример #1
0
static void parse_suffixes(w_query* res, const json_ref& query) {
  size_t i;

  auto suffixes = query.get_default("suffix");
  if (!suffixes) {
    return;
  }

  if (suffixes.isString()) {
    auto suff = parse_suffix(suffixes);
    res->suffixes.emplace_back(std::move(suff));
    return;
  }

  if (!suffixes.isArray()) {
    throw QueryParseError("'suffix' must be a string or an array of strings");
  }

  res->suffixes.reserve(json_array_size(suffixes));

  for (i = 0; i < json_array_size(suffixes); i++) {
    const auto& ele = suffixes.at(i);

    if (!ele.isString()) {
      throw QueryParseError("'suffix' must be a string or an array of strings");
    }

    auto suff = parse_suffix(ele);
    res->suffixes.emplace_back(std::move(suff));
  }
}
Пример #2
0
static void parse_query_expression(w_query* res, const json_ref& query) {
  auto exp = query.get_default("expression");
  if (!exp) {
    // Empty expression means that we emit all generated files
    return;
  }

  res->expr = w_query_expr_parse(res, exp);
}
Пример #3
0
static void parse_benchmark(w_query* res, const json_ref& query) {
  // Preserve behavior by supporting a boolean value. Also support int values.
  auto bench = query.get_default("bench");
  if (bench) {
    if (bench.isBool()) {
      res->bench_iterations = 100;
    } else {
      res->bench_iterations = json_integer_value(bench);
    }
  }
}
Пример #4
0
static void parse_request_id(w_query* res, const json_ref& query) {
  auto request_id = query.get_default("request_id");
  if (!request_id) {
    return;
  }

  if (!request_id.isString()) {
    throw QueryParseError("'request_id' must be a string");
  }

  res->request_id = json_to_w_string(request_id);
}
LocalSavedStateInterface::LocalSavedStateInterface(
    const json_ref& savedStateConfig,
    const SCM* scm)
    : SavedStateInterface(savedStateConfig), scm_(scm) {
  // Max commits to search in source control history for a saved state
  auto maxCommits = savedStateConfig.get_default("max-commits");
  if (maxCommits) {
    if (!maxCommits.isInt()) {
      throw QueryParseError("'max-commits' must be an integer");
    }
    maxCommits_ = json_integer_value(maxCommits);
    if (maxCommits_ < 1) {
      throw QueryParseError("'max-commits' must be a positive integer");
    }
  } else {
    maxCommits_ = kDefaultMaxCommits;
  }
  // Local path to search for saved states. This path will only ever be read,
  // never written.
  auto localStoragePath = savedStateConfig.get_default("local-storage-path");
  if (!localStoragePath) {
    throw QueryParseError(
        "'local-storage-path' must be present in saved state config");
  }
  if (!localStoragePath.isString()) {
    throw QueryParseError("'local-storage-path' must be a string");
  }
  localStoragePath_ = json_to_w_string(localStoragePath);
  if (!w_string_path_is_absolute(localStoragePath_)) {
    throw QueryParseError("'local-storage-path' must be an absolute path");
  }
  // The saved state project must be a sub-directory in the local storage
  // path.
  if (w_string_path_is_absolute(project_)) {
    throw QueryParseError("'project' must be a relative path");
  }
}
Пример #6
0
static bool parse_since(w_query* res, const json_ref& query) {
  auto since = query.get_default("since");
  if (!since) {
    return true;
  }

  auto spec = ClockSpec::parseOptionalClockSpec(since);
  if (spec) {
    // res owns the ref to spec
    res->since_spec = std::move(spec);
    return true;
  }

  throw QueryParseError("invalid value for 'since'");
}
Пример #7
0
static void parse_relative_root(
    const std::shared_ptr<w_root_t>& root,
    w_query* res,
    const json_ref& query) {
  auto relative_root = query.get_default("relative_root");
  if (!relative_root) {
    return;
  }

  if (!relative_root.isString()) {
    throw QueryParseError("'relative_root' must be a string");
  }

  auto path = json_to_w_string(relative_root).normalizeSeparators();
  auto canon_path = w_string_canon_path(path);
  res->relative_root = w_string::pathCat({root->root_path, canon_path});
  res->relative_root_slash =
      w_string::printf("%s/", res->relative_root.c_str());
}
Пример #8
0
static bool parse_paths(w_query* res, const json_ref& query) {
  size_t i;

  auto paths = query.get_default("path");
  if (!paths) {
    return true;
  }

  if (!paths.isArray()) {
    throw QueryParseError("'path' must be an array");
  }

  res->paths.resize(json_array_size(paths));

  for (i = 0; i < json_array_size(paths); i++) {
    const auto& ele = paths.at(i);
    w_string name;

    res->paths[i].depth = -1;

    if (ele.isString()) {
      name = json_to_w_string(ele);
    } else if (ele.isObject()) {
      name = json_to_w_string(ele.get("path"));

      auto depth = ele.get("depth");
      if (!depth.isInt()) {
        throw QueryParseError("path.depth must be an integer");
      }

      res->paths[i].depth = json_integer_value(depth);
    } else {
      throw QueryParseError(
          "expected object with 'path' and 'depth' properties");
    }

    res->paths[i].name = name.normalizeSeparators();
  }

  return true;
}
Пример #9
0
void parse_globs(w_query* res, const json_ref& query) {
  size_t i;
  int noescape = 0;
  int includedotfiles = 0;

  auto globs = query.get_default("glob");
  if (!globs) {
    return;
  }

  if (!json_is_array(globs)) {
    throw QueryParseError("'glob' must be an array");
  }

  // Globs implicitly enable dedup_results mode
  res->dedup_results = true;

  if (json_unpack(query, "{s?b}", "glob_noescape", &noescape) != 0) {
    throw QueryParseError("glob_noescape must be a boolean");
  }

  if (json_unpack(query, "{s?b}", "glob_includedotfiles", &includedotfiles) !=
      0) {
    throw QueryParseError("glob_includedotfiles must be a boolean");
  }

  res->glob_flags =
      (includedotfiles ? 0 : WM_PERIOD) | (noescape ? WM_NOESCAPE : 0);

  res->glob_tree = watchman::make_unique<watchman_glob_tree>("", 0);
  for (i = 0; i < json_array_size(globs); i++) {
    const auto& ele = globs.at(i);
    const auto& pattern = json_to_w_string(ele);

    if (!add_glob(res->glob_tree.get(), pattern)) {
      throw QueryParseError("failed to compile multi-glob");
    }
  }
}
Пример #10
0
std::shared_ptr<w_query> w_query_parse(
    const std::shared_ptr<w_root_t>& root,
    const json_ref& query) {
  auto result = std::make_shared<w_query>();
  auto res = result.get();

  parse_benchmark(res, query);
  parse_case_sensitive(res, root, query);
  parse_sync(res, query);
  parse_dedup(res, query);
  parse_lock_timeout(res, query);
  parse_relative_root(root, res, query);
  parse_empty_on_fresh_instance(res, query);

  /* Look for path generators */
  parse_paths(res, query);

  /* Look for glob generators */
  parse_globs(res, query);

  /* Look for suffix generators */
  parse_suffixes(res, query);

  /* Look for since generator */
  parse_since(res, query);

  parse_query_expression(res, query);

  parse_request_id(res, query);

  parse_field_list(query.get_default("fields"), &res->fieldList);

  res->query_spec = query;

  return result;
}