Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: tools/bisect-builds.py

Issue 11266025: Make tools/bisect_builds.py handle reversed bad/good revision ranges (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fewer parens Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/bisect_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/bisect-builds.py
diff --git a/tools/bisect-builds.py b/tools/bisect-builds.py
index 04b4689d4e42dd5935ff9fcb4b6b21bc11c7001f..e601e4792094263d96eb11369110f7e2e882ce69 100755
--- a/tools/bisect-builds.py
+++ b/tools/bisect-builds.py
@@ -32,8 +32,10 @@ DEPS_FILE= 'http://src.chromium.org/viewvc/chrome/trunk/src/DEPS?revision=%d'
WEBKIT_CHANGELOG_URL = 'http://trac.webkit.org/log/' \
'trunk/?rev=%d&stop_rev=%d&verbose=on&limit=10000'
-DONE_MESSAGE = 'You are probably looking for a change made after ' \
- '%s (known good), but no later than %s (first known bad).'
+DONE_MESSAGE_GOOD_MIN = 'You are probably looking for a change made after %s ' \
+ '(known good), but no later than %s (first known bad).'
+DONE_MESSAGE_GOOD_MAX = 'You are probably looking for a change made after %s ' \
+ '(known bad), but no later than %s (first known good).'
###############################################################################
@@ -140,8 +142,7 @@ class PathContext(object):
def ParseDirectoryIndex(self):
"""Parses the Google Storage directory listing into a list of revision
- numbers. The range starts with self.good_revision and goes until
- self.bad_revision."""
+ numbers."""
def _FetchAndParse(url):
"""Fetches a URL and returns a 2-Tuple of ([revisions], next-marker). If
@@ -198,8 +199,8 @@ class PathContext(object):
"""Gets the list of revision numbers between self.good_revision and
self.bad_revision."""
# Download the revlist and filter for just the range between good and bad.
- minrev = self.good_revision
- maxrev = self.bad_revision
+ minrev = min(self.good_revision, self.bad_revision)
+ maxrev = max(self.good_revision, self.bad_revision)
revlist = map(int, self.ParseDirectoryIndex())
revlist = [x for x in revlist if x >= int(minrev) and x <= int(maxrev)]
revlist.sort()
@@ -209,8 +210,8 @@ class PathContext(object):
"""Gets the list of official build numbers between self.good_revision and
self.bad_revision."""
# Download the revlist and filter for just the range between good and bad.
- minrev = self.good_revision
- maxrev = self.bad_revision
+ minrev = min(self.good_revision, self.bad_revision)
+ maxrev = max(self.good_revision, self.bad_revision)
handle = urllib.urlopen(OFFICIAL_BASE_URL)
dirindex = handle.read()
handle.close()
@@ -392,8 +393,8 @@ def Bisect(platform,
@param platform Which build to download/run ('mac', 'win', 'linux64', etc.).
@param official_builds Specify build type (Chromium or Official build).
- @param good_rev Number/tag of the last known good revision.
- @param bad_rev Number/tag of the first known bad revision.
+ @param good_rev Number/tag of the known good revision.
+ @param bad_rev Number/tag of the known bad revision.
@param num_runs Number of times to run each build for asking good/bad.
@param try_args A tuple of arguments to pass to the test application.
@param profile The name of the user profile to run with.
@@ -436,36 +437,41 @@ def Bisect(platform,
msg = 'We don\'t have enough builds to bisect. revlist: %s' % revlist
raise RuntimeError(msg)
- print 'Bisecting range [%s, %s].' % (revlist[0], revlist[-1])
-
# Figure out our bookends and first pivot point; fetch the pivot revision.
- good = 0
- bad = len(revlist) - 1
- pivot = bad / 2
+ minrev = 0
+ maxrev = len(revlist) - 1
+ pivot = maxrev / 2
rev = revlist[pivot]
zipfile = _GetDownloadPath(rev)
- initial_fetch = DownloadJob(context, 'initial_fetch', rev, zipfile)
- initial_fetch.Start()
- initial_fetch.WaitFor()
+ fetch = DownloadJob(context, 'initial_fetch', rev, zipfile)
+ fetch.Start()
+ fetch.WaitFor()
# Binary search time!
- while zipfile and bad - good > 1:
+ while fetch and fetch.zipfile and maxrev - minrev > 1:
+ if bad_rev < good_rev:
+ min_str, max_str = "bad", "good"
+ else:
+ min_str, max_str = "good", "bad"
+ print 'Bisecting range [%s (%s), %s (%s)].' % (revlist[minrev], min_str, \
+ revlist[maxrev], max_str)
+
# Pre-fetch next two possible pivots
# - down_pivot is the next revision to check if the current revision turns
# out to be bad.
# - up_pivot is the next revision to check if the current revision turns
# out to be good.
- down_pivot = int((pivot - good) / 2) + good
+ down_pivot = int((pivot - minrev) / 2) + minrev
down_fetch = None
- if down_pivot != pivot and down_pivot != good:
+ if down_pivot != pivot and down_pivot != minrev:
down_rev = revlist[down_pivot]
down_fetch = DownloadJob(context, 'down_fetch', down_rev,
_GetDownloadPath(down_rev))
down_fetch.Start()
- up_pivot = int((bad - pivot) / 2) + pivot
+ up_pivot = int((maxrev - pivot) / 2) + pivot
up_fetch = None
- if up_pivot != pivot and up_pivot != bad:
+ if up_pivot != pivot and up_pivot != maxrev:
up_rev = revlist[up_pivot]
up_fetch = DownloadJob(context, 'up_fetch', up_rev,
_GetDownloadPath(up_rev))
@@ -478,43 +484,44 @@ def Bisect(platform,
try:
(status, stdout, stderr) = RunRevision(context,
rev,
- zipfile,
+ fetch.zipfile,
profile,
num_runs,
try_args)
except Exception, e:
print >>sys.stderr, e
- os.unlink(zipfile)
- zipfile = None
+ fetch.Stop()
+ fetch = None
# Call the evaluate function to see if the current revision is good or bad.
# On that basis, kill one of the background downloads and complete the
# other, as described in the comments above.
try:
answer = evaluate(rev, official_builds, status, stdout, stderr)
- if answer == 'g':
- good = pivot
+ if answer == 'g' and good_rev < bad_rev or \
+ answer == 'b' and bad_rev < good_rev:
+ minrev = pivot
if down_fetch:
down_fetch.Stop() # Kill the download of the older revision.
if up_fetch:
up_fetch.WaitFor()
pivot = up_pivot
- zipfile = up_fetch.zipfile
- elif answer == 'b':
- bad = pivot
+ fetch = up_fetch
+ elif answer == 'b' and good_rev < bad_rev or \
+ answer == 'g' and bad_rev < good_rev:
+ maxrev = pivot
if up_fetch:
up_fetch.Stop() # Kill the download of the newer revision.
if down_fetch:
down_fetch.WaitFor()
pivot = down_pivot
- zipfile = down_fetch.zipfile
+ fetch = down_fetch
elif answer == 'u':
# Nuke the revision from the revlist and choose a new pivot.
revlist.pop(pivot)
- bad -= 1 # Assumes bad >= pivot.
+ maxrev -= 1 # Assumes maxrev >= pivot.
- fetch = None
- if bad - good > 1:
+ if maxrev - minrev > 1:
# Alternate between using down_pivot or up_pivot for the new pivot
# point, without affecting the range. Do this instead of setting the
# pivot to the midpoint of the new range because adjacent revisions
@@ -551,7 +558,7 @@ def Bisect(platform,
rev = revlist[pivot]
- return (revlist[good], revlist[bad])
+ return (revlist[minrev], revlist[maxrev])
def GetWebKitRevisionForChromiumRevision(rev):
@@ -638,43 +645,38 @@ def main():
good_rev = int(good_rev)
bad_rev = int(bad_rev)
- if good_rev > bad_rev:
- print ('The good revision (%s) must precede the bad revision (%s).\n' %
- (good_rev, bad_rev))
- parser.print_help()
- return 1
-
if opts.times < 1:
print('Number of times to run (%d) must be greater than or equal to 1.' %
opts.times)
parser.print_help()
return 1
- (last_known_good_rev, first_known_bad_rev) = Bisect(
+ (min_chromium_rev, max_chromium_rev) = Bisect(
opts.archive, opts.official_builds, good_rev, bad_rev, opts.times, args,
opts.profile)
# Get corresponding webkit revisions.
try:
- last_known_good_webkit_rev = GetWebKitRevisionForChromiumRevision(
- last_known_good_rev)
- first_known_bad_webkit_rev = GetWebKitRevisionForChromiumRevision(
- first_known_bad_rev)
+ min_webkit_rev = GetWebKitRevisionForChromiumRevision(min_chromium_rev)
+ max_webkit_rev = GetWebKitRevisionForChromiumRevision(max_chromium_rev)
except Exception, e:
# Silently ignore the failure.
- last_known_good_webkit_rev, first_known_bad_webkit_rev = 0, 0
+ min_webkit_rev, max_webkit_rev = 0, 0
# We're done. Let the user know the results in an official manner.
- print DONE_MESSAGE % (str(last_known_good_rev), str(first_known_bad_rev))
- if last_known_good_webkit_rev != first_known_bad_webkit_rev:
+ if good_rev > bad_rev:
+ print DONE_MESSAGE_GOOD_MAX % (str(min_chromium_rev), str(max_chromium_rev))
+ else:
+ print DONE_MESSAGE_GOOD_MIN % (str(min_chromium_rev), str(max_chromium_rev))
+
+ if min_webkit_rev != max_webkit_rev:
print 'WEBKIT CHANGELOG URL:'
- print ' ' + WEBKIT_CHANGELOG_URL % (first_known_bad_webkit_rev,
- last_known_good_webkit_rev)
+ print ' ' + WEBKIT_CHANGELOG_URL % (max_webkit_rev, min_webkit_rev)
print 'CHANGELOG URL:'
if opts.official_builds:
- print OFFICIAL_CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev)
+ print OFFICIAL_CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
else:
- print ' ' + CHANGELOG_URL % (last_known_good_rev, first_known_bad_rev)
+ print ' ' + CHANGELOG_URL % (min_chromium_rev, max_chromium_rev)
if __name__ == '__main__':
sys.exit(main())
« no previous file with comments | « no previous file | tools/bisect_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698