| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 the V8 project authors. All rights reserved. | 2 # Copyright 2013 the V8 project authors. All rights reserved. |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following | 10 # copyright notice, this list of conditions and the following |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 import argparse | 29 import argparse |
| 30 import sys | 30 import sys |
| 31 import tempfile | 31 import tempfile |
| 32 import urllib2 | 32 import urllib2 |
| 33 | 33 |
| 34 from common_includes import * | 34 from common_includes import * |
| 35 | 35 |
| 36 TRUNKBRANCH = "TRUNKBRANCH" | 36 TRUNKBRANCH = "TRUNKBRANCH" |
| 37 CHROMIUM = "CHROMIUM" | 37 CHROMIUM = "CHROMIUM" |
| 38 DEPS_FILE = "DEPS_FILE" | 38 DEPS_FILE = "DEPS_FILE" |
| 39 NEW_CHANGELOG_FILE = "NEW_CHANGELOG_FILE" |
| 39 | 40 |
| 40 CONFIG = { | 41 CONFIG = { |
| 41 BRANCHNAME: "prepare-push", | 42 BRANCHNAME: "prepare-push", |
| 42 TRUNKBRANCH: "trunk-push", | 43 TRUNKBRANCH: "trunk-push", |
| 43 PERSISTFILE_BASENAME: "/tmp/v8-push-to-trunk-tempfile", | 44 PERSISTFILE_BASENAME: "/tmp/v8-push-to-trunk-tempfile", |
| 44 TEMP_BRANCH: "prepare-push-temporary-branch-created-by-script", | 45 TEMP_BRANCH: "prepare-push-temporary-branch-created-by-script", |
| 45 DOT_GIT_LOCATION: ".git", | 46 DOT_GIT_LOCATION: ".git", |
| 46 VERSION_FILE: "src/version.cc", | 47 VERSION_FILE: "src/version.cc", |
| 47 CHANGELOG_FILE: "ChangeLog", | 48 CHANGELOG_FILE: "ChangeLog", |
| 49 NEW_CHANGELOG_FILE: "/tmp/v8-push-to-trunk-tempfile-new-changelog", |
| 48 CHANGELOG_ENTRY_FILE: "/tmp/v8-push-to-trunk-tempfile-changelog-entry", | 50 CHANGELOG_ENTRY_FILE: "/tmp/v8-push-to-trunk-tempfile-changelog-entry", |
| 49 PATCH_FILE: "/tmp/v8-push-to-trunk-tempfile-patch-file", | 51 PATCH_FILE: "/tmp/v8-push-to-trunk-tempfile-patch-file", |
| 50 COMMITMSG_FILE: "/tmp/v8-push-to-trunk-tempfile-commitmsg", | 52 COMMITMSG_FILE: "/tmp/v8-push-to-trunk-tempfile-commitmsg", |
| 51 DEPS_FILE: "DEPS", | 53 DEPS_FILE: "DEPS", |
| 52 } | 54 } |
| 53 | 55 |
| 54 PUSH_MESSAGE_SUFFIX = " (based on bleeding_edge revision r%d)" | 56 PUSH_MESSAGE_SUFFIX = " (based on bleeding_edge revision r%d)" |
| 55 PUSH_MESSAGE_RE = re.compile(r".* \(based on bleeding_edge revision r(\d+)\)$") | 57 PUSH_MESSAGE_RE = re.compile(r".* \(based on bleeding_edge revision r(\d+)\)$") |
| 56 | 58 |
| 57 | 59 |
| 58 class PushToTrunkOptions(CommonOptions): | |
| 59 @staticmethod | |
| 60 def MakeForcedOptions(author, reviewer, chrome_path): | |
| 61 """Convenience wrapper.""" | |
| 62 class Options(object): | |
| 63 pass | |
| 64 options = Options() | |
| 65 options.step = 0 | |
| 66 options.last_push = None | |
| 67 options.last_bleeding_edge = None | |
| 68 options.force = True | |
| 69 options.manual = False | |
| 70 options.chromium = chrome_path | |
| 71 options.reviewer = reviewer | |
| 72 options.author = author | |
| 73 return PushToTrunkOptions(options) | |
| 74 | |
| 75 def __init__(self, options): | |
| 76 super(PushToTrunkOptions, self).__init__(options, options.manual) | |
| 77 self.requires_editor = not options.force | |
| 78 self.wait_for_lgtm = not options.force | |
| 79 self.tbr_commit = not options.manual | |
| 80 self.last_push = options.last_push | |
| 81 self.reviewer = options.reviewer | |
| 82 self.chromium = options.chromium | |
| 83 self.last_bleeding_edge = getattr(options, 'last_bleeding_edge', None) | |
| 84 self.author = getattr(options, 'author', None) | |
| 85 | |
| 86 | |
| 87 class Preparation(Step): | 60 class Preparation(Step): |
| 88 MESSAGE = "Preparation." | 61 MESSAGE = "Preparation." |
| 89 | 62 |
| 90 def RunStep(self): | 63 def RunStep(self): |
| 91 self.InitialEnvironmentChecks() | 64 self.InitialEnvironmentChecks() |
| 92 self.CommonPrepare() | 65 self.CommonPrepare() |
| 93 self.PrepareBranch() | 66 self.PrepareBranch() |
| 94 self.DeleteBranch(self.Config(TRUNKBRANCH)) | 67 self.DeleteBranch(self.Config(TRUNKBRANCH)) |
| 95 | 68 |
| 96 | 69 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 115 | 88 |
| 116 if self._options.last_bleeding_edge: | 89 if self._options.last_bleeding_edge: |
| 117 # Read the bleeding edge revision of the last push from a command-line | 90 # Read the bleeding edge revision of the last push from a command-line |
| 118 # option. | 91 # option. |
| 119 last_push_bleeding_edge = self._options.last_bleeding_edge | 92 last_push_bleeding_edge = self._options.last_bleeding_edge |
| 120 else: | 93 else: |
| 121 # Retrieve the bleeding edge revision of the last push from the text in | 94 # Retrieve the bleeding edge revision of the last push from the text in |
| 122 # the push commit message. | 95 # the push commit message. |
| 123 last_push_title = self.GitLog(n=1, format="%s", git_hash=last_push) | 96 last_push_title = self.GitLog(n=1, format="%s", git_hash=last_push) |
| 124 last_push_be_svn = PUSH_MESSAGE_RE.match(last_push_title).group(1) | 97 last_push_be_svn = PUSH_MESSAGE_RE.match(last_push_title).group(1) |
| 125 if not last_push_be_svn: | 98 if not last_push_be_svn: # pragma: no cover |
| 126 self.Die("Could not retrieve bleeding edge revision for trunk push %s" | 99 self.Die("Could not retrieve bleeding edge revision for trunk push %s" |
| 127 % last_push) | 100 % last_push) |
| 128 last_push_bleeding_edge = self.GitSVNFindGitHash(last_push_be_svn) | 101 last_push_bleeding_edge = self.GitSVNFindGitHash(last_push_be_svn) |
| 129 if not last_push_bleeding_edge: | 102 if not last_push_bleeding_edge: # pragma: no cover |
| 130 self.Die("Could not retrieve bleeding edge git hash for trunk push %s" | 103 self.Die("Could not retrieve bleeding edge git hash for trunk push %s" |
| 131 % last_push) | 104 % last_push) |
| 132 | 105 |
| 133 # TODO(machenbach): last_push_trunk points to the svn revision on trunk. | 106 # TODO(machenbach): last_push_trunk points to the svn revision on trunk. |
| 134 # It is not used yet but we'll need it for retrieving the current version. | 107 # It is not used yet but we'll need it for retrieving the current version. |
| 135 self["last_push_trunk"] = last_push | 108 self["last_push_trunk"] = last_push |
| 136 # TODO(machenbach): This currently points to the prepare push revision that | 109 # TODO(machenbach): This currently points to the prepare push revision that |
| 137 # will be deprecated soon. After the deprecation it will point to the last | 110 # will be deprecated soon. After the deprecation it will point to the last |
| 138 # bleeding_edge revision that went into the last push. | 111 # bleeding_edge revision that went into the last push. |
| 139 self["last_push_bleeding_edge"] = last_push_bleeding_edge | 112 self["last_push_bleeding_edge"] = last_push_bleeding_edge |
| 140 | 113 |
| 141 | 114 |
| 142 class PrepareChangeLog(Step): | 115 class PrepareChangeLog(Step): |
| 143 MESSAGE = "Prepare raw ChangeLog entry." | 116 MESSAGE = "Prepare raw ChangeLog entry." |
| 144 | 117 |
| 145 def Reload(self, body): | 118 def Reload(self, body): |
| 146 """Attempts to reload the commit message from rietveld in order to allow | 119 """Attempts to reload the commit message from rietveld in order to allow |
| 147 late changes to the LOG flag. Note: This is brittle to future changes of | 120 late changes to the LOG flag. Note: This is brittle to future changes of |
| 148 the web page name or structure. | 121 the web page name or structure. |
| 149 """ | 122 """ |
| 150 match = re.search(r"^Review URL: https://codereview\.chromium\.org/(\d+)$", | 123 match = re.search(r"^Review URL: https://codereview\.chromium\.org/(\d+)$", |
| 151 body, flags=re.M) | 124 body, flags=re.M) |
| 152 if match: | 125 if match: |
| 153 cl_url = ("https://codereview.chromium.org/%s/description" | 126 cl_url = ("https://codereview.chromium.org/%s/description" |
| 154 % match.group(1)) | 127 % match.group(1)) |
| 155 try: | 128 try: |
| 156 # Fetch from Rietveld but only retry once with one second delay since | 129 # Fetch from Rietveld but only retry once with one second delay since |
| 157 # there might be many revisions. | 130 # there might be many revisions. |
| 158 body = self.ReadURL(cl_url, wait_plan=[1]) | 131 body = self.ReadURL(cl_url, wait_plan=[1]) |
| 159 except urllib2.URLError: | 132 except urllib2.URLError: # pragma: no cover |
| 160 pass | 133 pass |
| 161 return body | 134 return body |
| 162 | 135 |
| 163 def RunStep(self): | 136 def RunStep(self): |
| 164 # These version numbers are used again later for the trunk commit. | 137 # These version numbers are used again later for the trunk commit. |
| 165 self.ReadAndPersistVersion() | 138 self.ReadAndPersistVersion() |
| 166 self["date"] = self.GetDate() | 139 self["date"] = self.GetDate() |
| 167 self["version"] = "%s.%s.%s" % (self["major"], | 140 self["version"] = "%s.%s.%s" % (self["major"], |
| 168 self["minor"], | 141 self["minor"], |
| 169 self["build"]) | 142 self["build"]) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 199 | 172 |
| 200 class EditChangeLog(Step): | 173 class EditChangeLog(Step): |
| 201 MESSAGE = "Edit ChangeLog entry." | 174 MESSAGE = "Edit ChangeLog entry." |
| 202 | 175 |
| 203 def RunStep(self): | 176 def RunStep(self): |
| 204 print ("Please press <Return> to have your EDITOR open the ChangeLog " | 177 print ("Please press <Return> to have your EDITOR open the ChangeLog " |
| 205 "entry, then edit its contents to your liking. When you're done, " | 178 "entry, then edit its contents to your liking. When you're done, " |
| 206 "save the file and exit your EDITOR. ") | 179 "save the file and exit your EDITOR. ") |
| 207 self.ReadLine(default="") | 180 self.ReadLine(default="") |
| 208 self.Editor(self.Config(CHANGELOG_ENTRY_FILE)) | 181 self.Editor(self.Config(CHANGELOG_ENTRY_FILE)) |
| 209 handle, new_changelog = tempfile.mkstemp() | |
| 210 os.close(handle) | |
| 211 | 182 |
| 212 # Strip comments and reformat with correct indentation. | 183 # Strip comments and reformat with correct indentation. |
| 213 changelog_entry = FileToText(self.Config(CHANGELOG_ENTRY_FILE)).rstrip() | 184 changelog_entry = FileToText(self.Config(CHANGELOG_ENTRY_FILE)).rstrip() |
| 214 changelog_entry = StripComments(changelog_entry) | 185 changelog_entry = StripComments(changelog_entry) |
| 215 changelog_entry = "\n".join(map(Fill80, changelog_entry.splitlines())) | 186 changelog_entry = "\n".join(map(Fill80, changelog_entry.splitlines())) |
| 216 changelog_entry = changelog_entry.lstrip() | 187 changelog_entry = changelog_entry.lstrip() |
| 217 | 188 |
| 218 if changelog_entry == "": | 189 if changelog_entry == "": # pragma: no cover |
| 219 self.Die("Empty ChangeLog entry.") | 190 self.Die("Empty ChangeLog entry.") |
| 220 | 191 |
| 221 with open(new_changelog, "w") as f: | 192 # Safe new change log for adding it later to the trunk patch. |
| 222 f.write(changelog_entry) | 193 TextToFile(changelog_entry, self.Config(NEW_CHANGELOG_FILE)) |
| 223 f.write("\n\n\n") # Explicitly insert two empty lines. | |
| 224 | 194 |
| 225 AppendToFile(FileToText(self.Config(CHANGELOG_FILE)), new_changelog) | 195 old_change_log = FileToText(self.Config(CHANGELOG_FILE)) |
| 226 TextToFile(FileToText(new_changelog), self.Config(CHANGELOG_FILE)) | 196 new_change_log = "%s\n\n\n%s" % (changelog_entry, old_change_log) |
| 227 os.remove(new_changelog) | 197 TextToFile(new_change_log, self.Config(CHANGELOG_FILE)) |
| 228 | 198 |
| 229 | 199 |
| 230 class IncrementVersion(Step): | 200 class IncrementVersion(Step): |
| 231 MESSAGE = "Increment version number." | 201 MESSAGE = "Increment version number." |
| 232 | 202 |
| 233 def RunStep(self): | 203 def RunStep(self): |
| 234 new_build = str(int(self["build"]) + 1) | 204 new_build = str(int(self["build"]) + 1) |
| 235 | 205 |
| 236 if self.Confirm(("Automatically increment BUILD_NUMBER? (Saying 'n' will " | 206 if self.Confirm(("Automatically increment BUILD_NUMBER? (Saying 'n' will " |
| 237 "fire up your EDITOR on %s so you can make arbitrary " | 207 "fire up your EDITOR on %s so you can make arbitrary " |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 suffix = PUSH_MESSAGE_SUFFIX % int(self["svn_revision"]) | 283 suffix = PUSH_MESSAGE_SUFFIX % int(self["svn_revision"]) |
| 314 text = MSub(r"^(Version \d+\.\d+\.\d+)$", "\\1%s" % suffix, text) | 284 text = MSub(r"^(Version \d+\.\d+\.\d+)$", "\\1%s" % suffix, text) |
| 315 | 285 |
| 316 # Remove indentation and merge paragraphs into single long lines, keeping | 286 # Remove indentation and merge paragraphs into single long lines, keeping |
| 317 # empty lines between them. | 287 # empty lines between them. |
| 318 def SplitMapJoin(split_text, fun, join_text): | 288 def SplitMapJoin(split_text, fun, join_text): |
| 319 return lambda text: join_text.join(map(fun, text.split(split_text))) | 289 return lambda text: join_text.join(map(fun, text.split(split_text))) |
| 320 strip = lambda line: line.strip() | 290 strip = lambda line: line.strip() |
| 321 text = SplitMapJoin("\n\n", SplitMapJoin("\n", strip, " "), "\n\n")(text) | 291 text = SplitMapJoin("\n\n", SplitMapJoin("\n", strip, " "), "\n\n")(text) |
| 322 | 292 |
| 323 if not text: | 293 if not text: # pragma: no cover |
| 324 self.Die("Commit message editing failed.") | 294 self.Die("Commit message editing failed.") |
| 325 TextToFile(text, self.Config(COMMITMSG_FILE)) | 295 TextToFile(text, self.Config(COMMITMSG_FILE)) |
| 326 os.remove(self.Config(CHANGELOG_ENTRY_FILE)) | 296 os.remove(self.Config(CHANGELOG_ENTRY_FILE)) |
| 327 | 297 |
| 328 | 298 |
| 329 class NewBranch(Step): | 299 class NewBranch(Step): |
| 330 MESSAGE = "Create a new branch from trunk." | 300 MESSAGE = "Create a new branch from trunk." |
| 331 | 301 |
| 332 def RunStep(self): | 302 def RunStep(self): |
| 333 self.GitCreateBranch(self.Config(TRUNKBRANCH), "svn/trunk") | 303 self.GitCreateBranch(self.Config(TRUNKBRANCH), "svn/trunk") |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 Command("rm", "-f %s*" % self.Config(COMMITMSG_FILE)) | 340 Command("rm", "-f %s*" % self.Config(COMMITMSG_FILE)) |
| 371 | 341 |
| 372 | 342 |
| 373 class SanityCheck(Step): | 343 class SanityCheck(Step): |
| 374 MESSAGE = "Sanity check." | 344 MESSAGE = "Sanity check." |
| 375 | 345 |
| 376 def RunStep(self): | 346 def RunStep(self): |
| 377 if not self.Confirm("Please check if your local checkout is sane: Inspect " | 347 if not self.Confirm("Please check if your local checkout is sane: Inspect " |
| 378 "%s, compile, run tests. Do you want to commit this new trunk " | 348 "%s, compile, run tests. Do you want to commit this new trunk " |
| 379 "revision to the repository?" % self.Config(VERSION_FILE)): | 349 "revision to the repository?" % self.Config(VERSION_FILE)): |
| 380 self.Die("Execution canceled.") | 350 self.Die("Execution canceled.") # pragma: no cover |
| 381 | 351 |
| 382 | 352 |
| 383 class CommitSVN(Step): | 353 class CommitSVN(Step): |
| 384 MESSAGE = "Commit to SVN." | 354 MESSAGE = "Commit to SVN." |
| 385 | 355 |
| 386 def RunStep(self): | 356 def RunStep(self): |
| 387 result = self.GitSVNDCommit() | 357 result = self.GitSVNDCommit() |
| 388 if not result: | 358 if not result: # pragma: no cover |
| 389 self.Die("'git svn dcommit' failed.") | 359 self.Die("'git svn dcommit' failed.") |
| 390 result = filter(lambda x: re.search(r"^Committed r[0-9]+", x), | 360 result = filter(lambda x: re.search(r"^Committed r[0-9]+", x), |
| 391 result.splitlines()) | 361 result.splitlines()) |
| 392 if len(result) > 0: | 362 if len(result) > 0: |
| 393 self["trunk_revision"] = re.sub(r"^Committed r([0-9]+)", r"\1",result[0]) | 363 self["trunk_revision"] = re.sub(r"^Committed r([0-9]+)", r"\1",result[0]) |
| 394 | 364 |
| 395 # Sometimes grepping for the revision fails. No idea why. If you figure | 365 # Sometimes grepping for the revision fails. No idea why. If you figure |
| 396 # out why it is flaky, please do fix it properly. | 366 # out why it is flaky, please do fix it properly. |
| 397 if not self["trunk_revision"]: | 367 if not self["trunk_revision"]: |
| 398 print("Sorry, grepping for the SVN revision failed. Please look for it " | 368 print("Sorry, grepping for the SVN revision failed. Please look for it " |
| (...skipping 29 matching lines...) Expand all Loading... |
| 428 | 398 |
| 429 class SwitchChromium(Step): | 399 class SwitchChromium(Step): |
| 430 MESSAGE = "Switch to Chromium checkout." | 400 MESSAGE = "Switch to Chromium checkout." |
| 431 REQUIRES = "chrome_path" | 401 REQUIRES = "chrome_path" |
| 432 | 402 |
| 433 def RunStep(self): | 403 def RunStep(self): |
| 434 self["v8_path"] = os.getcwd() | 404 self["v8_path"] = os.getcwd() |
| 435 os.chdir(self["chrome_path"]) | 405 os.chdir(self["chrome_path"]) |
| 436 self.InitialEnvironmentChecks() | 406 self.InitialEnvironmentChecks() |
| 437 # Check for a clean workdir. | 407 # Check for a clean workdir. |
| 438 if not self.GitIsWorkdirClean(): | 408 if not self.GitIsWorkdirClean(): # pragma: no cover |
| 439 self.Die("Workspace is not clean. Please commit or undo your changes.") | 409 self.Die("Workspace is not clean. Please commit or undo your changes.") |
| 440 # Assert that the DEPS file is there. | 410 # Assert that the DEPS file is there. |
| 441 if not os.path.exists(self.Config(DEPS_FILE)): | 411 if not os.path.exists(self.Config(DEPS_FILE)): # pragma: no cover |
| 442 self.Die("DEPS file not present.") | 412 self.Die("DEPS file not present.") |
| 443 | 413 |
| 444 | 414 |
| 445 class UpdateChromiumCheckout(Step): | 415 class UpdateChromiumCheckout(Step): |
| 446 MESSAGE = "Update the checkout and create a new branch." | 416 MESSAGE = "Update the checkout and create a new branch." |
| 447 REQUIRES = "chrome_path" | 417 REQUIRES = "chrome_path" |
| 448 | 418 |
| 449 def RunStep(self): | 419 def RunStep(self): |
| 450 os.chdir(self["chrome_path"]) | 420 os.chdir(self["chrome_path"]) |
| 451 self.GitCheckout("master") | 421 self.GitCheckout("master") |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 | 461 |
| 492 | 462 |
| 493 class CleanUp(Step): | 463 class CleanUp(Step): |
| 494 MESSAGE = "Done!" | 464 MESSAGE = "Done!" |
| 495 | 465 |
| 496 def RunStep(self): | 466 def RunStep(self): |
| 497 if self["chrome_path"]: | 467 if self["chrome_path"]: |
| 498 print("Congratulations, you have successfully created the trunk " | 468 print("Congratulations, you have successfully created the trunk " |
| 499 "revision %s and rolled it into Chromium. Please don't forget to " | 469 "revision %s and rolled it into Chromium. Please don't forget to " |
| 500 "update the v8rel spreadsheet:" % self["version"]) | 470 "update the v8rel spreadsheet:" % self["version"]) |
| 501 else: | 471 else: # pragma: no cover |
| 502 print("Congratulations, you have successfully created the trunk " | 472 print("Congratulations, you have successfully created the trunk " |
| 503 "revision %s. Please don't forget to roll this new version into " | 473 "revision %s. Please don't forget to roll this new version into " |
| 504 "Chromium, and to update the v8rel spreadsheet:" | 474 "Chromium, and to update the v8rel spreadsheet:" |
| 505 % self["version"]) | 475 % self["version"]) |
| 506 print "%s\ttrunk\t%s" % (self["version"], | 476 print "%s\ttrunk\t%s" % (self["version"], |
| 507 self["trunk_revision"]) | 477 self["trunk_revision"]) |
| 508 | 478 |
| 509 self.CommonCleanup() | 479 self.CommonCleanup() |
| 510 if self.Config(TRUNKBRANCH) != self["current_branch"]: | 480 if self.Config(TRUNKBRANCH) != self["current_branch"]: |
| 511 self.GitDeleteBranch(self.Config(TRUNKBRANCH)) | 481 self.GitDeleteBranch(self.Config(TRUNKBRANCH)) |
| 512 | 482 |
| 513 | 483 |
| 514 def RunPushToTrunk(config, | 484 class PushToTrunk(ScriptsBase): |
| 515 options, | 485 def _PrepareOptions(self, parser): |
| 516 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): | 486 group = parser.add_mutually_exclusive_group() |
| 517 step_classes = [ | 487 group.add_argument("-f", "--force", |
| 518 Preparation, | 488 help="Don't prompt the user.", |
| 519 FreshBranch, | 489 default=False, action="store_true") |
| 520 DetectLastPush, | 490 group.add_argument("-m", "--manual", |
| 521 PrepareChangeLog, | 491 help="Prompt the user at every important step.", |
| 522 EditChangeLog, | 492 default=False, action="store_true") |
| 523 IncrementVersion, | 493 parser.add_argument("-b", "--last-bleeding-edge", |
| 524 CommitLocal, | 494 help=("The git commit ID of the last bleeding edge " |
| 525 UploadStep, | 495 "revision that was pushed to trunk. This is " |
| 526 CommitRepository, | 496 "used for the auto-generated ChangeLog entry.")) |
| 527 StragglerCommits, | 497 parser.add_argument("-c", "--chromium", |
| 528 SquashCommits, | 498 help=("The path to your Chromium src/ " |
| 529 NewBranch, | 499 "directory to automate the V8 roll.")) |
| 530 ApplyChanges, | 500 parser.add_argument("-l", "--last-push", |
| 531 SetVersion, | 501 help="The git commit ID of the last push to trunk.") |
| 532 CommitTrunk, | |
| 533 SanityCheck, | |
| 534 CommitSVN, | |
| 535 TagRevision, | |
| 536 CheckChromium, | |
| 537 SwitchChromium, | |
| 538 UpdateChromiumCheckout, | |
| 539 UploadCL, | |
| 540 SwitchV8, | |
| 541 CleanUp, | |
| 542 ] | |
| 543 | 502 |
| 544 RunScript(step_classes, config, options, side_effect_handler) | 503 def _ProcessOptions(self, options): # pragma: no cover |
| 504 if not options.manual and not options.reviewer: |
| 505 print "A reviewer (-r) is required in (semi-)automatic mode." |
| 506 return False |
| 507 if not options.manual and not options.chromium: |
| 508 print "A chromium checkout (-c) is required in (semi-)automatic mode." |
| 509 return False |
| 510 if not options.manual and not options.author: |
| 511 print "Specify your chromium.org email with -a in (semi-)automatic mode." |
| 512 return False |
| 513 |
| 514 options.tbr_commit = not options.manual |
| 515 return True |
| 516 |
| 517 def _Steps(self): |
| 518 return [ |
| 519 Preparation, |
| 520 FreshBranch, |
| 521 DetectLastPush, |
| 522 PrepareChangeLog, |
| 523 EditChangeLog, |
| 524 IncrementVersion, |
| 525 CommitLocal, |
| 526 UploadStep, |
| 527 CommitRepository, |
| 528 StragglerCommits, |
| 529 SquashCommits, |
| 530 NewBranch, |
| 531 ApplyChanges, |
| 532 SetVersion, |
| 533 CommitTrunk, |
| 534 SanityCheck, |
| 535 CommitSVN, |
| 536 TagRevision, |
| 537 CheckChromium, |
| 538 SwitchChromium, |
| 539 UpdateChromiumCheckout, |
| 540 UploadCL, |
| 541 SwitchV8, |
| 542 CleanUp, |
| 543 ] |
| 545 | 544 |
| 546 | 545 |
| 547 def BuildOptions(): | 546 if __name__ == "__main__": # pragma: no cover |
| 548 parser = argparse.ArgumentParser() | 547 sys.exit(PushToTrunk(CONFIG).Run()) |
| 549 group = parser.add_mutually_exclusive_group() | |
| 550 group.add_argument("-f", "--force", | |
| 551 help="Don't prompt the user.", | |
| 552 default=False, action="store_true") | |
| 553 group.add_argument("-m", "--manual", | |
| 554 help="Prompt the user at every important step.", | |
| 555 default=False, action="store_true") | |
| 556 parser.add_argument("-a", "--author", | |
| 557 help="The author email used for rietveld.") | |
| 558 parser.add_argument("-b", "--last-bleeding-edge", | |
| 559 help=("The git commit ID of the last bleeding edge " | |
| 560 "revision that was pushed to trunk. This is used " | |
| 561 "for the auto-generated ChangeLog entry.")) | |
| 562 parser.add_argument("-c", "--chromium", | |
| 563 help=("The path to your Chromium src/ directory to " | |
| 564 "automate the V8 roll.")) | |
| 565 parser.add_argument("-l", "--last-push", | |
| 566 help="The git commit ID of the last push to trunk.") | |
| 567 parser.add_argument("-r", "--reviewer", | |
| 568 help="The account name to be used for reviews.") | |
| 569 parser.add_argument("-s", "--step", | |
| 570 help="The step where to start work. Default: 0.", | |
| 571 default=0, type=int) | |
| 572 return parser | |
| 573 | |
| 574 | |
| 575 def ProcessOptions(options): | |
| 576 if options.step < 0: | |
| 577 print "Bad step number %d" % options.step | |
| 578 return False | |
| 579 if not options.manual and not options.reviewer: | |
| 580 print "A reviewer (-r) is required in (semi-)automatic mode." | |
| 581 return False | |
| 582 if not options.manual and not options.chromium: | |
| 583 print "A chromium checkout (-c) is required in (semi-)automatic mode." | |
| 584 return False | |
| 585 if not options.manual and not options.author: | |
| 586 print "Specify your chromium.org email with -a in (semi-)automatic mode." | |
| 587 return False | |
| 588 return True | |
| 589 | |
| 590 | |
| 591 def Main(): | |
| 592 parser = BuildOptions() | |
| 593 options = parser.parse_args() | |
| 594 if not ProcessOptions(options): | |
| 595 parser.print_help() | |
| 596 return 1 | |
| 597 RunPushToTrunk(CONFIG, PushToTrunkOptions(options)) | |
| 598 | |
| 599 if __name__ == "__main__": | |
| 600 sys.exit(Main()) | |
| OLD | NEW |