int translation_queue::find_repeat_commits_and_head()

in src/translation_queue.h [189:254]


int translation_queue::find_repeat_commits_and_head(commit_source *repeat,
                                                    sha1_ref &head) {
  if (!repeat)
    return 0;
  assert(repeat->is_repeat);
  if (repeat->goal == repeat->head)
    return repeat->skip_repeat_commits();

  // Set a lower bound for how far back to create merges.  Note that branches
  // can have a head from a start directive, without any of the sources having
  // an appropriate head.
  long long min_ct_to_merge = 0;
  if (head)
    if (cache.compute_ct(head, min_ct_to_merge))
      return error("failed to %ct of head '" + head->to_string() +
                   "' for stopping repeat '" + repeat->goal->to_string() + "'");

  // If it's possible to fast forward from head, figure out how far.
  bool can_ff_head = false;
  bool any_source_cts = false;
  if (!head || cache.merge_base_is_ancestor(head, repeat->goal)) {
    can_ff_head = true;
    for (auto &source : sources) {
      if (source.is_repeat)
        continue;

      if (!source.head)
        continue;

      // If there's a head and it's not an ancestor of the repeat commit goal,
      // then we should stretch repeat back to it.
      sha1_ref mono;
      if (cache.compute_mono(source.head, mono))
        return error("could not find monorepo hash for '" +
                     source.head->to_string() + "'");
      if (cache.merge_base_is_ancestor(mono, repeat->goal))
        continue;

      long long ct;
      if (cache.compute_ct(source.head, ct))
        return error("could not grab commit date of '" +
                      source.head->to_string() + "'");
      min_ct_to_merge = std::max(min_ct_to_merge, ct);
      any_source_cts = true;
    }
  }

  // Try harder to fast-forward.
  if (can_ff_head && !any_source_cts) {
    if (fparents.empty()) {
      // If there is nothing to translate and all the heads can fast-forward to
      // the repeat goal, then we only need to look back far enough to
      // determine the goal and refine the head.
      min_ct_to_merge = LLONG_MAX;
    } else {
      // Get the real ct, not the ct used for sorting.
      if (cache.compute_ct(fparents.back().commit, min_ct_to_merge))
        return error("could not grab commit date of '" +
                     fparents.back().commit->to_string() + "'");
    }
  }

  // We should have found this by now.
  assert(min_ct_to_merge);
  return repeat->find_repeat_commits_and_head(cache, min_ct_to_merge);
}