diff options
author | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-03 22:06:09 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-03 22:06:09 +0000 |
commit | 67e0bc60ab1b227c07303f088d485a866c646b14 (patch) | |
tree | f8282e59c6cd5682d6fd15454bf2aaaa783c8065 /build/build-bisect.py | |
parent | 91e1bd8b364d374372ab7be8c133ca03ffa1d2dd (diff) | |
download | chromium_src-67e0bc60ab1b227c07303f088d485a866c646b14.zip chromium_src-67e0bc60ab1b227c07303f088d485a866c646b14.tar.gz chromium_src-67e0bc60ab1b227c07303f088d485a866c646b14.tar.bz2 |
Add a Mac-specifc snapshot build archive bisecting tool.
Review URL: http://codereview.chromium.org/195006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25384 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'build/build-bisect.py')
-rwxr-xr-x | build/build-bisect.py | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/build/build-bisect.py b/build/build-bisect.py new file mode 100755 index 0000000..38fc54f --- /dev/null +++ b/build/build-bisect.py @@ -0,0 +1,160 @@ +#!/usr/bin/python2.5 +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Snapshot Build Bisect Tool + +This script bisects the Mac snapshot archive using binary search. It starts at +a bad revision (it will try to guess HEAD) and asks for a last known-good +revision. It will then binary search across this revision range by downloading, +unzipping, and opening Chromium for you. After testing the specific revision, +it will ask you whether it is good or bad before continuing the search. + +Currently this only works on Mac, but with some effort it could be ported to +other platforms. +""" + +# Base URL to download snapshots from. +BUILD_BASE_URL = \ + "http://build.chromium.org/buildbot/snapshots/chromium-rel-mac" + +# Location of the latest build revision number +BUILD_LATEST_URL = "%s/LATEST" % BUILD_BASE_URL + +# The location of the builds. +BUILD_ARCHIVE_URL = "/%d/" + +# Name of the build archive. +BUILD_ZIP_NAME = "chrome-mac.zip" + +# Directory name inside the archive. +BUILD_DIR_NAME = "chrome-mac" + +# Name of the executable. +BUILD_EXE_NAME = "Chromium.app" + +# URL to the ViewVC commit page. +BUILD_VIEWVC_URL = "http://src.chromium.org/viewvc/chrome?view=rev&revision=%d" + +############################################################################### + +import math +import os +import re +import shutil +import sys +import urllib + +def ParseDirectoryIndex(url): + """Parses the HTML directory listing into a list of revision numbers.""" + handle = urllib.urlopen(url) + dirindex = handle.read() + handle.close() + return re.findall(r'<a href="([0-9]*)/">\1/</a>', dirindex) + +def GetRevList(good, bad): + """Gets the list of revision numbers between |good| and |bad|.""" + # Download the main revlist. + revlist = ParseDirectoryIndex(BUILD_BASE_URL) + revlist = map(int, revlist) + revlist = filter(lambda r: range(good, bad).__contains__(int(r)), revlist) + revlist.sort() + return revlist + +def TryRevision(rev): + """Downloads revision |rev|, unzips it, and opens it for the user to test.""" + # Clear anything that's currently there. + try: + os.remove(BUILD_ZIP_NAME) + shutil.rmtree(BUILD_DIR_NAME, True) + except Exception, e: + pass + + # Download the file. + download_url = BUILD_BASE_URL + (BUILD_ARCHIVE_URL % rev) + BUILD_ZIP_NAME + try: + urllib.urlretrieve(download_url, BUILD_ZIP_NAME) + except Exception, e: + print("Could not retrieve the download. Sorry.") + print("Tried to get: %s" % download_url) + sys.exit(-1) + + # Unzip the file. + os.system("unzip -q %s" % BUILD_ZIP_NAME) + + # Tell Finder to open the app. + os.system("open %s/%s" % (BUILD_DIR_NAME, BUILD_EXE_NAME)) + +def AskIsGoodBuild(rev): + """Annoyingly ask the user whether build |rev| is good or bad.""" + while True: + check = raw_input("Build %d [g/b]: " % int(rev))[0] + if (check == "g" or check == "b"): + return (check == "g") + else: + print("Just answer the question...") + +def main(): + print("chrome-bisect: Perform binary search on the snapshot builds") + + # Pick a starting point, try to get HEAD for this. + bad_rev = 0 + try: + nh = urllib.urlopen(BUILD_LATEST_URL) + latest = int(nh.read()) + nh.close() + bad_rev = raw_input("Bad revision [HEAD:%d]: " % latest) + if (bad_rev == ""): + bad_rev = latest + bad_rev = int(bad_rev) + except Exception, e: + print("Could not determine latest revision. This could be bad...") + bad_rev = int(raw_input("Bad revision: ")) + + # Find out when we were good. + good_rev = 0 + try: + good_rev = int(raw_input("Last known good [0]: ")) + except Exception, e: + pass + + # Get a list of revisions to bisect across. + revlist = GetRevList(good_rev, bad_rev) + + # If we don't have a |good_rev|, set it to be the first revision possible. + if good_rev == 0: + good_rev = revlist[0] + + # These are indexes of |revlist|. + good = 0 + bad = len(revlist) - 1 + + # Binary search time! + while good < bad: + candidates = revlist[good:bad] + num_poss = len(candidates) + if num_poss > 10: + print("%d candidates. %d tries left." % + (num_poss, round(math.log(num_poss, 2)))) + else: + print("Candidates: %s" % revlist[good:bad]) + + # Cut the problem in half... + test = int((bad - good) / 2) + good + test_rev = revlist[test] + + # Let the user give this revision a spin. + TryRevision(test_rev) + if AskIsGoodBuild(test_rev): + good = test + 1 + else: + bad = test + + # We're done. Let the user know the results in an official manner. + print("You are probably looking for build %d." % revlist[bad]) + print("This is the ViewVC URL for the potential bustage:") + print(BUILD_VIEWVC_URL % revlist[bad]) + +if __name__ == '__main__': + main() |