# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import datetime
import enum
import re
import textwrap

import attr

from PB.recipe_engine import result
from PB.go.chromium.org.luci.buildbucket.proto import common
from recipe_engine import recipe_api

UPSTREAM_REF = "main"

# The name of the link to the Gerrit change created for a roll. This is
# displayed in the CQ failure error message to help others understand where to
# look when debugging failed rolls.
GERRIT_LINK_NAME = "gerrit link"

# A substring of the message that CQ posts to CLs that pass the dry run.
PASSED_DRY_RUN_MESSAGE = "Dry run: This CL passed the CQ dry run."
FAILED_DRY_RUN_MESSAGE = "Dry run: Failed builds"

# CQ's dry run update comment will have on of these values in its "tag" field.
CQ_MESSAGE_TAGS = (
    "autogenerated:cv",
    # TODO(olivernewman): Delete this entry one LUCI CV is used everywhere and
    # we no longer need to support using the Commit Queue service.
    "autogenerated:cq:dry-run",
)

# Status of Gerrit labels. See _is_cq_complete() for details.
LABEL_STATUSES = ("rejected", "approved", "disliked", "recommended")


class CQResult(enum.Enum):
    """Represents the result of waiting for CQ to complete."""

    # CQ completed successfully.
    SUCCESS = 1

    # CQ tryjobs failed.
    FAILURE = 2

    # Timed out waiting for CQ to finish.
    TIMEOUT = 3

    # The CL was manually abandoned.
    ABANDONED = 4

    # The CL bypassed CQ.
    SKIPPED = 5

    # The CQ result cannot be determined because the CQ label was removed but
    # the CQ Bot result comment was not posted. This applies to dry run mode
    # only.
    MISSING_COMMENT = 6


FAILURE_REASONS = {
    CQResult.FAILURE: "CQ failed",
    CQResult.TIMEOUT: "auto-roller timeout",
    CQResult.ABANDONED: "CL manually abandoned",
}


@attr.s
class _ChangeId(object):
    project = attr.ib(type=str)
    branch = attr.ib(type=str)
    id = attr.ib(type=str)

    def __str__(self):
        return "~".join((self.project, self.branch, self.id))


@attr.s
class GerritChange(object):
    _api = attr.ib()
    # Full ID of the change, e.g. "fuchsia~main~Iabcd..."
    id = attr.ib(type=str)
    project = attr.ib(type=str)
    upstream_ref = attr.ib(type=str)
    host = attr.ib(type=str)
    dry_run = attr.ib(type=bool)
    cq_result = attr.ib(type=CQResult, default=None)
    _last_seen_status = attr.ib(type=str, default="")
    _revision = attr.ib(type=str, default="", init=False)

    @property
    def url(self):
        """A link to the CL in the Gerrit UI.

        The URL is actually a link to a search query for the change ID, but if
        there's only one change returned by the query then Gerrit redirects to
        that change, and this query will always return one or zero changes
        because it uses a full unique change ID.
        """
        return "https://%s/q/%s" % (self.host, self.id)

    @property
    def last_seen_status(self):
        """The status most recently returned by self.get_details().

        May be out of date with the Gerrit backend.
        """
        return self._last_seen_status

    @property
    def revision(self):
        """The commit hash most recently returned by self.get_details().

        May be out of date with the Gerrit backend.
        """
        return self._revision

    @property
    def success(self):
        """Whether the roll was successful.

        A roll is considered successful if CQ passed, or if CQ was
        bypassed and (for a non-dry run) the change was force-submitted.
        """
        return self.cq_result in (CQResult.SUCCESS, CQResult.SKIPPED)

    @property
    def retrigger_link(self):
        """Link to retrigger the roll."""
        trigger = "{}/{}".format(
            self._api.buildbucket.build.builder.project,
            self._api.buildbucket.build.builder.builder,
        )

        for tag in self._api.buildbucket.build.tags:
            if tag.key == "scheduler_job_id":
                trigger = tag.value
                break

        return "https://luci-scheduler.appspot.com/jobs/{}".format(trigger)

    def raise_if_failed(self):
        """Raise an informative StepFailure if CQ failed."""
        if not self.success:
            msg = (
                "Failed to roll changes: {reason}.\n\n"
                "[{link_name}]({url})\n\n"
                "[Retrigger]({retrigger})"
            ).format(
                reason=FAILURE_REASONS[self.cq_result],
                link_name=GERRIT_LINK_NAME,
                url=self.url,
                retrigger=self.retrigger_link,
            )
            raise recipe_api.StepFailure(msg)

    def get_details(self, step_name):
        """Queries the change-details endpoint for this change.

        Returns:
            A dict corresponding to the Gerrit API response.
        """
        step = self._api.gerrit.change_details(
            step_name,
            self.id,
            host=self.host,
            query_params=["CURRENT_REVISION"],
            max_attempts=3,
        )
        details = step.json.output
        self._last_seen_status = details["status"]
        self._revision = details["current_revision"]
        return details


class AutoRollerApi(recipe_api.RecipeApi):
    """API for writing auto-roller recipes."""

    CQResult = CQResult

    def __init__(self, poll_interval_secs, poll_timeout_secs, *args, **kwargs):
        # poll_interval_secs and poll_timeout_secs are input properties which come
        # from __init__.PROPERTIES in this directory.
        super(AutoRollerApi, self).__init__(*args, **kwargs)
        self._poll_interval_secs = poll_interval_secs
        self._poll_timeout_secs = poll_timeout_secs

    def initialize(self):
        if not self._poll_timeout_secs:
            # If execution_timeout is set, set the poll timeout to 10 minutes
            # before the build times out. If there's no execution_timeout or
            # it's less than 10 minutes, set the poll timeout to the prior
            # default, 50 minutes.
            delta = 10 * 60
            if self.m.buildbucket.build.execution_timeout.seconds > delta:
                self._poll_timeout_secs = (
                    self.m.buildbucket.build.execution_timeout.seconds - delta
                )
            else:
                self._poll_timeout_secs = 50 * 60
            assert self._poll_timeout_secs > 0

    def attempt_roll(
        self,
        gerrit_host,
        gerrit_project,
        repo_dir,
        commit_message,
        commit_untracked=False,
        force_submit=False,
        no_tryjobs=False,
        author_override=None,
        cl_notify_option=None,
        create_unique_id=False,
        dry_run=False,
        upstream_ref=UPSTREAM_REF,
        raise_on_failure=True,
        labels_to_set=None,
        labels_to_wait_on=None,
        cc=None,
        cc_on_failure=None,
        bot_commit=False,
        roller_owners=(),
        include_tryjobs=None,
    ):
        """Commit and attempt to submit local edits to a git repo.

        The high-level steps it performs are as follows (some of these steps
        will differ slightly in practice depending on argument values, but
        this is what most rollers do):

        1.  Calculate a Gerrit change ID using the local change diff, along
            with several other fields, as the input to a hash function.
        2.  Query Gerrit to see if there's an existing change with the same
            change ID (and thus the same diff).
            -   If there is no duplicate change, commit the local changes and
                push them to Gerrit to create a new change, setting the
                appropriate labels (CQ+1 in dry-run mode, or CQ+2 and CR+2 in
                production mode) using Gerrit push options to avoid making
                separate API request to set the labels.
            -   If there is a change with the same diff:
                -   If we're running in production mode, the change probably
                    failed a previous CQ attempt and got abandoned. Restore
                    the change if it's abandoned and then set the
                    Commit-Queue+2 label using the Gerrit CLI.
                -   If we're running in dry-run mode, assume that we've
                    already done a dry run on the CL, and exit the build
                    early. If the previous dry run succeeded, the build will
                    turn green, otherwise it will turn red. This is to avoid
                    needlessly running CQ many times on a broken dry run CL.
        3. Wait for CQ to complete.
            -   If CQ passes:
                -   If we're running in production mode, then CQ will have
                    submitted the CL after CQ passed. Exit and turn the build
                    green.
                -   If we're running in dry-run mode, abandon the CL now that
                    we're done with it. Then exit and turn the build green.
            -   If CQ fails, abandon the CL and exit, turning the build red.
            -   If the change is manually abandoned while CQ is running, exit
                and turn the build red.

        Args:
            gerrit_host (str): The name of the Gerrit host. e.g.
                "fuchsia-review.googlesource.com".
            gerrit_project (str): The name of the project to roll to in
                Gerrit, which is hosted on gerrit_host.
            repo_dir (Path): The path to the directory containing a local
                copy of the git repo with unstaged changes that will be
                committed and rolled.
            commit_message (str): The commit message for the roll. Note that
                this method will automatically append a Gerrit Change ID and
                several other footers to the change. Also, it may be a
                multiline string (embedded newlines are allowed).
            commit_untracked (bool): Whether to commit untracked files as
                well.
            force_submit (bool): Whether to force-submit the CL, bypassing CQ
                entirely (so changes will land even if the tree is closed).
                This is useful when rolling changes that have already been
                validated well enough that it's considered safe to roll them
                without further checks.
            no_tryjobs (bool): Whether CQ should skip running tryjobs on the
                CL. This is useful for rolling changes that are known to be
                no-ops but for which the tree status should still be
                respected to avoid launching unnecessary CI builds during
                tree closures.
            author_override (dict): Dict representation of a git.Commit_User
                containing name and email keys. If specified, override the
                author of the commit.
            cl_notify_option (str): One of "NONE", "OWNER", "OWNER_REVIEWERS",
                "ALL" specifying whom to send roll CL notifications to.
            create_unique_id (bool): Whether to create a Gerrit Change ID
                for the roll that is unique to this build.
            dry_run (bool): Whether to execute this method in dry_run mode
                (upload the changes and do a CQ dry run, but don't submit).
            upstream_ref (str): The git ref to roll changes onto.
            raise_on_failure (bool): Whether to raise an exception if the
                roll fails.
            labels_to_set (dict(str, int)): Labels to set on created CL. This
                is in addition to Commit-Queue (depending on dry_run), but
                {"Commit-Queue": 0} deletes the "Commit-Queue" label. This
                allows for integration with projects not using CQ.
            labels_to_wait_on (seq(str)): Non-CQ/CR labels to wait on before
                submitting.
            cc (seq(str)): List of emails to CC on the roll CL.
            cc_on_failure (seq(str)): Like cc, but only gets CCd on roll
                failures.
            bot_commit (bool): Vote Bot-Commit+1.
            roller_owners (seq(str)): Emails of the owners of the auto-roller
                that's creating this change. If set, the emails will be included in
                a commit message footer for informational purposes.
            include_tryjobs (dict(str, seq(str))): Extra tryjobs to include.

        Returns:
            A GerritChange corresponding to the roll CL created, or None if
            there were no changes to roll.
        """
        # Check to see if there are actually any changes in repo_dir before
        # continuing.
        if not self._repo_has_uncommitted_files(repo_dir, commit_untracked):
            self.m.step.empty("no changes to roll")
            return None

        assert not (
            force_submit and no_tryjobs
        ), "`force_submit` and `no_tryjobs` are mutually exclusive"

        labels = {}
        if not dry_run:
            if bot_commit:
                labels["Bot-Commit"] = 1
        if not force_submit:
            labels["Commit-Queue"] = 1 if dry_run else 2

        if labels_to_set:
            labels.update(labels_to_set)
            labels = {k: v for k, v in labels.items() if v}

        # Create the change both locally and remotely and push, applying the
        # specified labels (which will trigger CQ if the Commit-Queue label is
        # set).
        change = self._create_gerrit_change(
            gerrit_host=self.m.gerrit.normalize_host(gerrit_host),
            gerrit_project=gerrit_project,
            repo_dir=repo_dir,
            commit_message=commit_message,
            commit_untracked=commit_untracked,
            dry_run=dry_run,
            force_submit=force_submit,
            no_tryjobs=no_tryjobs,
            upstream_ref=upstream_ref,
            labels=labels,
            author_override=author_override,
            notify_option=cl_notify_option,
            create_unique_id=create_unique_id,
            cc=cc,
            roller_owners=roller_owners,
            include_tryjobs=include_tryjobs,
        )

        # If not setting Commit-Queue on upload we shouldn't try to clear it
        # in _ensure_abandoned(). By default we set Commit-Queue, so if it's
        # not explicitly mentioned assume we're setting it.
        clear_commit_queue = True
        if labels_to_set:
            clear_commit_queue = labels_to_set.get("Commit-Queue", True)

        if force_submit:
            change.cq_result = CQResult.SKIPPED
            if dry_run:
                self._ensure_abandoned(
                    change,
                    reason="would force-submit",
                    notify_option=cl_notify_option,
                    clear_commit_queue=clear_commit_queue,
                )
            else:
                self._force_submit(change)
            return change

        # If we already have a CQ result for this change (e.g. because we found
        # a previous dry run attempt) then don't bother rerunning CQ.
        if not change.cq_result or change.cq_result == CQResult.MISSING_COMMENT:
            change.cq_result = self._wait_for_cq(
                change, dry_run, labels_to_set or {}, labels_to_wait_on
            )

        if not change.success and cc_on_failure:
            self.m.gerrit.set_review(
                "cc", change.id, ccs=cc_on_failure, host=change.host
            )

        # Interpret the result and finish.
        if dry_run:
            # Only abandon the roll on success if it was a dry-run.
            self._ensure_abandoned(
                change,
                reason="dry run %s" % ("passed" if change.success else "failed"),
                notify_option=cl_notify_option,
                clear_commit_queue=clear_commit_queue,
            )
        elif not change.success:
            self._ensure_abandoned(
                change,
                notify_option=cl_notify_option,
                clear_commit_queue=clear_commit_queue,
                retrigger_link=True,
            )
        elif change.last_seen_status and change.last_seen_status != "MERGED":
            # For Gerrit hosts that do not use CQ, the roller itself must
            # handle submission.
            self._force_submit(change)

        if raise_on_failure:
            change.raise_if_failed()

        return change

    def raw_result(self, change=None, success_text=None):
        """Return a RawResult object containing a Gerrit link.

        If the change failed, will raise a user-friendly exception with a link
        to the roll CL.

        This is meant to be returned from RunSteps(). If done so, it results in
        the Gerrit link being included in the run summary at the top of the
        build page in MILO and in the "Summary" column of the builder page.

        If `change` is None, we assume that no roll was attempted because
        everything was already up to date.

        Args:
            change (GerritChange or None): The change created for the roll
                attempt, or None if no change was necessary.
            success_text (str): Custom text to include in the summary along
                with the Gerrit link in case of a successful roll, rather
                than the default text.
        """
        if not change:
            return self.nothing_to_roll()

        # Possibly redundant, but doesn't hurt anything.
        change.raise_if_failed()

        if not success_text:
            success_text = "%s succeeded" % ("Dry run" if change.dry_run else "Roll")

        return result.RawResult(
            summary_markdown="{}. [{}]({})".format(
                success_text, GERRIT_LINK_NAME, change.url
            ),
            status=common.SUCCESS,
        )

    def nothing_to_roll(self):
        """Returns a RawResult suitable for returning from RunSteps.

        Roller recipes should return this value when exiting early due to all
        dependencies already being up to date.
        """
        return result.RawResult(
            summary_markdown="Nothing to roll.",
            status=common.SUCCESS,
        )

    def _repo_has_uncommitted_files(self, repo_dir, check_untracked):
        """Checks whether the git repository at repo_dir has any changes.

        Args:
          repo_dir (Path): Path to the git repository.
          check_untracked (bool): Whether to include untracked files in the check.

        Returns:
          True if there are, and False if not.
        """
        with self.m.context(cwd=repo_dir):
            step_result = self.m.git.ls_files(
                step_name="check for no-op commit",
                modified=True,
                deleted=True,
                exclude_standard=True,
                others=check_untracked,
            )
        step_result.presentation.logs["stdout"] = step_result.stdout.split("\n")
        return bool(step_result.stdout.strip())

    def _create_gerrit_change(
        self,
        gerrit_host,
        gerrit_project,
        repo_dir,
        commit_message,
        commit_untracked,
        labels,
        dry_run,
        force_submit,
        no_tryjobs,
        author_override,
        notify_option,
        create_unique_id,
        upstream_ref,
        cc,
        roller_owners,
        include_tryjobs,
    ):
        """Creates a Gerrit change containing modified files under repo_dir.

        Returns:
            A GerritChange corresponding to the created CL.
        """
        with self.m.context(cwd=repo_dir, infra_steps=True):
            if commit_untracked:
                add_kwargs = dict(add_all=True)
            else:
                add_kwargs = dict(only_tracked=True)
            self.m.git.add(**add_kwargs)

            change_id, dupe_details = self._find_usable_change_id(
                gerrit_host,
                gerrit_project,
                create_unique_id,
                dry_run,
                upstream_ref,
            )

            if dupe_details:
                if dry_run:
                    # If we've already done a CQ dry run with these changes,
                    # it's likely a waste of resources to do additional dry
                    # runs.
                    self.m.step.empty("no new changes to dry-run")
                    cq_result = None
                    if not force_submit:
                        cq_result = self._cq_dry_run_result(dupe_details)
                    return GerritChange(
                        api=self.m,
                        project=gerrit_project,
                        upstream_ref=upstream_ref,
                        id=change_id,
                        host=gerrit_host,
                        dry_run=dry_run,
                        cq_result=cq_result,
                        last_seen_status=dupe_details["status"],
                    )

                # TODO(olivernewman): There's a bug in Gerrit where a new
                # patchset isn't considered trivial if it includes a rebase and
                # a commit message modification, so CQ won't reuse tryjobs from
                # older patchsets. We can get around this by splitting up the
                # operations into separate patchsets, which will both be
                # considered trivial: first, commit and push the changes with
                # the same commit message as the previous patchset. Then, amend
                # the commit to use the new commit message, and re-push.
                #
                # TODO(olivernewman): Remove this logic and just do a single
                # commit+push once http://b/171317704 is resolved.
                current_revision = dupe_details["current_revision"]
                old_commit_message = dupe_details["revisions"][current_revision][
                    "commit"
                ]["message"]
                self.m.git.commit(
                    message=old_commit_message,
                    author_override=author_override,
                )
                self._push(upstream_ref, notify_option=notify_option, cc=cc)

            extra_footers = [
                "Roller-URL: %s" % self.m.buildbucket_util.build_url,
            ]
            if roller_owners:
                # Purely for informational purposes; it's useful for build
                # gardeners to have an easily identifiable point of contact for
                # rollers when debugging a breakage caused by a roll.
                extra_footers.append("Roller-Owners: %s" % ", ".join(roller_owners))
            extra_footers.extend(
                [
                    "Cq-Cl-Tag: roller-builder:%s" % self.m.buildbucket.builder_name,
                    "Cq-Cl-Tag: roller-bid:%s" % self.m.buildbucket_util.id,
                    "CQ-Do-Not-Cancel-Tryjobs: true",
                    # Convert from a full change ID back to a partial change ID.
                    "Change-Id: %s" % change_id.id,
                ]
            )
            if no_tryjobs:
                extra_footers.append("No-Try: true")
            if include_tryjobs:
                extra_footers.append(
                    "Cq-Include-Trybots: "
                    + ";".join(
                        [
                            "%s:%s" % (bucket, ",".join(builders))
                            for bucket, builders in include_tryjobs.items()
                        ]
                    )
                )
            if len(commit_message.splitlines()) == 1:
                # Make sure we have a blank line after the commit message title.
                commit_message += "\n"
            commit_message += "".join("\n" + footer for footer in extra_footers)

            self.m.git.commit(
                message=commit_message,
                # If we're updating an existing CL, use this commit step to
                # amend the old commit message.
                # TODO(olivernewman): Stop amending once http://b/171317704 is
                # resolved.
                amend=bool(dupe_details),
                author_override=author_override,
                all_tracked=True,
            )

            push_step = self._push(
                upstream_ref, labels, notify_option=notify_option, cc=cc
            )
            if "redirect" in push_step.presentation.logs:
                upstream_ref = push_step.presentation.logs["redirect"]
                change_id.branch = upstream_ref

            change = GerritChange(
                api=self.m,
                project=gerrit_project,
                upstream_ref=upstream_ref,
                id=change_id,
                host=gerrit_host,
                dry_run=dry_run,
            )
            push_step.presentation.links[GERRIT_LINK_NAME] = change.url
            return change

    def _find_usable_change_id(
        self,
        gerrit_host,
        gerrit_project,
        create_unique_id,
        dry_run,
        upstream_ref,
    ):
        """Finds a Change-Id for the CL that Gerrit will allow.

        The Change-Id must *NOT* be the same as the Change-Id of an existing
        already-merged CL.

        Given that restriction, we try to make it as likely as possible that
        we'll find and re-CQ+2 an unmerged change with the same diff, if one
        exists.

        Returns:
            The calculated Change-Id, along with the change details of an
            identical change (or None if there is no identical change).
        """
        possible_extra_hash_inputs = [
            # If there's an already-merged CL with the same diff, we'll fall
            # back to including the base revision in the Change-Id hash inputs.
            # Barring a race condition with an identical roller, it should be
            # impossible for this CL to have the same diff *and* the same base
            # revision as an already-merged CL.
            self.m.git.rev_parse("HEAD"),
            # If all else fails, we'll give up on trying to find and restore an
            # identical change and just try to get a unique Change Id.
            str(self.m.random.random()),
        ]
        for i in range(len(possible_extra_hash_inputs) + 1):
            with self.m.step.nest("calculate Change-Id") as presentation:
                partial_change_id = self._calculate_change_id(
                    create_unique_id,
                    dry_run,
                    extra_hash_inputs=possible_extra_hash_inputs[:i],
                )
                presentation.step_text = partial_change_id
                change_id = self._full_change_id(
                    gerrit_project, upstream_ref, partial_change_id
                )

            # Check to see if there's an existing identical roll CL that the roller
            # abandoned (probably because it failed in CQ).
            change_query_step = self.m.gerrit.change_query(
                "check for identical roll",
                "change:%s" % change_id,
                query_params=["CURRENT_COMMIT", "CURRENT_REVISION", "MESSAGES"],
                host=gerrit_host,
                # The Gerrit API returns null if no changes are found.
                test_data=self.m.json.test_api.output(None),
            )
            identical_changes = change_query_step.json.output
            if not identical_changes:
                return change_id, None

            def _change_url(details):
                return "https://%s/%s" % (gerrit_host, details["_number"])

            for c in identical_changes:
                link_name = "CL %d (%s)" % (c["_number"], c["status"].lower())
                change_query_step.presentation.links[link_name] = _change_url(c)

            # There's something weird going on if there's more than one
            # identical change (Gerrit is supposed to make this
            # impossible) so we should just exit.
            assert len(identical_changes) == 1, "%d != 1" % len(identical_changes)
            change_details = identical_changes[0]

            if change_details["status"] == "MERGED":
                # If there's a merged change with the same change ID, we'll
                # recalculate the change ID using more specific hash inputs.
                continue
            elif change_details["status"] == "ABANDONED" and not dry_run:
                # Don't bother restoring abandoned changes in dry-run mode,
                # since we'll just reuse the result of the previous dry run
                # instead of retrying CQ.
                restore_step = self.m.gerrit.restore_change(
                    "restore CL from previous roll attempt",
                    change_id,
                    host=gerrit_host,
                    message="Retrying CQ.",
                )
                restore_step.presentation.step_text = (
                    "\nfound an identical roll CL that was abandoned."
                )
            else:
                # Either we're in dry-run mode, or the previous roll attempt's
                # CL is open, rather than abandoned. If the change is open,
                # it's likely that either:
                # - Someone restored a previously abandoned auto-roll CL
                #   expecting the roller to pick it back up.
                # - OR the roller failed to clean up properly on its last
                #   attempt.
                # In either case we should re-CQ the CL.
                self.m.step.empty("reusing CL from previous roll attempt")

            return change_id, change_details

        raise self.m.step.InfraFailure(
            "failed to calculate a unique Change-Id for this CL"
        )  # pragma: no cover

    def _calculate_change_id(self, create_unique_id, dry_run, extra_hash_inputs=()):
        """Compute a Gerrit change ID for the roll commit.

        This function assumes that it's run in the directory corresponding to
        the git repo that will contain the roll commit.

        We generate our own change ID because:
        - We need to know the change ID post-push in order to perform operations
          on the change via the Gerrit API. Since we generate the change ID
          ourselves, there's no need to scan Gerrit's `git push` output for the
          change URL, or to query the Gerrit API for the commit hash (such
          queries often fail due to Gerrit backend replication delays).
        - Deterministically generating a change ID using the git diff lets us
          detect when an identical roll has already been attempted, because
          we'll calculate the same change ID as an existing CL.
        """
        mock_diff = textwrap.dedent(
            """\
            diff --git a/foo.txt b/foo.txt
            index 63bcead3a0..b0dff288cd 100644
            --- a/foo.txt
            +++ b/foo.txt
            @@ -16 +16 @@
            -        foo = 5
            +        foo = 6
            diff --git a/bar.txt b/bar.txt
            index 9410318a54..5a8c587f75 100644
            --- a/bar.txt
            +++ b/bar.txt
            @@ -5 +5 @@
            -        bar = 0
            +        bar = 1
            """
        )

        diff_step = self.m.git.diff(
            ref_base=None,
            # Include no context around the changed lines to make it less likely
            # that two identical patches will have different diff output
            # depending on whether a recent change touching nearby lines is
            # checked out locally.
            unified=0,
            # Assumes we've already staged the changes we're going to commit.
            cached=True,
            step_test_data=lambda: self.m.raw_io.test_api.stream_output_text(mock_diff),
        )

        # git diff output includes a header line for each modified file of the
        # form: "index <oldhash>..<newhash> <mode>". These hashes might vary
        # depending on how much history we have checked out locally, making it
        # less likely that otherwise identical patches will have the same diff
        # output. So strip out these "index" lines in the diff that we use to
        # calculate a Change-Id.
        diff_lines = [
            l for l in diff_step.stdout.split("\n") if not l.startswith("index ")
        ]
        diff_step.presentation.logs["diff (without hashes)"] = diff_lines

        # Use the hash of the diff so that this CL will collide with any older
        # identical CLs. Also include:
        # - The builder name, to ensure that two builders don't try to operate
        #   on the same roll CLs.
        # - Whether we're running in dry-run mode, because commit messages
        #   intentionally differ between dry-run and non-dry-run rolls.
        # - Whether this is a led build. If it is a led build it probably means
        #   a developer is trying to test changes to a recipe, so we don't want
        #   CLs created by the led job to collide with CLs created by a
        #   production roller build.
        hash_inputs = [
            "\n".join(diff_lines),
            str(self.m.buildbucket.builder_name),
            ("dry-run" if dry_run else ""),
            # TODO(crbug.com/1129577): Use the name of the user who launched the
            # led job instead of a boolean led/no-led so that multiple people
            # can test the same recipe with led without stepping on each other's
            # toes.
            ("led" if self.m.led.launched_by_led else ""),
        ]
        if create_unique_id:
            hash_inputs.append(self.m.buildbucket_util.id)
        hash_inputs.extend(extra_hash_inputs)
        hash_step = self.m.git.hash_object(
            # Separate hash inputs with a special string just to be extra
            # unambiguous about which part of the string corresponds to a
            # separate parameter.
            "####".join(hash_inputs),
        )

        return "I%s" % hash_step.stdout.strip()

    def _full_change_id(self, project, upstream_ref, change_id):
        """Returns the full (unique) change ID for a change.

        Each Gerrit host only enforces change ID uniqueness per (repo, upstream_ref)
        combination, so a full change ID is required to uniquely identify a change.
        """
        return _ChangeId(project, upstream_ref, change_id)

    def _push(self, upstream_ref, labels=None, notify_option=None, cc=None):
        labels = labels or {}
        # Apply labels at push time rather than using `api.gerrit.set_review()`
        # to apply them post-push in order to avoid extra Gerrit API requests as
        # well as a possible race condition when applying labels to a very
        # recently pushed change. See
        # https://gerrit-review.googlesource.com/Documentation/user-upload.html#review_labels.
        gerrit_options = []
        for label, score in sorted(labels.items()):
            if score != 0:
                # Label push options look like "l=Commit-Queue+2".
                gerrit_options.append("l=%s%+d" % (label, score))
        if notify_option:
            gerrit_options.append("notify=%s" % notify_option)
        if cc:
            gerrit_options.extend("cc=%s" % c for c in cc)

        push_ref = "HEAD:refs/for/%s" % upstream_ref
        if gerrit_options:
            push_ref += "%" + ",".join(gerrit_options)

        def do_push():
            # Gerrit sometimes rejects pushes with spurious "found private key"
            # errors, so we disable key checking.
            step = self.m.git.push(
                push_ref,
                options=["nokeycheck"],
                timeout=datetime.timedelta(minutes=3),
                stdout=self.m.raw_io.output_text(),
            )
            match = re.search(
                r"Update redirected to refs/for/refs/heads/([-\w_]+)(%|\.)",
                step.stdout,
            )
            if match:
                step.presentation.logs["redirect"] = match.group(1)
            step.presentation.logs["stdout"] = step.stdout
            return step

        # Retry in case Gerrit backend replication delays cause the backend to
        # think that a recently restored CL is still closed.
        return self.m.utils.retry(do_push, max_attempts=5, sleep=5, backoff_factor=2)

    def _is_cq_complete(
        self, iteration, change, dry_run, labels_to_set, labels_to_wait_on
    ):
        with self.m.context(infra_steps=True):
            details = change.get_details("check if done (%d)" % iteration)

        # If the CQ label is un-set, then that means either:
        # * CQ failed (production mode), or
        # * CQ finished (dry-run mode).
        #
        # 'recommended' and 'approved' are objects that appear for a label if
        # somebody gave the label a positive vote (maximum vote (+2) for approved,
        # non-maximum (+1) for 'recommended') and contains the information of one
        # reviewer who gave this vote. There are 4 different states for a label in
        # this sense: 'rejected', 'approved', 'disliked', and 'recommended'. For a
        # given label, only one of these will be shown if the label has any votes
        # in priority order 'rejected' > 'approved' > 'disliked' > 'recommended'.
        # Unfortunately, this is the absolute simplest way to check this. Gerrit
        # provides an 'all' field that contains every vote, but iterating over
        # every vote, or operating under the assumption that there's at least one
        # causes more error cases.
        #
        # Read more at:
        # https://gerrit-review.googlesource.com/Documentation/rest-self.m-changes.html#get-change-detail

        if details["status"] == "ABANDONED":
            return CQResult.ABANDONED

        # If it merged, we're done! (Even if this is a dry run.)
        if details["status"] == "MERGED":
            return CQResult.SUCCESS

        # Wait on all extra non-CQ labels before checking CQ.
        for label in labels_to_wait_on or ():
            with self.m.step.nest("check %s label (%d)" % (label, iteration)) as pres:
                pres.step_summary_text = "not set"
                for status in LABEL_STATUSES:
                    if status in details["labels"][label]:
                        pres.step_summary_text = status
                if "rejected" in details["labels"][label]:
                    return CQResult.FAILURE
                if "approved" not in details["labels"][label]:
                    return None

        # If there's no "Commit-Queue" label don't attempt to wait on CQ to
        # complete. (Presumably there's a non-CQ presubmit system that was
        # handled through labels_to_wait_on above, and if we got here that
        # non-CQ presubmit system has passed.)
        if "Commit-Queue" not in details["labels"]:
            return CQResult.SUCCESS

        # If the properties say to set Commit-Queue to 1 regardless of whether
        # this is a dry run then we're likely mixing CQ with other presubmits,
        # and we want to submit after all presubmits run. In this case use the
        # dry run processing even if not in a dry run.
        if dry_run or labels_to_set.get("Commit-Queue") == 1:
            dry_run_result = self._cq_dry_run_result(details)
            if dry_run_result:
                return dry_run_result
        else:
            # If CQ drops the CQ+2 label at any point (i.e. 'approved' state), then
            # that always means CQ has failed. CQ will always remove the CQ+2 label
            # when it fails, and it will never remove it on success.
            #
            # Note: Because CQ won't unset the the CQ+2 label when it merges, there's
            # no chance that we might see that the CL hasn't merged with the CQ+2
            # label unset on a successful CQ.
            if "approved" not in details["labels"]["Commit-Queue"]:
                return CQResult.FAILURE

        # CQ is still running.
        return None

    def _cq_dry_run_result(self, change_details):
        # If CQ drops the CQ+1 label (i.e. 'recommended' state), then that means
        # CQ finished trying. CQ will always remove the CQ+1 label when it's
        # finished, regardless of success or failure.
        labels = change_details["labels"] or {}
        if "recommended" in labels.get("Commit-Queue", {}):
            return None

        # Unfortunately the only way to determine whether the dry run has passed
        # or failed is to check whether CQ's most recent dry run comment has a
        # specific string.
        messages = change_details["messages"] or []
        for message in reversed(messages):
            if message.get("tag") not in CQ_MESSAGE_TAGS:
                continue
            if PASSED_DRY_RUN_MESSAGE in message["message"]:
                return CQResult.SUCCESS
            elif FAILED_DRY_RUN_MESSAGE in message["message"]:
                return CQResult.FAILURE
            # If we get here then this message is likely a "CQ is trying the
            # patch" comment, which indicates that CQ has not yet posted the
            # dry run result.
            break

        # If we're here, the CQ label was removed but CQ Bot didn't comment the
        # status yet.
        return CQResult.MISSING_COMMENT

    def _wait_for_cq(self, change_id, dry_run, labels_to_set, labels_to_wait_on):
        """Polls gerrit to see if CQ was successful.

        Returns a CQResult representing the status of CQ.
        """
        # Wait 30 seconds before polling for the first time to guard against Gerrit
        # minor replication delays.
        wait_time = 30

        # If waiting on additional labels it's possible they've been set to +1
        # or -1 based on a previous run and reinvoking won't immediately clear
        # them. In that case we need to give the non-CQ presubmits time to clear
        # existing votes when starting jobs.
        if labels_to_wait_on:
            wait_time = 5 * 60

        self.m.time.sleep(wait_time)

        with self.m.step.nest("check for completion"):
            num_iterations = int(self._poll_timeout_secs / self._poll_interval_secs)
            # Include one-time tolerance for the indeterminate CQ result where
            # we are waiting for the CQ result comment to be posted.
            wait_for_comment = True
            for i in range(num_iterations + 1):
                # Check the status of the CL.
                status = self._is_cq_complete(
                    i, change_id, dry_run, labels_to_set, labels_to_wait_on
                )
                if status == CQResult.MISSING_COMMENT:
                    # Unset the flag so that we no longer tolerate a missing CQ
                    # result comment.
                    if wait_for_comment:
                        wait_for_comment = False
                    else:
                        raise self.m.step.InfraFailure(
                            "CQ removed the CQ+1 vote but didn't post a message with the dry run result"
                        )
                elif status:
                    return status

                # If none of the terminal conditions above were reached (that is, there were
                # no label changes from what we initially set, and the change has not
                # merged or abandoned), then we should wait for |poll_interval_secs| before
                # trying again. Don't sleep after the final check.

                if i < num_iterations:
                    self.m.time.sleep(self._poll_interval_secs)

        return CQResult.TIMEOUT

    def _ensure_abandoned(
        self,
        change,
        reason="",
        notify_option=None,
        clear_commit_queue=True,
        retrigger_link=False,
    ):
        if not reason:
            reason = FAILURE_REASONS[change.cq_result]

        if change.cq_result == CQResult.TIMEOUT and clear_commit_queue:
            # CQ automatically removes the CQ label in case of a tryjob
            # failure, but if CQ has not yet completed then we'll need to
            # remove the label ourselves so that CQ doesn't submit the CL right
            # away if and when it's restored by a subsequent roll attempt.
            self.m.gerrit.set_review(
                "remove Commit-Queue label",
                change.id,
                labels={"Commit-Queue": 0},
                host=change.host,
            )

        if change.last_seen_status == "ABANDONED":
            step = self.m.step.empty(reason)
        else:
            # Capitalize the first letter and add a period for stylistic
            # consistency with comments added by CQ and by Gerrit itself.
            message = reason[0].upper() + reason[1:].rstrip(".") + "."
            if retrigger_link:
                message += " To retry this roll go to {}.".format(change.retrigger_link)

            step = self.m.gerrit.abandon(
                "abandon roll",
                change.id,
                message=message,
                host=change.host,
                notify=notify_option,
            )
            step.presentation.step_text = reason

        step.presentation.links[GERRIT_LINK_NAME] = change.url
        if not change.success:
            step.presentation.status = self.m.step.FAILURE

    def _force_submit(self, change):
        def submit_func():
            self.m.gerrit.submit("force-submit change", change.id, host=change.host)

        # Retry submission in case Gerrit backend replication delays cause 404s.
        self.m.utils.retry(submit_func, max_attempts=5)
