First, transitions between can_be_merged & cannot_be_merged are removed,
as they are currently blocked in `check_if_can_be_merged`.
`can_be_merge` always returns to `unchecked` first,
before it can transition to `cannot_be_merged` (and vice versa).
We want to avoid repeated notification triggered by repeated transition
between `cannot_be_merged` & `unchecked`.
So we added `cannot_be_merged_recheck` state, similar to `unchecked`,
but as a mean to remember it’s from cannot_be_merged.
See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18042/#note_65945407
Since `unchecked` and `cannot_be_merged_recheck` both mean
“we are in the middle of checking if it is mergeable”,
quite often we need to see if merge_status is in either one of them,
so `check_state?` is added to achieve this.
If the ref hasn't been fetched into the target repository yet, this will fail
with a Rugged::ReferencError (assuming we're not using Gitaly). We should handle
this in the same way as a missing ref.
This does two things:
- Pass commit oids instead of `Gitlab::Git::Commit`s. We only need the
former.
- Depend on only the target repository for conflict listing. For
conflict resolution, treat one repository as a remote one so that we can
implement it as such in Gitaly.
I don't know why this happens exactly, but given an upstream and fork repository
from a customer, both of which required GC, resolving conflicts would corrupt
the fork so badly that it couldn't be cloned.
This isn't a perfect fix for that case, because the MR may still need to be
merged manually, but it does ensure that the repository is at least usable.
My best guess is that when we generate the index for the conflict
resolution (which we previously did in the target project), we obtain a
reference to an OID that doesn't exist in the source, even though we already
fetch the refs from the target into the source.
Explicitly setting the source project as the place to get the merge index from
seems to prevent repository corruption in this way.