Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium 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 """Snapshot Build Bisect Tool | 6 """Snapshot Build Bisect Tool |
| 7 | 7 |
| 8 This script bisects a snapshot archive using binary search. It starts at | 8 This script bisects a snapshot archive using binary search. It starts at |
| 9 a bad revision (it will try to guess HEAD) and asks for a last known-good | 9 a bad revision (it will try to guess HEAD) and asks for a last known-good |
| 10 revision. It will then binary search across this revision range by downloading, | 10 revision. It will then binary search across this revision range by downloading, |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 | 162 |
| 163 def ParseDirectoryIndex(self): | 163 def ParseDirectoryIndex(self): |
| 164 """Parses the Google Storage directory listing into a list of revision | 164 """Parses the Google Storage directory listing into a list of revision |
| 165 numbers.""" | 165 numbers.""" |
| 166 | 166 |
| 167 def _FetchAndParse(url): | 167 def _FetchAndParse(url): |
| 168 """Fetches a URL and returns a 2-Tuple of ([revisions], next-marker). If | 168 """Fetches a URL and returns a 2-Tuple of ([revisions], next-marker). If |
| 169 next-marker is not None, then the listing is a partial listing and another | 169 next-marker is not None, then the listing is a partial listing and another |
| 170 fetch should be performed with next-marker being the marker= GET | 170 fetch should be performed with next-marker being the marker= GET |
| 171 parameter.""" | 171 parameter.""" |
| 172 | |
|
Robert Sesek
2013/09/23 16:37:15
remove
kareng
2013/09/23 21:20:32
Done.
| |
| 172 handle = urllib.urlopen(url) | 173 handle = urllib.urlopen(url) |
| 173 document = ElementTree.parse(handle) | 174 document = ElementTree.parse(handle) |
| 174 | 175 |
| 175 # All nodes in the tree are namespaced. Get the root's tag name to extract | 176 # All nodes in the tree are namespaced. Get the root's tag name to extract |
| 176 # the namespace. Etree does namespaces as |{namespace}tag|. | 177 # the namespace. Etree does namespaces as |{namespace}tag|. |
| 177 root_tag = document.getroot().tag | 178 root_tag = document.getroot().tag |
| 178 end_ns_pos = root_tag.find('}') | 179 end_ns_pos = root_tag.find('}') |
| 179 if end_ns_pos == -1: | 180 if end_ns_pos == -1: |
| 180 raise Exception("Could not locate end namespace for directory index") | 181 raise Exception("Could not locate end namespace for directory index") |
| 181 namespace = root_tag[:end_ns_pos + 1] | 182 namespace = root_tag[:end_ns_pos + 1] |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 (new_revisions, next_marker) = _FetchAndParse(next_url) | 215 (new_revisions, next_marker) = _FetchAndParse(next_url) |
| 215 revisions.extend(new_revisions) | 216 revisions.extend(new_revisions) |
| 216 return revisions | 217 return revisions |
| 217 | 218 |
| 218 def GetRevList(self): | 219 def GetRevList(self): |
| 219 """Gets the list of revision numbers between self.good_revision and | 220 """Gets the list of revision numbers between self.good_revision and |
| 220 self.bad_revision.""" | 221 self.bad_revision.""" |
| 221 # Download the revlist and filter for just the range between good and bad. | 222 # Download the revlist and filter for just the range between good and bad. |
| 222 minrev = min(self.good_revision, self.bad_revision) | 223 minrev = min(self.good_revision, self.bad_revision) |
| 223 maxrev = max(self.good_revision, self.bad_revision) | 224 maxrev = max(self.good_revision, self.bad_revision) |
| 224 revlist = map(int, self.ParseDirectoryIndex()) | 225 revlist_all = map(int, self.ParseDirectoryIndex()) |
| 225 revlist = [x for x in revlist if x >= int(minrev) and x <= int(maxrev)] | 226 |
| 227 revlist = [x for x in revlist_all if x >= int(minrev) and x <= int(maxrev)] | |
| 226 revlist.sort() | 228 revlist.sort() |
| 227 return revlist | 229 |
| 230 # set good and bad revisions to be legit revisions | |
|
Robert Sesek
2013/09/23 16:37:15
Proper punctuation, capitalization, and grammar fo
kareng
2013/09/23 21:20:32
Done.
| |
| 231 if revlist: | |
| 232 if (self.good_revision < self.bad_revision): | |
|
Robert Sesek
2013/09/23 16:37:15
nit: no () around conditions unless necessary for
kareng
2013/09/23 21:20:32
Done.
| |
| 233 self.good_revision = revlist[0] | |
| 234 self.bad_revision = revlist[-1] | |
| 235 else: | |
| 236 self.bad_revision = revlist[0] | |
| 237 self.good_revision = revlist[-1] | |
| 238 | |
| 239 #fix chromium rev so that the deps blink revision matches VERSIONS file | |
|
Robert Sesek
2013/09/23 16:37:15
nit: same as above, but add a space after #
kareng
2013/09/23 21:20:32
Done.
| |
| 240 if (self.base_url == WEBKIT_BASE_URL): | |
| 241 revlist_all.sort() | |
| 242 self.good_revision, revlist = FixChromiumRevForBlink(revlist, | |
| 243 revlist_all, | |
| 244 self, | |
| 245 self.good_revision) | |
| 246 self.bad_revision, revlist = FixChromiumRevForBlink(revlist, | |
| 247 revlist_all, | |
| 248 self, | |
| 249 self.bad_revision) | |
| 250 return revlist | |
|
Michael Moss
2013/09/20 21:10:12
You probably want to always return 'revlist' (i.e.
kareng
2013/09/23 21:20:32
yes that was a mistake of tabbing. ty!
| |
| 228 | 251 |
| 229 def GetOfficialBuildsList(self): | 252 def GetOfficialBuildsList(self): |
| 230 """Gets the list of official build numbers between self.good_revision and | 253 """Gets the list of official build numbers between self.good_revision and |
| 231 self.bad_revision.""" | 254 self.bad_revision.""" |
| 232 # Download the revlist and filter for just the range between good and bad. | 255 # Download the revlist and filter for just the range between good and bad. |
| 233 minrev = min(self.good_revision, self.bad_revision) | 256 minrev = min(self.good_revision, self.bad_revision) |
| 234 maxrev = max(self.good_revision, self.bad_revision) | 257 maxrev = max(self.good_revision, self.bad_revision) |
| 235 handle = urllib.urlopen(OFFICIAL_BASE_URL) | 258 handle = urllib.urlopen(OFFICIAL_BASE_URL) |
| 236 dirindex = handle.read() | 259 dirindex = handle.read() |
| 237 handle.close() | 260 handle.close() |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 os.unlink(f) | 624 os.unlink(f) |
| 602 except OSError: | 625 except OSError: |
| 603 pass | 626 pass |
| 604 sys.exit(0) | 627 sys.exit(0) |
| 605 | 628 |
| 606 rev = revlist[pivot] | 629 rev = revlist[pivot] |
| 607 | 630 |
| 608 return (revlist[minrev], revlist[maxrev]) | 631 return (revlist[minrev], revlist[maxrev]) |
| 609 | 632 |
| 610 | 633 |
| 634 def GetBlinkDEPSREvisionForChromiumRevision(rev): | |
|
Robert Sesek
2013/09/23 16:37:15
Lowercase the E in Revision
kareng
2013/09/23 21:20:32
Done.
| |
| 635 """Returns the blink revision that was in REVISIONS file at | |
| 636 chromium revision |rev|.""" | |
| 637 # . doesn't match newlines without re.DOTALL, so this is safe. | |
| 638 blink_re = re.compile(r'webkit_revision\D*(\d+)') | |
| 639 url = urllib.urlopen(DEPS_FILE % rev) | |
| 640 m = blink_re.search(url.read()) | |
| 641 url.close() | |
| 642 if m: | |
| 643 return int(m.group(1)) | |
| 644 else: | |
| 645 raise Exception('Could not get blink revision for cr rev %d' % rev) | |
|
Robert Sesek
2013/09/23 16:37:15
Capitalize Blink and spell out Chromium. This is a
kareng
2013/09/23 21:20:32
Done.
| |
| 646 | |
| 647 | |
| 611 def GetBlinkRevisionForChromiumRevision(self, rev): | 648 def GetBlinkRevisionForChromiumRevision(self, rev): |
| 612 """Returns the blink revision that was in REVISIONS file at | 649 """Returns the blink revision that was in REVISIONS file at |
| 613 chromium revision |rev|.""" | 650 chromium revision |rev|.""" |
| 614 # . doesn't match newlines without re.DOTALL, so this is safe. | |
| 615 file_url = "%s/%s%d/REVISIONS" % (self.base_url, | 651 file_url = "%s/%s%d/REVISIONS" % (self.base_url, |
| 616 self._listing_platform_dir, rev) | 652 self._listing_platform_dir, rev) |
| 617 url = urllib.urlopen(file_url) | 653 url = urllib.urlopen(file_url) |
| 618 data = json.loads(url.read()) | 654 data = json.loads(url.read()) |
| 619 url.close() | 655 url.close() |
| 620 if 'webkit_revision' in data: | 656 if 'webkit_revision' in data: |
| 621 return data['webkit_revision'] | 657 return data['webkit_revision'] |
| 622 else: | 658 else: |
| 623 raise Exception('Could not get blink revision for cr rev %d' % rev) | 659 raise Exception('Could not get blink revision for cr rev %d' % rev) |
| 624 | 660 |
| 661 def FixChromiumRevForBlink(revisions_final, revisions, self, rev): | |
| 662 """Returns the chromium revision that has the correct blink revision | |
| 663 for blink bisect, deps and REVISIONS file might not match since | |
| 664 blink snapshots point to tip of tree blink. | |
| 665 chromium revision |rev.""" | |
|
Michael Moss
2013/09/20 21:10:12
Last line in the comment looks like copy-paste err
kareng
2013/09/23 21:20:32
Done.
| |
| 666 | |
| 667 blink_deps_rev = GetBlinkDEPSREvisionForChromiumRevision(rev) | |
| 668 | |
| 669 while (GetBlinkRevisionForChromiumRevision(self, rev) > blink_deps_rev): | |
| 670 idx = revisions.index(rev) | |
| 671 rev = revisions[idx-1] | |
|
Michael Moss
2013/09/20 21:10:12
What happens if 'rev' is the first item in 'revisi
kareng
2013/09/23 21:20:32
heh good, point. i changed so now it doesn't conti
| |
| 672 if rev not in revisions_final: | |
| 673 revisions_final.insert(0, rev) | |
| 674 | |
| 675 revisions_final.sort() | |
| 676 return rev, revisions_final | |
|
Michael Moss
2013/09/20 21:10:12
It's probably worth noting that when you modify 'r
kareng
2013/09/23 21:20:32
so you think its better to copy and return the cop
Michael Moss
2013/09/23 22:01:56
Modifying in-place is fine with me, just make it e
| |
| 625 | 677 |
| 626 def GetChromiumRevision(url): | 678 def GetChromiumRevision(url): |
| 627 """Returns the chromium revision read from given URL.""" | 679 """Returns the chromium revision read from given URL.""" |
| 628 try: | 680 try: |
| 629 # Location of the latest build revision number | 681 # Location of the latest build revision number |
| 630 return int(urllib.urlopen(url).read()) | 682 return int(urllib.urlopen(url).read()) |
| 631 except Exception, e: | 683 except Exception, e: |
| 632 print('Could not determine latest revision. This could be bad...') | 684 print('Could not determine latest revision. This could be bad...') |
| 633 return 999999999 | 685 return 999999999 |
| 634 | 686 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 print 'BLINK CHANGELOG URL:' | 817 print 'BLINK CHANGELOG URL:' |
| 766 print ' ' + BLINK_CHANGELOG_URL % (max_blink_rev, min_blink_rev) | 818 print ' ' + BLINK_CHANGELOG_URL % (max_blink_rev, min_blink_rev) |
| 767 print 'CHANGELOG URL:' | 819 print 'CHANGELOG URL:' |
| 768 if opts.official_builds: | 820 if opts.official_builds: |
| 769 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) | 821 print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) |
| 770 else: | 822 else: |
| 771 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) | 823 print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev) |
| 772 | 824 |
| 773 if __name__ == '__main__': | 825 if __name__ == '__main__': |
| 774 sys.exit(main()) | 826 sys.exit(main()) |
| OLD | NEW |