#!/usr/bin/env python
# Copyright 2014 the V8 project 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 argparse
import os
import sys

from common_includes import *

ROLL_SUMMARY = ("Summary of changes available at:\n"
                "https://chromium.googlesource.com/v8/v8/+log/%s..%s")

ISSUE_MSG = (
"""Please follow these instructions for assigning/CC'ing issues:
https://github.com/v8/v8/wiki/Triaging%20issues

Please close rolling in case of a roll revert:
https://v8-roll.appspot.com/
This only works with a Google account.

CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel""")

class Preparation(Step):
  MESSAGE = "Preparation."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'preparation'
    # Update v8 remote tracking branches.
    self.GitFetchOrigin()
    self.Git("fetch origin +refs/tags/*:refs/tags/*")


class DetectLastRoll(Step):
  MESSAGE = "Detect commit ID of the last Chromium roll."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'detect_last_roll'
    self["last_roll"] = self._options.last_roll
    if not self["last_roll"]:
      # Interpret the DEPS file to retrieve the v8 revision.
      # TODO(machenbach): This should be part or the roll-deps api of
      # depot_tools.
      Var = lambda var: '%s'
      exec(FileToText(os.path.join(self._options.chromium, "DEPS")))

      # The revision rolled last.
      self["last_roll"] = vars['v8_revision']
    self["last_version"] = self.GetVersionTag(self["last_roll"])
    assert self["last_version"], "The last rolled v8 revision is not tagged."


class DetectRevisionToRoll(Step):
  MESSAGE = "Detect commit ID of the V8 revision to roll."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'detect_revision'
    self["roll"] = self._options.revision
    if self["roll"]:
      # If the revision was passed on the cmd line, continue script execution
      # in the next step.
      return False

    # The revision that should be rolled. Check for the latest of the most
    # recent releases based on commit timestamp.
    revisions = self.GetRecentReleases(
        max_age=self._options.max_age * DAY_IN_SECONDS)
    assert revisions, "Didn't find any recent release."

    # There must be some progress between the last roll and the new candidate
    # revision (i.e. we don't go backwards). The revisions are ordered newest
    # to oldest. It is possible that the newest timestamp has no progress
    # compared to the last roll, i.e. if the newest release is a cherry-pick
    # on a release branch. Then we look further.
    for revision in revisions:
      version = self.GetVersionTag(revision)
      assert version, "Internal error. All recent releases should have a tag"

      if SortingKey(self["last_version"]) < SortingKey(version):
        self["roll"] = revision
        break
    else:
      print("There is no newer v8 revision than the one in Chromium (%s)."
            % self["last_roll"])
      self['json_output']['monitoring_state'] = 'up_to_date'
      return True


class PrepareRollCandidate(Step):
  MESSAGE = "Robustness checks of the roll candidate."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'prepare_candidate'
    self["roll_title"] = self.GitLog(n=1, format="%s",
                                     git_hash=self["roll"])

    # Make sure the last roll and the roll candidate are releases.
    version = self.GetVersionTag(self["roll"])
    assert version, "The revision to roll is not tagged."
    version = self.GetVersionTag(self["last_roll"])
    assert version, "The revision used as last roll is not tagged."


class SwitchChromium(Step):
  MESSAGE = "Switch to Chromium checkout."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'switch_chromium'
    cwd = self._options.chromium
    self.InitialEnvironmentChecks(cwd)
    # Check for a clean workdir.
    if not self.GitIsWorkdirClean(cwd=cwd):  # pragma: no cover
      self.Die("Workspace is not clean. Please commit or undo your changes.")
    # Assert that the DEPS file is there.
    if not os.path.exists(os.path.join(cwd, "DEPS")):  # pragma: no cover
      self.Die("DEPS file not present.")


class UpdateChromiumCheckout(Step):
  MESSAGE = "Update the checkout and create a new branch."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'update_chromium'
    cwd = self._options.chromium
    self.GitCheckout("master", cwd=cwd)
    self.DeleteBranch("work-branch", cwd=cwd)
    self.GitPull(cwd=cwd)

    # Update v8 remotes.
    self.GitFetchOrigin()

    self.GitCreateBranch("work-branch", cwd=cwd)


class UploadCL(Step):
  MESSAGE = "Create and upload CL."

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'upload'
    cwd = self._options.chromium
    # Patch DEPS file.
    if self.Command("roll-dep-svn", "v8 %s" %
                    self["roll"], cwd=cwd) is None:
      self.Die("Failed to create deps for %s" % self["roll"])

    message = []
    message.append("Update V8 to %s." % self["roll_title"].lower())

    message.append(
        ROLL_SUMMARY % (self["last_roll"][:8], self["roll"][:8]))

    message.append(ISSUE_MSG)

    message.append("TBR=%s" % self._options.reviewer)
    self.GitCommit("\n\n".join(message),  author=self._options.author, cwd=cwd)
    if not self._options.dry_run:
      self.GitUpload(author=self._options.author,
                     force=True,
                     bypass_hooks=True,
                     cq=self._options.use_commit_queue,
                     cwd=cwd)
      print "CL uploaded."
    else:
      print "Dry run - don't upload."

    self.GitCheckout("master", cwd=cwd)
    self.GitDeleteBranch("work-branch", cwd=cwd)

class CleanUp(Step):
  MESSAGE = "Done!"

  def RunStep(self):
    self['json_output']['monitoring_state'] = 'success'
    print("Congratulations, you have successfully rolled %s into "
          "Chromium."
          % self["roll"])

    # Clean up all temporary files.
    Command("rm", "-f %s*" % self._config["PERSISTFILE_BASENAME"])


class AutoRoll(ScriptsBase):
  def _PrepareOptions(self, parser):
    parser.add_argument("-c", "--chromium", required=True,
                        help=("The path to your Chromium src/ "
                              "directory to automate the V8 roll."))
    parser.add_argument("--last-roll",
                        help="The git commit ID of the last rolled version. "
                             "Auto-detected if not specified.")
    parser.add_argument("--max-age", default=7, type=int,
                        help="Maximum age in days of the latest release.")
    parser.add_argument("--revision",
                        help="Revision to roll. Auto-detected if not "
                             "specified."),
    parser.add_argument("--roll", help="Deprecated.",
                        default=True, action="store_true")
    parser.add_argument("--use-commit-queue",
                        help="Check the CQ bit on upload.",
                        default=True, action="store_true")

  def _ProcessOptions(self, options):  # pragma: no cover
    if not options.author or not options.reviewer:
      print "A reviewer (-r) and an author (-a) are required."
      return False

    options.requires_editor = False
    options.force = True
    options.manual = False
    return True

  def _Config(self):
    return {
      "PERSISTFILE_BASENAME": "/tmp/v8-chromium-roll-tempfile",
    }

  def _Steps(self):
    return [
      Preparation,
      DetectLastRoll,
      DetectRevisionToRoll,
      PrepareRollCandidate,
      SwitchChromium,
      UpdateChromiumCheckout,
      UploadCL,
      CleanUp,
    ]


if __name__ == "__main__":  # pragma: no cover
  sys.exit(AutoRoll().Run())
