Chromium Code Reviews| 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 | 6 # This script retrieves the history of all V8 branches 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 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 | 63 |
| 64 def SortBranches(branches): | 64 def SortBranches(branches): |
| 65 """Sort branches with version number names.""" | 65 """Sort branches with version number names.""" |
| 66 return sorted(branches, key=SortingKey, reverse=True) | 66 return sorted(branches, key=SortingKey, reverse=True) |
| 67 | 67 |
| 68 | 68 |
| 69 def FilterDuplicatesAndReverse(cr_releases): | 69 def FilterDuplicatesAndReverse(cr_releases): |
| 70 """Returns the chromium releases in reverse order filtered by v8 revision | 70 """Returns the chromium releases in reverse order filtered by v8 revision |
| 71 duplicates. | 71 duplicates. |
| 72 | 72 |
| 73 cr_releases is a list of [cr_rev, v8_rev] reverse-sorted by cr_rev. | 73 cr_releases is a list of [cr_rev, v8_hsh] reverse-sorted by cr_rev. |
| 74 """ | 74 """ |
| 75 last = "" | 75 last = "" |
| 76 result = [] | 76 result = [] |
| 77 for release in reversed(cr_releases): | 77 for release in reversed(cr_releases): |
| 78 if last == release[1]: | 78 if last == release[1]: |
| 79 continue | 79 continue |
| 80 last = release[1] | 80 last = release[1] |
| 81 result.append(release) | 81 result.append(release) |
| 82 return result | 82 return result |
| 83 | 83 |
| 84 | 84 |
| 85 def BuildRevisionRanges(cr_releases): | 85 def BuildRevisionRanges(cr_releases): |
| 86 """Returns a mapping of v8 revision -> chromium ranges. | 86 """Returns a mapping of v8 revision -> chromium ranges. |
| 87 The ranges are comma-separated, each range has the form R1:R2. The newest | 87 The ranges are comma-separated, each range has the form R1:R2. The newest |
| 88 entry is the only one of the form R1, as there is no end range. | 88 entry is the only one of the form R1, as there is no end range. |
| 89 | 89 |
| 90 cr_releases is a list of [cr_rev, v8_rev] reverse-sorted by cr_rev. | 90 cr_releases is a list of [cr_rev, v8_hsh] reverse-sorted by cr_rev. |
| 91 cr_rev either refers to a chromium svn revision or a chromium branch number. | 91 cr_rev either refers to a chromium commit position or a chromium branch |
| 92 number. | |
| 92 """ | 93 """ |
| 93 range_lists = {} | 94 range_lists = {} |
| 94 cr_releases = FilterDuplicatesAndReverse(cr_releases) | 95 cr_releases = FilterDuplicatesAndReverse(cr_releases) |
| 95 | 96 |
| 96 # Visit pairs of cr releases from oldest to newest. | 97 # Visit pairs of cr releases from oldest to newest. |
| 97 for cr_from, cr_to in itertools.izip( | 98 for cr_from, cr_to in itertools.izip( |
| 98 cr_releases, itertools.islice(cr_releases, 1, None)): | 99 cr_releases, itertools.islice(cr_releases, 1, None)): |
| 99 | 100 |
| 100 # Assume the chromium revisions are all different. | 101 # Assume the chromium revisions are all different. |
| 101 assert cr_from[0] != cr_to[0] | 102 assert cr_from[0] != cr_to[0] |
| 102 | 103 |
| 103 # TODO(machenbach): Subtraction is not git friendly. | |
| 104 ran = "%s:%d" % (cr_from[0], int(cr_to[0]) - 1) | 104 ran = "%s:%d" % (cr_from[0], int(cr_to[0]) - 1) |
| 105 | 105 |
| 106 # Collect the ranges in lists per revision. | 106 # Collect the ranges in lists per revision. |
| 107 range_lists.setdefault(cr_from[1], []).append(ran) | 107 range_lists.setdefault(cr_from[1], []).append(ran) |
| 108 | 108 |
| 109 # Add the newest revision. | 109 # Add the newest revision. |
| 110 if cr_releases: | 110 if cr_releases: |
| 111 range_lists.setdefault(cr_releases[-1][1], []).append(cr_releases[-1][0]) | 111 range_lists.setdefault(cr_releases[-1][1], []).append(cr_releases[-1][0]) |
| 112 | 112 |
| 113 # Stringify and comma-separate the range lists. | 113 # Stringify and comma-separate the range lists. |
| 114 return dict((rev, ", ".join(ran)) for rev, ran in range_lists.iteritems()) | 114 return dict((hsh, ", ".join(ran)) for hsh, ran in range_lists.iteritems()) |
| 115 | 115 |
| 116 | 116 |
| 117 def MatchSafe(match): | 117 def MatchSafe(match): |
| 118 if match: | 118 if match: |
| 119 return match.group(1) | 119 return match.group(1) |
| 120 else: | 120 else: |
| 121 return "" | 121 return "" |
| 122 | 122 |
| 123 | 123 |
| 124 class Preparation(Step): | 124 class Preparation(Step): |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 200 body = self.GitLog(n=1, format="%B", git_hash=git_hash) | 200 body = self.GitLog(n=1, format="%B", git_hash=git_hash) |
| 201 | 201 |
| 202 patches = "" | 202 patches = "" |
| 203 if self["patch"] != "0": | 203 if self["patch"] != "0": |
| 204 version += ".%s" % self["patch"] | 204 version += ".%s" % self["patch"] |
| 205 if CHERRY_PICK_TITLE_GIT_RE.match(body.splitlines()[0]): | 205 if CHERRY_PICK_TITLE_GIT_RE.match(body.splitlines()[0]): |
| 206 patches = self.GetMergedPatchesGit(body) | 206 patches = self.GetMergedPatchesGit(body) |
| 207 else: | 207 else: |
| 208 patches = self.GetMergedPatches(body) | 208 patches = self.GetMergedPatches(body) |
| 209 | 209 |
| 210 title = self.GitLog(n=1, format="%s", git_hash=git_hash) | 210 if SortingKey("4.2.69") <= SortingKey(version): |
| 211 master_hash = self.GetMasterHashFromPush(title) | 211 master_hash = self.GetLatestReleaseBase(version=version) |
| 212 else: | |
| 213 # Legacy: Before version 4.2.69, the master revision was determined | |
| 214 # by commit message. | |
| 215 title = self.GitLog(n=1, format="%s", git_hash=git_hash) | |
| 216 master_hash = self.GetMasterHashFromPush(title) | |
| 212 master_position = "" | 217 master_position = "" |
| 213 if master_hash: | 218 if master_hash: |
| 214 master_position = self.GetCommitPositionNumber(master_hash) | 219 master_position = self.GetCommitPositionNumber(master_hash) |
| 215 # TODO(machenbach): Add the commit position number. | |
| 216 return self.GetReleaseDict( | 220 return self.GetReleaseDict( |
| 217 git_hash, master_position, master_hash, branch, version, | 221 git_hash, master_position, master_hash, branch, version, |
| 218 patches, body), self["patch"] | 222 patches, body), self["patch"] |
| 219 | 223 |
| 220 def GetReleasesFromBranch(self, branch): | 224 def GetReleasesFromBranch(self, branch): |
| 221 self.GitReset(self.vc.RemoteBranch(branch)) | 225 self.GitReset(self.vc.RemoteBranch(branch)) |
| 222 if branch == self.vc.MasterBranch(): | 226 if branch == self.vc.MasterBranch(): |
| 223 return self.GetReleasesFromMaster() | 227 return self.GetReleasesFromMaster() |
| 224 | 228 |
| 225 releases = [] | 229 releases = [] |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 not self.GitCheckoutFileSafe(VERSION_FILE, revision)): | 261 not self.GitCheckoutFileSafe(VERSION_FILE, revision)): |
| 258 print "Skipping revision %s" % revision | 262 print "Skipping revision %s" % revision |
| 259 return [] # pragma: no cover | 263 return [] # pragma: no cover |
| 260 | 264 |
| 261 branches = map( | 265 branches = map( |
| 262 str.strip, | 266 str.strip, |
| 263 self.Git("branch -r --contains %s" % revision).strip().splitlines(), | 267 self.Git("branch -r --contains %s" % revision).strip().splitlines(), |
| 264 ) | 268 ) |
| 265 branch = "" | 269 branch = "" |
| 266 for b in branches: | 270 for b in branches: |
| 267 if b == "origin/candidates": | 271 if b.startswith("origin/"): |
| 268 branch = "candidates" | 272 branch = b.split("origin/")[1] |
| 269 break | 273 break |
| 270 if b.startswith("branch-heads/"): | 274 if b.startswith("branch-heads/"): |
| 271 branch = b.split("branch-heads/")[1] | 275 branch = b.split("branch-heads/")[1] |
| 272 break | 276 break |
| 273 else: | 277 else: |
| 274 print "Could not determine branch for %s" % revision | 278 print "Could not determine branch for %s" % revision |
| 275 | 279 |
| 276 release, _ = self.GetRelease(revision, branch) | 280 release, _ = self.GetRelease(revision, branch) |
| 277 releases.append(release) | 281 releases.append(release) |
| 278 | 282 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 return revision | 343 return revision |
| 340 return step.GetCommitPositionNumber( | 344 return step.GetCommitPositionNumber( |
| 341 revision, cwd=os.path.join(step._options.chromium, "v8")) | 345 revision, cwd=os.path.join(step._options.chromium, "v8")) |
| 342 | 346 |
| 343 | 347 |
| 344 class RetrieveChromiumV8Releases(Step): | 348 class RetrieveChromiumV8Releases(Step): |
| 345 MESSAGE = "Retrieve V8 releases from Chromium DEPS." | 349 MESSAGE = "Retrieve V8 releases from Chromium DEPS." |
| 346 | 350 |
| 347 def RunStep(self): | 351 def RunStep(self): |
| 348 cwd = self._options.chromium | 352 cwd = self._options.chromium |
| 349 releases = filter( | |
| 350 lambda r: r["branch"] in [self.vc.CandidateBranch(), | |
| 351 self.vc.MasterBranch()], | |
| 352 self["releases"]) | |
| 353 if not releases: # pragma: no cover | |
| 354 print "No releases detected. Skipping chromium history." | |
| 355 return True | |
| 356 | 353 |
| 357 # Update v8 checkout in chromium. | 354 # Update v8 checkout in chromium. |
| 358 self.GitFetchOrigin(cwd=os.path.join(cwd, "v8")) | 355 self.GitFetchOrigin(cwd=os.path.join(cwd, "v8")) |
| 359 | 356 |
| 360 oldest_v8_rev = int(releases[-1]["revision"]) | 357 # All v8 revisions we are interested in. |
| 358 releases_dict = dict((r["revision_git"], r) for r in self["releases"]) | |
| 361 | 359 |
| 362 cr_releases = [] | 360 cr_releases = [] |
| 363 try: | 361 try: |
| 364 for git_hash in self.GitLog( | 362 for git_hash in self.GitLog( |
| 365 format="%H", grep="V8", cwd=cwd).splitlines(): | 363 format="%H", grep="V8", cwd=cwd).splitlines(): |
| 366 if "DEPS" not in self.GitChangedFiles(git_hash, cwd=cwd): | 364 if "DEPS" not in self.GitChangedFiles(git_hash, cwd=cwd): |
| 367 continue | 365 continue |
| 368 if not self.GitCheckoutFileSafe("DEPS", git_hash, cwd=cwd): | 366 if not self.GitCheckoutFileSafe("DEPS", git_hash, cwd=cwd): |
| 369 break # pragma: no cover | 367 break # pragma: no cover |
| 370 deps = FileToText(os.path.join(cwd, "DEPS")) | 368 deps = FileToText(os.path.join(cwd, "DEPS")) |
| 371 match = DEPS_RE.search(deps) | 369 match = DEPS_RE.search(deps) |
| 372 if match: | 370 if match: |
| 373 cr_rev = self.GetCommitPositionNumber(git_hash, cwd=cwd) | 371 cr_rev = self.GetCommitPositionNumber(git_hash, cwd=cwd) |
| 374 if cr_rev: | 372 if cr_rev: |
| 375 v8_rev = ConvertToCommitNumber(self, match.group(1)) | 373 v8_hsh = match.group(1) |
| 376 cr_releases.append([cr_rev, v8_rev]) | 374 cr_releases.append([cr_rev, v8_hsh]) |
| 377 | 375 |
| 378 # Stop after reaching beyond the last v8 revision we want to update. | 376 # Stop as soon as we find a v8 revision that we didn't fetch in the |
| 379 # We need a small buffer for possible revert/reland frenzies. | 377 # v8-revision-retrieval part above (i.e. a revision that's too old). |
| 380 # TODO(machenbach): Subtraction is not git friendly. | 378 if v8_hsh not in releases_dict: |
| 381 if int(v8_rev) < oldest_v8_rev - 100: | |
| 382 break # pragma: no cover | 379 break # pragma: no cover |
| 383 | 380 |
| 384 # Allow Ctrl-C interrupt. | 381 # Allow Ctrl-C interrupt. |
| 385 except (KeyboardInterrupt, SystemExit): # pragma: no cover | 382 except (KeyboardInterrupt, SystemExit): # pragma: no cover |
| 386 pass | 383 pass |
| 387 | 384 |
| 388 # Clean up. | 385 # Clean up. |
| 389 self.GitCheckoutFileSafe("DEPS", "HEAD", cwd=cwd) | 386 self.GitCheckoutFileSafe("DEPS", "HEAD", cwd=cwd) |
| 390 | 387 |
| 391 # Add the chromium ranges to the v8 candidates and master releases. | 388 # Add the chromium ranges to the v8 candidates and master releases. |
| 392 all_ranges = BuildRevisionRanges(cr_releases) | 389 all_ranges = BuildRevisionRanges(cr_releases) |
| 393 releases_dict = dict((r["revision"], r) for r in releases) | 390 |
| 394 for revision, ranges in all_ranges.iteritems(): | 391 for hsh, ranges in all_ranges.iteritems(): |
| 395 releases_dict.get(revision, {})["chromium_revision"] = ranges | 392 releases_dict.get(hsh, {})["chromium_revision"] = ranges |
| 396 | 393 |
| 397 | 394 |
| 398 # TODO(machenbach): Unify common code with method above. | 395 # TODO(machenbach): Unify common code with method above. |
| 399 class RietrieveChromiumBranches(Step): | 396 class RietrieveChromiumBranches(Step): |
| 400 MESSAGE = "Retrieve Chromium branch information." | 397 MESSAGE = "Retrieve Chromium branch information." |
| 401 | 398 |
| 402 def RunStep(self): | 399 def RunStep(self): |
| 403 cwd = self._options.chromium | 400 cwd = self._options.chromium |
| 404 cand_releases = filter(lambda r: r["branch"] == self.vc.CandidateBranch(), | |
| 405 self["releases"]) | |
| 406 if not cand_releases: # pragma: no cover | |
| 407 print "No candidates releases detected. Skipping chromium history." | |
| 408 return True | |
| 409 | 401 |
| 410 oldest_v8_rev = int(cand_releases[-1]["revision"]) | 402 # All v8 revisions we are interested in. |
| 403 releases_dict = dict((r["revision_git"], r) for r in self["releases"]) | |
| 411 | 404 |
| 412 # Filter out irrelevant branches. | 405 # Filter out irrelevant branches. |
| 413 branches = filter(lambda r: re.match(r"branch-heads/\d+", r), | 406 branches = filter(lambda r: re.match(r"branch-heads/\d+", r), |
| 414 self.GitRemotes(cwd=cwd)) | 407 self.GitRemotes(cwd=cwd)) |
| 415 | 408 |
| 416 # Transform into pure branch numbers. | 409 # Transform into pure branch numbers. |
| 417 branches = map(lambda r: int(re.match(r"branch-heads/(\d+)", r).group(1)), | 410 branches = map(lambda r: int(re.match(r"branch-heads/(\d+)", r).group(1)), |
| 418 branches) | 411 branches) |
| 419 | 412 |
| 420 branches = sorted(branches, reverse=True) | 413 branches = sorted(branches, reverse=True) |
| 421 | 414 |
| 422 cr_branches = [] | 415 cr_branches = [] |
| 423 try: | 416 try: |
| 424 for branch in branches: | 417 for branch in branches: |
| 425 if not self.GitCheckoutFileSafe("DEPS", | 418 if not self.GitCheckoutFileSafe("DEPS", |
| 426 "branch-heads/%d" % branch, | 419 "branch-heads/%d" % branch, |
| 427 cwd=cwd): | 420 cwd=cwd): |
| 428 break # pragma: no cover | 421 break # pragma: no cover |
| 429 deps = FileToText(os.path.join(cwd, "DEPS")) | 422 deps = FileToText(os.path.join(cwd, "DEPS")) |
| 430 match = DEPS_RE.search(deps) | 423 match = DEPS_RE.search(deps) |
| 431 if match: | 424 if match: |
| 432 v8_rev = ConvertToCommitNumber(self, match.group(1)) | 425 v8_hsh = match.group(1) |
| 433 cr_branches.append([str(branch), v8_rev]) | 426 cr_branches.append([str(branch), v8_hsh]) |
| 434 | 427 |
| 435 # Stop after reaching beyond the last v8 revision we want to update. | 428 # Stop as soon as we find a v8 revision that we didn't fetch in the |
| 436 # We need a small buffer for possible revert/reland frenzies. | 429 # v8-revision-retrieval part above (i.e. a revision that's too old). |
| 437 # TODO(machenbach): Subtraction is not git friendly. | 430 if v8_hsh not in releases_dict: |
| 438 if int(v8_rev) < oldest_v8_rev - 100: | |
| 439 break # pragma: no cover | 431 break # pragma: no cover |
| 440 | 432 |
| 433 | |
|
tandrii(chromium)
2015/02/16 15:31:06
nit: del extra space?
| |
| 441 # Allow Ctrl-C interrupt. | 434 # Allow Ctrl-C interrupt. |
| 442 except (KeyboardInterrupt, SystemExit): # pragma: no cover | 435 except (KeyboardInterrupt, SystemExit): # pragma: no cover |
| 443 pass | 436 pass |
| 444 | 437 |
| 445 # Clean up. | 438 # Clean up. |
| 446 self.GitCheckoutFileSafe("DEPS", "HEAD", cwd=cwd) | 439 self.GitCheckoutFileSafe("DEPS", "HEAD", cwd=cwd) |
| 447 | 440 |
| 448 # Add the chromium branches to the v8 candidate releases. | 441 # Add the chromium branches to the v8 candidate releases. |
| 449 all_ranges = BuildRevisionRanges(cr_branches) | 442 all_ranges = BuildRevisionRanges(cr_branches) |
| 450 cand_dict = dict((r["revision"], r) for r in cand_releases) | |
| 451 for revision, ranges in all_ranges.iteritems(): | 443 for revision, ranges in all_ranges.iteritems(): |
| 452 cand_dict.get(revision, {})["chromium_branch"] = ranges | 444 releases_dict.get(revision, {})["chromium_branch"] = ranges |
| 453 | 445 |
| 454 | 446 |
| 455 class CleanUp(Step): | 447 class CleanUp(Step): |
| 456 MESSAGE = "Clean up." | 448 MESSAGE = "Clean up." |
| 457 | 449 |
| 458 def RunStep(self): | 450 def RunStep(self): |
| 459 self.GitCheckout("master", cwd=self._options.chromium) | 451 self.GitCheckout("master", cwd=self._options.chromium) |
| 460 self.GitDeleteBranch(self.Config("BRANCHNAME"), cwd=self._options.chromium) | 452 self.GitDeleteBranch(self.Config("BRANCHNAME"), cwd=self._options.chromium) |
| 461 self.CommonCleanup() | 453 self.CommonCleanup() |
| 462 | 454 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 UpdateChromiumCheckout, | 505 UpdateChromiumCheckout, |
| 514 RetrieveChromiumV8Releases, | 506 RetrieveChromiumV8Releases, |
| 515 RietrieveChromiumBranches, | 507 RietrieveChromiumBranches, |
| 516 CleanUp, | 508 CleanUp, |
| 517 WriteOutput, | 509 WriteOutput, |
| 518 ] | 510 ] |
| 519 | 511 |
| 520 | 512 |
| 521 if __name__ == "__main__": # pragma: no cover | 513 if __name__ == "__main__": # pragma: no cover |
| 522 sys.exit(Releases().Run()) | 514 sys.exit(Releases().Run()) |
| OLD | NEW |