Home | History | Annotate | Download | only in push-to-trunk
      1 #!/usr/bin/env python
      2 # Copyright 2014 the V8 project authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import argparse
      7 import os
      8 import sys
      9 
     10 from common_includes import *
     11 
     12 DEPS_FILE = "DEPS_FILE"
     13 CHROMIUM = "CHROMIUM"
     14 
     15 CONFIG = {
     16   PERSISTFILE_BASENAME: "/tmp/v8-chromium-roll-tempfile",
     17   DOT_GIT_LOCATION: ".git",
     18   DEPS_FILE: "DEPS",
     19 }
     20 
     21 
     22 class Preparation(Step):
     23   MESSAGE = "Preparation."
     24 
     25   def RunStep(self):
     26     self.CommonPrepare()
     27 
     28 
     29 class DetectLastPush(Step):
     30   MESSAGE = "Detect commit ID of last push to trunk."
     31 
     32   def RunStep(self):
     33     self["last_push"] = self._options.last_push or self.FindLastTrunkPush(
     34         include_patches=True)
     35     self["trunk_revision"] = self.GitSVNFindSVNRev(self["last_push"])
     36     self["push_title"] = self.GitLog(n=1, format="%s",
     37                                      git_hash=self["last_push"])
     38 
     39 
     40 class CheckChromium(Step):
     41   MESSAGE = "Ask for chromium checkout."
     42 
     43   def Run(self):
     44     self["chrome_path"] = self._options.chromium
     45     while not self["chrome_path"]:
     46       self.DieNoManualMode("Please specify the path to a Chromium checkout in "
     47                            "forced mode.")
     48       print ("Please specify the path to the chromium \"src\" directory: "),
     49       self["chrome_path"] = self.ReadLine()
     50 
     51 
     52 class SwitchChromium(Step):
     53   MESSAGE = "Switch to Chromium checkout."
     54   REQUIRES = "chrome_path"
     55 
     56   def RunStep(self):
     57     self["v8_path"] = os.getcwd()
     58     os.chdir(self["chrome_path"])
     59     self.InitialEnvironmentChecks()
     60     # Check for a clean workdir.
     61     if not self.GitIsWorkdirClean():  # pragma: no cover
     62       self.Die("Workspace is not clean. Please commit or undo your changes.")
     63     # Assert that the DEPS file is there.
     64     if not os.path.exists(self.Config(DEPS_FILE)):  # pragma: no cover
     65       self.Die("DEPS file not present.")
     66 
     67 
     68 class UpdateChromiumCheckout(Step):
     69   MESSAGE = "Update the checkout and create a new branch."
     70   REQUIRES = "chrome_path"
     71 
     72   def RunStep(self):
     73     os.chdir(self["chrome_path"])
     74     self.GitCheckout("master")
     75     self.GitPull()
     76     self.GitCreateBranch("v8-roll-%s" % self["trunk_revision"])
     77 
     78 
     79 class UploadCL(Step):
     80   MESSAGE = "Create and upload CL."
     81   REQUIRES = "chrome_path"
     82 
     83   def RunStep(self):
     84     os.chdir(self["chrome_path"])
     85 
     86     # Patch DEPS file.
     87     deps = FileToText(self.Config(DEPS_FILE))
     88     deps = re.sub("(?<=\"v8_revision\": \")([0-9]+)(?=\")",
     89                   self["trunk_revision"],
     90                   deps)
     91     TextToFile(deps, self.Config(DEPS_FILE))
     92 
     93     if self._options.reviewer and not self._options.manual:
     94       print "Using account %s for review." % self._options.reviewer
     95       rev = self._options.reviewer
     96     else:
     97       print "Please enter the email address of a reviewer for the roll CL: ",
     98       self.DieNoManualMode("A reviewer must be specified in forced mode.")
     99       rev = self.ReadLine()
    100 
    101     commit_title = "Update V8 to %s." % self["push_title"].lower()
    102     sheriff = ""
    103     if self["sheriff"]:
    104       sheriff = ("\n\nPlease reply to the V8 sheriff %s in case of problems."
    105                  % self["sheriff"])
    106     self.GitCommit("%s%s\n\nTBR=%s" % (commit_title, sheriff, rev))
    107     self.GitUpload(author=self._options.author,
    108                    force=self._options.force_upload)
    109     print "CL uploaded."
    110 
    111 
    112 class SwitchV8(Step):
    113   MESSAGE = "Returning to V8 checkout."
    114   REQUIRES = "chrome_path"
    115 
    116   def RunStep(self):
    117     os.chdir(self["v8_path"])
    118 
    119 
    120 class CleanUp(Step):
    121   MESSAGE = "Done!"
    122 
    123   def RunStep(self):
    124     print("Congratulations, you have successfully rolled the push r%s it into "
    125           "Chromium. Please don't forget to update the v8rel spreadsheet."
    126           % self["trunk_revision"])
    127 
    128     # Clean up all temporary files.
    129     Command("rm", "-f %s*" % self._config[PERSISTFILE_BASENAME])
    130 
    131 
    132 class ChromiumRoll(ScriptsBase):
    133   def _PrepareOptions(self, parser):
    134     group = parser.add_mutually_exclusive_group()
    135     group.add_argument("-f", "--force",
    136                       help="Don't prompt the user.",
    137                       default=False, action="store_true")
    138     group.add_argument("-m", "--manual",
    139                       help="Prompt the user at every important step.",
    140                       default=False, action="store_true")
    141     parser.add_argument("-c", "--chromium",
    142                         help=("The path to your Chromium src/ "
    143                               "directory to automate the V8 roll."))
    144     parser.add_argument("-l", "--last-push",
    145                         help="The git commit ID of the last push to trunk.")
    146 
    147   def _ProcessOptions(self, options):  # pragma: no cover
    148     if not options.manual and not options.reviewer:
    149       print "A reviewer (-r) is required in (semi-)automatic mode."
    150       return False
    151     if not options.manual and not options.chromium:
    152       print "A chromium checkout (-c) is required in (semi-)automatic mode."
    153       return False
    154     if not options.manual and not options.author:
    155       print "Specify your chromium.org email with -a in (semi-)automatic mode."
    156       return False
    157 
    158     options.tbr_commit = not options.manual
    159     return True
    160 
    161   def _Steps(self):
    162     return [
    163       Preparation,
    164       DetectLastPush,
    165       CheckChromium,
    166       DetermineV8Sheriff,
    167       SwitchChromium,
    168       UpdateChromiumCheckout,
    169       UploadCL,
    170       SwitchV8,
    171       CleanUp,
    172     ]
    173 
    174 
    175 if __name__ == "__main__":  # pragma: no cover
    176   sys.exit(ChromiumRoll(CONFIG).Run())
    177