int commit_source::list_first_parents_limit_impl()

in src/commit_source.h [411:475]


int commit_source::list_first_parents_limit_impl(git_cache &cache,
                                                 const std::string &limitter,
                                                 std::string start,
                                                 sha1_ref &last_first_parent,
                                                 std::vector<sha1_ref> stops) {
  assert(!start.empty());

  // Repeat fparents don't have the right metadata to make this work.
  assert(!is_repeat);

  auto &git_reply = cache.git_reply;
  std::vector<const char *> argv = {
      "git",
      "log",
      "--first-parent",
      "--date=raw",
      "--format=tformat:%H %ct %P%x00%an%n%cn%n%ad%n%cd%n%ae%n%ce%n%B%x00",
      start.c_str(),
  };
  if (!limitter.empty())
    argv.push_back(limitter.c_str());
  std::vector<std::string> stop_sha1s;
  if (!stops.empty()) {
    argv.push_back("--not");
    for (auto &stop : stops)
      stop_sha1s.push_back(stop->to_string());
    for (auto &stop : stop_sha1s)
      argv.push_back(stop.c_str());
  }
  argv.push_back(nullptr);
  git_reply.clear();
  if (call_git(argv.data(), nullptr, "", git_reply))
    return error("git failed");
  git_reply.push_back(0);

  const char *current = git_reply.data();
  const char *end = git_reply.data() + git_reply.size() - 1;
  while (current != end) {
    fparents.emplace_back(source_index);
    fparents.back().is_translated = extra_commits_have_been_translated;
    if (cache.pool.parse_sha1(current, fparents.back().commit) ||
        parse_space(current) || parse_ct(current, fparents.back().ct) ||
        parse_space(current))
      return error("failed to parse commit and ct");
    validate_last_ct();

    last_first_parent = sha1_ref();
    const char *metadata = current;
    const char *end_metadata = end;
    if (cache.parse_for_store_metadata(fparents.back().commit, metadata,
                                       end_metadata, fparents.back().is_merge,
                                       last_first_parent))
      return 1;
    cache.store_metadata_if_new(fparents.back().commit, metadata, end_metadata,
                                fparents.back().is_merge, last_first_parent);
    current = end_metadata;
    if (last_first_parent) {
      fparents.back().has_parents = true;
      fparents.back().head_p = 0;
    }
    if (parse_null(current) || parse_newline(current))
      return 1;
  }
  return 0;
}