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