| OLD | NEW | 
|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # Copyright 2014 the V8 project authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be | 
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. | 
| 5 | 5 | 
| 6 # This script retrieves the history of all V8 branches and trunk revisions and | 6 # This script retrieves the history of all V8 branches and trunk revisions and | 
| 7 # their corresponding Chromium revisions. | 7 # their corresponding Chromium revisions. | 
| 8 | 8 | 
| 9 # Requires a chromium checkout with branch heads: | 9 # Requires a chromium checkout with branch heads: | 
| 10 # gclient sync --with_branch_heads | 10 # gclient sync --with_branch_heads | 
| 11 # gclient fetch | 11 # gclient fetch | 
| 12 | 12 | 
| 13 import argparse | 13 import argparse | 
| 14 import csv | 14 import csv | 
| 15 import itertools | 15 import itertools | 
| 16 import json | 16 import json | 
| 17 import os | 17 import os | 
| 18 import re | 18 import re | 
| 19 import sys | 19 import sys | 
| 20 | 20 | 
| 21 from common_includes import * | 21 from common_includes import * | 
| 22 | 22 | 
| 23 DEPS_FILE = "DEPS_FILE" |  | 
| 24 CHROMIUM = "CHROMIUM" | 23 CHROMIUM = "CHROMIUM" | 
| 25 | 24 | 
| 26 CONFIG = { | 25 CONFIG = { | 
| 27   BRANCHNAME: "retrieve-v8-releases", | 26   BRANCHNAME: "retrieve-v8-releases", | 
| 28   PERSISTFILE_BASENAME: "/tmp/v8-releases-tempfile", | 27   PERSISTFILE_BASENAME: "/tmp/v8-releases-tempfile", | 
| 29   DOT_GIT_LOCATION: ".git", | 28   DOT_GIT_LOCATION: ".git", | 
| 30   VERSION_FILE: "src/version.cc", | 29   VERSION_FILE: "src/version.cc", | 
| 31   DEPS_FILE: "DEPS", |  | 
| 32 } | 30 } | 
| 33 | 31 | 
| 34 # Expression for retrieving the bleeding edge revision from a commit message. | 32 # Expression for retrieving the bleeding edge revision from a commit message. | 
| 35 PUSH_MESSAGE_RE = re.compile(r".* \(based on bleeding_edge revision r(\d+)\)$") | 33 PUSH_MESSAGE_RE = re.compile(r".* \(based on bleeding_edge revision r(\d+)\)$") | 
| 36 | 34 | 
| 37 # Expression for retrieving the merged patches from a merge commit message | 35 # Expression for retrieving the merged patches from a merge commit message | 
| 38 # (old and new format). | 36 # (old and new format). | 
| 39 MERGE_MESSAGE_RE = re.compile(r"^.*[M|m]erged (.+)(\)| into).*$", re.M) | 37 MERGE_MESSAGE_RE = re.compile(r"^.*[M|m]erged (.+)(\)| into).*$", re.M) | 
| 40 | 38 | 
| 41 # Expression for retrieving reverted patches from a commit message (old and | 39 # Expression for retrieving reverted patches from a commit message (old and | 
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 261     else:  # pragma: no cover | 259     else:  # pragma: no cover | 
| 262       # Retrieve history for a specified branch. | 260       # Retrieve history for a specified branch. | 
| 263       assert self._options.branch in branches + ["trunk", "bleeding_edge"] | 261       assert self._options.branch in branches + ["trunk", "bleeding_edge"] | 
| 264       releases += self.GetReleasesFromBranch(self._options.branch) | 262       releases += self.GetReleasesFromBranch(self._options.branch) | 
| 265 | 263 | 
| 266     self["releases"] = sorted(releases, | 264     self["releases"] = sorted(releases, | 
| 267                               key=lambda r: SortingKey(r["version"]), | 265                               key=lambda r: SortingKey(r["version"]), | 
| 268                               reverse=True) | 266                               reverse=True) | 
| 269 | 267 | 
| 270 | 268 | 
| 271 # TODO(machenbach): Parts of the Chromium setup are c/p from the chromium_roll |  | 
| 272 # script -> unify. |  | 
| 273 class CheckChromium(Step): |  | 
| 274   MESSAGE = "Check the chromium checkout." |  | 
| 275 |  | 
| 276   def Run(self): |  | 
| 277     self["chrome_path"] = self._options.chromium |  | 
| 278 |  | 
| 279 |  | 
| 280 class SwitchChromium(Step): | 269 class SwitchChromium(Step): | 
| 281   MESSAGE = "Switch to Chromium checkout." | 270   MESSAGE = "Switch to Chromium checkout." | 
| 282   REQUIRES = "chrome_path" |  | 
| 283 | 271 | 
| 284   def RunStep(self): | 272   def RunStep(self): | 
| 285     self["v8_path"] = os.getcwd() | 273     cwd = self._options.chromium | 
| 286     os.chdir(self["chrome_path"]) |  | 
| 287     # Check for a clean workdir. | 274     # Check for a clean workdir. | 
| 288     if not self.GitIsWorkdirClean():  # pragma: no cover | 275     if not self.GitIsWorkdirClean(cwd=cwd):  # pragma: no cover | 
| 289       self.Die("Workspace is not clean. Please commit or undo your changes.") | 276       self.Die("Workspace is not clean. Please commit or undo your changes.") | 
| 290     # Assert that the DEPS file is there. | 277     # Assert that the DEPS file is there. | 
| 291     if not os.path.exists(self.Config(DEPS_FILE)):  # pragma: no cover | 278     if not os.path.exists(os.path.join(cwd, "DEPS")):  # pragma: no cover | 
| 292       self.Die("DEPS file not present.") | 279       self.Die("DEPS file not present.") | 
| 293 | 280 | 
| 294 | 281 | 
| 295 class UpdateChromiumCheckout(Step): | 282 class UpdateChromiumCheckout(Step): | 
| 296   MESSAGE = "Update the checkout and create a new branch." | 283   MESSAGE = "Update the checkout and create a new branch." | 
| 297   REQUIRES = "chrome_path" |  | 
| 298 | 284 | 
| 299   def RunStep(self): | 285   def RunStep(self): | 
| 300     os.chdir(self["chrome_path"]) | 286     cwd = self._options.chromium | 
| 301     self.GitCheckout("master") | 287     self.GitCheckout("master", cwd=cwd) | 
| 302     self.GitPull() | 288     self.GitPull(cwd=cwd) | 
| 303     self.GitCreateBranch(self.Config(BRANCHNAME)) | 289     self.GitCreateBranch(self.Config(BRANCHNAME), cwd=cwd) | 
| 304 | 290 | 
| 305 | 291 | 
| 306 def ConvertToCommitNumber(step, revision): | 292 def ConvertToCommitNumber(step, revision): | 
| 307   # Simple check for git hashes. | 293   # Simple check for git hashes. | 
| 308   if revision.isdigit() and len(revision) < 8: | 294   if revision.isdigit() and len(revision) < 8: | 
| 309     return revision | 295     return revision | 
| 310   try: | 296   return step.GitConvertToSVNRevision( | 
| 311     # TODO(machenbach): Add cwd to git calls. | 297       revision, cwd=os.path.join(step._options.chromium, "v8")) | 
| 312     os.chdir(os.path.join(step["chrome_path"], "v8")) |  | 
| 313     return step.GitConvertToSVNRevision(revision) |  | 
| 314   finally: |  | 
| 315     os.chdir(step["chrome_path"]) |  | 
| 316 | 298 | 
| 317 | 299 | 
| 318 class RetrieveChromiumV8Releases(Step): | 300 class RetrieveChromiumV8Releases(Step): | 
| 319   MESSAGE = "Retrieve V8 releases from Chromium DEPS." | 301   MESSAGE = "Retrieve V8 releases from Chromium DEPS." | 
| 320   REQUIRES = "chrome_path" |  | 
| 321 | 302 | 
| 322   def RunStep(self): | 303   def RunStep(self): | 
| 323     os.chdir(self["chrome_path"]) | 304     cwd = self._options.chromium | 
| 324 |  | 
| 325     releases = filter( | 305     releases = filter( | 
| 326         lambda r: r["branch"] in ["trunk", "bleeding_edge"], self["releases"]) | 306         lambda r: r["branch"] in ["trunk", "bleeding_edge"], self["releases"]) | 
| 327     if not releases:  # pragma: no cover | 307     if not releases:  # pragma: no cover | 
| 328       print "No releases detected. Skipping chromium history." | 308       print "No releases detected. Skipping chromium history." | 
| 329       return True | 309       return True | 
| 330 | 310 | 
| 331     # Update v8 checkout in chromium. | 311     # Update v8 checkout in chromium. | 
| 332     try: | 312     self.GitFetchOrigin(cwd=os.path.join(cwd, "v8")) | 
| 333       # TODO(machenbach): Add cwd to git calls. |  | 
| 334       os.chdir(os.path.join(self["chrome_path"], "v8")) |  | 
| 335       self.GitFetchOrigin() |  | 
| 336     finally: |  | 
| 337       os.chdir(self["chrome_path"]) |  | 
| 338 | 313 | 
| 339     oldest_v8_rev = int(releases[-1]["revision"]) | 314     oldest_v8_rev = int(releases[-1]["revision"]) | 
| 340 | 315 | 
| 341     cr_releases = [] | 316     cr_releases = [] | 
| 342     try: | 317     try: | 
| 343       for git_hash in self.GitLog(format="%H", grep="V8").splitlines(): | 318       for git_hash in self.GitLog( | 
| 344         if self._config[DEPS_FILE] not in self.GitChangedFiles(git_hash): | 319           format="%H", grep="V8", cwd=cwd).splitlines(): | 
|  | 320         if "DEPS" not in self.GitChangedFiles(git_hash, cwd=cwd): | 
| 345           continue | 321           continue | 
| 346         if not self.GitCheckoutFileSafe(self._config[DEPS_FILE], git_hash): | 322         if not self.GitCheckoutFileSafe("DEPS", git_hash, cwd=cwd): | 
| 347           break  # pragma: no cover | 323           break  # pragma: no cover | 
| 348         deps = FileToText(self.Config(DEPS_FILE)) | 324         deps = FileToText(os.path.join(cwd, "DEPS")) | 
| 349         match = DEPS_RE.search(deps) | 325         match = DEPS_RE.search(deps) | 
| 350         if match: | 326         if match: | 
| 351           cr_rev = self.GetCommitPositionNumber(git_hash) | 327           cr_rev = self.GetCommitPositionNumber(git_hash, cwd=cwd) | 
| 352           if cr_rev: | 328           if cr_rev: | 
| 353             v8_rev = ConvertToCommitNumber(self, match.group(1)) | 329             v8_rev = ConvertToCommitNumber(self, match.group(1)) | 
| 354             cr_releases.append([cr_rev, v8_rev]) | 330             cr_releases.append([cr_rev, v8_rev]) | 
| 355 | 331 | 
| 356           # Stop after reaching beyond the last v8 revision we want to update. | 332           # Stop after reaching beyond the last v8 revision we want to update. | 
| 357           # We need a small buffer for possible revert/reland frenzies. | 333           # We need a small buffer for possible revert/reland frenzies. | 
| 358           # TODO(machenbach): Subtraction is not git friendly. | 334           # TODO(machenbach): Subtraction is not git friendly. | 
| 359           if int(v8_rev) < oldest_v8_rev - 100: | 335           if int(v8_rev) < oldest_v8_rev - 100: | 
| 360             break  # pragma: no cover | 336             break  # pragma: no cover | 
| 361 | 337 | 
| 362     # Allow Ctrl-C interrupt. | 338     # Allow Ctrl-C interrupt. | 
| 363     except (KeyboardInterrupt, SystemExit):  # pragma: no cover | 339     except (KeyboardInterrupt, SystemExit):  # pragma: no cover | 
| 364       pass | 340       pass | 
| 365 | 341 | 
| 366     # Clean up. | 342     # Clean up. | 
| 367     self.GitCheckoutFileSafe(self._config[DEPS_FILE], "HEAD") | 343     self.GitCheckoutFileSafe("DEPS", "HEAD", cwd=cwd) | 
| 368 | 344 | 
| 369     # Add the chromium ranges to the v8 trunk and bleeding_edge releases. | 345     # Add the chromium ranges to the v8 trunk and bleeding_edge releases. | 
| 370     all_ranges = BuildRevisionRanges(cr_releases) | 346     all_ranges = BuildRevisionRanges(cr_releases) | 
| 371     releases_dict = dict((r["revision"], r) for r in releases) | 347     releases_dict = dict((r["revision"], r) for r in releases) | 
| 372     for revision, ranges in all_ranges.iteritems(): | 348     for revision, ranges in all_ranges.iteritems(): | 
| 373       releases_dict.get(revision, {})["chromium_revision"] = ranges | 349       releases_dict.get(revision, {})["chromium_revision"] = ranges | 
| 374 | 350 | 
| 375 | 351 | 
| 376 # TODO(machenbach): Unify common code with method above. | 352 # TODO(machenbach): Unify common code with method above. | 
| 377 class RietrieveChromiumBranches(Step): | 353 class RietrieveChromiumBranches(Step): | 
| 378   MESSAGE = "Retrieve Chromium branch information." | 354   MESSAGE = "Retrieve Chromium branch information." | 
| 379   REQUIRES = "chrome_path" |  | 
| 380 | 355 | 
| 381   def RunStep(self): | 356   def RunStep(self): | 
| 382     os.chdir(self["chrome_path"]) | 357     cwd = self._options.chromium | 
| 383 |  | 
| 384     trunk_releases = filter(lambda r: r["branch"] == "trunk", self["releases"]) | 358     trunk_releases = filter(lambda r: r["branch"] == "trunk", self["releases"]) | 
| 385     if not trunk_releases:  # pragma: no cover | 359     if not trunk_releases:  # pragma: no cover | 
| 386       print "No trunk releases detected. Skipping chromium history." | 360       print "No trunk releases detected. Skipping chromium history." | 
| 387       return True | 361       return True | 
| 388 | 362 | 
| 389     oldest_v8_rev = int(trunk_releases[-1]["revision"]) | 363     oldest_v8_rev = int(trunk_releases[-1]["revision"]) | 
| 390 | 364 | 
| 391     # Filter out irrelevant branches. | 365     # Filter out irrelevant branches. | 
| 392     branches = filter(lambda r: re.match(r"branch-heads/\d+", r), | 366     branches = filter(lambda r: re.match(r"branch-heads/\d+", r), | 
| 393                       self.GitRemotes()) | 367                       self.GitRemotes(cwd=cwd)) | 
| 394 | 368 | 
| 395     # Transform into pure branch numbers. | 369     # Transform into pure branch numbers. | 
| 396     branches = map(lambda r: int(re.match(r"branch-heads/(\d+)", r).group(1)), | 370     branches = map(lambda r: int(re.match(r"branch-heads/(\d+)", r).group(1)), | 
| 397                    branches) | 371                    branches) | 
| 398 | 372 | 
| 399     branches = sorted(branches, reverse=True) | 373     branches = sorted(branches, reverse=True) | 
| 400 | 374 | 
| 401     cr_branches = [] | 375     cr_branches = [] | 
| 402     try: | 376     try: | 
| 403       for branch in branches: | 377       for branch in branches: | 
| 404         if not self.GitCheckoutFileSafe(self._config[DEPS_FILE], | 378         if not self.GitCheckoutFileSafe("DEPS", | 
| 405                                         "branch-heads/%d" % branch): | 379                                         "branch-heads/%d" % branch, | 
|  | 380                                         cwd=cwd): | 
| 406           break  # pragma: no cover | 381           break  # pragma: no cover | 
| 407         deps = FileToText(self.Config(DEPS_FILE)) | 382         deps = FileToText(os.path.join(cwd, "DEPS")) | 
| 408         match = DEPS_RE.search(deps) | 383         match = DEPS_RE.search(deps) | 
| 409         if match: | 384         if match: | 
| 410           v8_rev = ConvertToCommitNumber(self, match.group(1)) | 385           v8_rev = ConvertToCommitNumber(self, match.group(1)) | 
| 411           cr_branches.append([str(branch), v8_rev]) | 386           cr_branches.append([str(branch), v8_rev]) | 
| 412 | 387 | 
| 413           # Stop after reaching beyond the last v8 revision we want to update. | 388           # Stop after reaching beyond the last v8 revision we want to update. | 
| 414           # We need a small buffer for possible revert/reland frenzies. | 389           # We need a small buffer for possible revert/reland frenzies. | 
| 415           # TODO(machenbach): Subtraction is not git friendly. | 390           # TODO(machenbach): Subtraction is not git friendly. | 
| 416           if int(v8_rev) < oldest_v8_rev - 100: | 391           if int(v8_rev) < oldest_v8_rev - 100: | 
| 417             break  # pragma: no cover | 392             break  # pragma: no cover | 
| 418 | 393 | 
| 419     # Allow Ctrl-C interrupt. | 394     # Allow Ctrl-C interrupt. | 
| 420     except (KeyboardInterrupt, SystemExit):  # pragma: no cover | 395     except (KeyboardInterrupt, SystemExit):  # pragma: no cover | 
| 421       pass | 396       pass | 
| 422 | 397 | 
| 423     # Clean up. | 398     # Clean up. | 
| 424     self.GitCheckoutFileSafe(self._config[DEPS_FILE], "HEAD") | 399     self.GitCheckoutFileSafe("DEPS", "HEAD", cwd=cwd) | 
| 425 | 400 | 
| 426     # Add the chromium branches to the v8 trunk releases. | 401     # Add the chromium branches to the v8 trunk releases. | 
| 427     all_ranges = BuildRevisionRanges(cr_branches) | 402     all_ranges = BuildRevisionRanges(cr_branches) | 
| 428     trunk_dict = dict((r["revision"], r) for r in trunk_releases) | 403     trunk_dict = dict((r["revision"], r) for r in trunk_releases) | 
| 429     for revision, ranges in all_ranges.iteritems(): | 404     for revision, ranges in all_ranges.iteritems(): | 
| 430       trunk_dict.get(revision, {})["chromium_branch"] = ranges | 405       trunk_dict.get(revision, {})["chromium_branch"] = ranges | 
| 431 | 406 | 
| 432 | 407 | 
| 433 class SwitchV8(Step): |  | 
| 434   MESSAGE = "Returning to V8 checkout." |  | 
| 435   REQUIRES = "chrome_path" |  | 
| 436 |  | 
| 437   def RunStep(self): |  | 
| 438     self.GitCheckout("master") |  | 
| 439     self.GitDeleteBranch(self.Config(BRANCHNAME)) |  | 
| 440     os.chdir(self["v8_path"]) |  | 
| 441 |  | 
| 442 |  | 
| 443 class CleanUp(Step): | 408 class CleanUp(Step): | 
| 444   MESSAGE = "Clean up." | 409   MESSAGE = "Clean up." | 
| 445 | 410 | 
| 446   def RunStep(self): | 411   def RunStep(self): | 
|  | 412     self.GitCheckout("master", cwd=self._options.chromium) | 
|  | 413     self.GitDeleteBranch(self.Config(BRANCHNAME), cwd=self._options.chromium) | 
| 447     self.CommonCleanup() | 414     self.CommonCleanup() | 
| 448 | 415 | 
| 449 | 416 | 
| 450 class WriteOutput(Step): | 417 class WriteOutput(Step): | 
| 451   MESSAGE = "Print output." | 418   MESSAGE = "Print output." | 
| 452 | 419 | 
| 453   def Run(self): | 420   def Run(self): | 
| 454     if self._options.csv: | 421     if self._options.csv: | 
| 455       with open(self._options.csv, "w") as f: | 422       with open(self._options.csv, "w") as f: | 
| 456         writer = csv.DictWriter(f, | 423         writer = csv.DictWriter(f, | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 481                         help="The maximum number of releases to track.") | 448                         help="The maximum number of releases to track.") | 
| 482     parser.add_argument("--json", help="Path to a JSON file for export.") | 449     parser.add_argument("--json", help="Path to a JSON file for export.") | 
| 483 | 450 | 
| 484   def _ProcessOptions(self, options):  # pragma: no cover | 451   def _ProcessOptions(self, options):  # pragma: no cover | 
| 485     return True | 452     return True | 
| 486 | 453 | 
| 487   def _Steps(self): | 454   def _Steps(self): | 
| 488     return [ | 455     return [ | 
| 489       Preparation, | 456       Preparation, | 
| 490       RetrieveV8Releases, | 457       RetrieveV8Releases, | 
| 491       CheckChromium, |  | 
| 492       SwitchChromium, | 458       SwitchChromium, | 
| 493       UpdateChromiumCheckout, | 459       UpdateChromiumCheckout, | 
| 494       RetrieveChromiumV8Releases, | 460       RetrieveChromiumV8Releases, | 
| 495       RietrieveChromiumBranches, | 461       RietrieveChromiumBranches, | 
| 496       SwitchV8, |  | 
| 497       CleanUp, | 462       CleanUp, | 
| 498       WriteOutput, | 463       WriteOutput, | 
| 499     ] | 464     ] | 
| 500 | 465 | 
| 501 | 466 | 
| 502 if __name__ == "__main__":  # pragma: no cover | 467 if __name__ == "__main__":  # pragma: no cover | 
| 503   sys.exit(Releases(CONFIG).Run()) | 468   sys.exit(Releases(CONFIG).Run()) | 
| OLD | NEW | 
|---|