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

Unified Diff: third_party/buildbot_7_12/buildbot/status/web/console.py

Issue 12207158: Bye bye buildbot 0.7.12. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months 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
Index: third_party/buildbot_7_12/buildbot/status/web/console.py
diff --git a/third_party/buildbot_7_12/buildbot/status/web/console.py b/third_party/buildbot_7_12/buildbot/status/web/console.py
deleted file mode 100755
index 71d5218711f3b7bc0d8af3d002e684bfeb518330..0000000000000000000000000000000000000000
--- a/third_party/buildbot_7_12/buildbot/status/web/console.py
+++ /dev/null
@@ -1,1072 +0,0 @@
-from __future__ import generators
-
-import time
-import operator
-import re
-import urllib
-
-from buildbot import util
-from buildbot import version
-from buildbot.status import builder
-from buildbot.status.web.base import HtmlResource
-from buildbot.status.web import console_html as res
-from buildbot.status.web import console_js as js
-
-def isBuildGoingToFail(build):
- """Returns True if one of the step in the running build has failed."""
- for step in build.getSteps():
- if step.getResults()[0] == builder.FAILURE:
- return True
- return False
-
-def getInProgressResults(build):
- """Returns build status expectation for an incomplete build."""
- if not build.isFinished() and isBuildGoingToFail(build):
- return builder.FAILURE
-
- return build.getResults()
-
-def getResultsClass(results, prevResults, inProgress, inProgressResults=None):
- """Given the current and past results, returns the class that will be used
- by the css to display the right color for a box."""
-
- if inProgress:
- if inProgressResults == builder.FAILURE:
- return "running_failure"
- return "running"
-
- if results is None:
- return "notstarted"
-
- if results == builder.SUCCESS:
- return "success"
-
- if results == builder.FAILURE:
- if not prevResults:
- # This is the bottom box. We don't know if the previous one failed
- # or not. We assume it did not.
- return "failure"
-
- if prevResults != builder.FAILURE:
- # This is a new failure.
- return "failure"
- else:
- # The previous build also failed.
- return "warnings"
-
- # Any other results? Like EXCEPTION?
- return "exception"
-
-cachedBoxes = dict()
-
-class ANYBRANCH: pass # a flag value, used below
-
-class CachedStatusBox:
- def __init__(self, color, title, details, url, tag):
- self.color = color
- self.title = title
- self.details = details
- self.url = url
- self.tag = tag
-
-
-class CacheStatus:
- def __init__(self):
- self.allBoxes = dict()
- self.lastRevisions = dict()
-
- def display(self):
- data = ""
- for builder in self.allBoxes:
- lastRevision = -1
- try:
- lastRevision = self.lastRevisions[builder]
- except:
- pass
- data += "<br> %s is up to revision %d" % (builder, int(lastRevision))
- for revision in self.allBoxes[builder]:
- data += "<br>%s %s %s" % (builder, revision,
- self.allBoxes[builder][revision].color)
- return data
-
- def insert(self, builderName, revision, color, title, details, url, tag):
- box = CachedStatusBox(color, title, details, url, tag)
- try:
- test = self.allBoxes[builderName]
- except:
- self.allBoxes[builderName] = dict()
-
- self.allBoxes[builderName][revision] = box
-
- def get(self, builderName, revision):
- try:
- return self.allBoxes[builderName][revision]
- except:
- return None
-
- def trim(self):
- for builder in self.allBoxes:
- allRevs = []
- for revision in self.allBoxes[builder]:
- allRevs.append(revision)
-
- if len(allRevs) > 150:
- allRevs.sort()
- deleteCount = len(allRevs) - 150
- for i in range(0, deleteCount):
- del self.allBoxes[builder][allRevs[i]]
-
- def update(self, builderName, lastRevision):
- currentRevision = 0
- try:
- currentRevision = self.lastRevisions[builderName]
- except:
- pass
-
- if currentRevision < lastRevision:
- self.lastRevisions[builderName] = lastRevision
-
- def getRevision(self, builderName):
- try:
- return self.lastRevisions[builderName]
- except:
- return None
-
-
-class TemporaryCache:
- def __init__(self):
- self.lastRevisions = dict()
-
- def display(self):
- data = ""
- for builder in self.lastRevisions:
- data += "<br>%s: %s" % (builder, self.lastRevisions[builder])
-
- return data
-
- def insert(self, builderName, revision):
- currentRevision = 0
- try:
- currentRevision = self.lastRevisions[builderName]
- except:
- pass
-
- if currentRevision < revision:
- self.lastRevisions[builderName] = revision
-
- def updateGlobalCache(self, global_cache):
- for builder in self.lastRevisions:
- global_cache.update(builder, self.lastRevisions[builder])
-
-
-class DevRevision:
- """Helper class that contains all the information we need for a revision."""
-
- def __init__(self, revision, who, comments, date, revlink, when):
- self.revision = revision
- self.comments = comments
- self.who = who
- self.date = date
- self.revlink = revlink
- self.when = when
-
-
-class DevBuild:
- """Helper class that contains all the information we need for a build."""
-
- def __init__(self, revision, results, inProgressResults, number, isFinished,
- text, eta, details, when):
- self.revision = revision
- self.results = results
- self.inProgressResults = inProgressResults
- self.number = number
- self.isFinished = isFinished
- self.text = text
- self.eta = eta
- self.details = details
- self.when = when
-
-
-class ConsoleStatusResource(HtmlResource):
- """Main console class. It displays a user-oriented status page.
- Every change is a line in the page, and it shows the result of the first
- build with this change for each slave."""
-
- def __init__(self, allowForce=True, css=None, orderByTime=False):
- HtmlResource.__init__(self)
-
- self.status = None
- self.control = None
- self.changemaster = None
- self.cache = CacheStatus()
- self.initialRevs = None
-
- self.allowForce = allowForce
- self.css = css
-
- if orderByTime:
- self.comparator = TimeRevisionComparator()
- else:
- self.comparator = IntegerRevisionComparator()
-
- def getTitle(self, request):
- status = self.getStatus(request)
- projectName = status.getProjectName()
- if projectName:
- return "BuildBot: %s" % projectName
- else:
- return "BuildBot"
-
- def getChangemaster(self, request):
- return request.site.buildbot_service.parent.change_svc
-
- def head(self, request):
- jsonFormat = request.args.get("json", [False])[0]
- if jsonFormat:
- return ""
-
- # Start by adding all the javascript functions we have.
- head = "<script type='text/javascript'> %s </script>" % js.JAVASCRIPT
-
- reload_time = None
- # Check if there was an arg. Don't let people reload faster than
- # every 15 seconds. 0 means no reload.
- if "reload" in request.args:
- try:
- reload_time = int(request.args["reload"][0])
- if reload_time != 0:
- reload_time = max(reload_time, 15)
- except ValueError:
- pass
-
- # Append the tag to refresh the page.
- if reload_time is not None and reload_time != 0:
- head += '<meta http-equiv="refresh" content="%d">\n' % reload_time
- return head
-
-
- ##
- ## Data gathering functions
- ##
-
- def getHeadBuild(self, builder):
- """Get the most recent build for the given builder.
- """
- build = builder.getBuild(-1)
-
- # HACK: Work around #601, the head build may be None if it is
- # locked.
- if build is None:
- build = builder.getBuild(-2)
-
- return build
-
- def fetchChangesFromHistory(self, status, max_depth, max_builds, debugInfo):
- """Look at the history of the builders and try to fetch as many changes
- as possible. We need this when the main source does not contain enough
- sourcestamps.
-
- max_depth defines how many builds we will parse for a given builder.
- max_builds defines how many builds total we want to parse. This is to
- limit the amount of time we spend in this function.
-
- This function is sub-optimal, but the information returned by this
- function is cached, so this function won't be called more than once.
- """
-
- allChanges = list()
- build_count = 0
- for builderName in status.getBuilderNames()[:]:
- if build_count > max_builds:
- break
-
- builder = status.getBuilder(builderName)
- build = self.getHeadBuild(builder)
- depth = 0
- while build and depth < max_depth and build_count < max_builds:
- depth += 1
- build_count += 1
- sourcestamp = build.getSourceStamp()
- allChanges.extend(sourcestamp.changes[:])
- build = build.getPreviousBuild()
-
- debugInfo["source_fetch_len"] = len(allChanges)
- return allChanges
-
- def getAllChanges(self, source, status, debugInfo):
- """Return all the changes we can find at this time. If |source| does not
- not have enough (less than 25), we try to fetch more from the builders
- history."""
-
- allChanges = list()
- allChanges.extend(source.changes[:])
-
- debugInfo["source_len"] = len(source.changes)
-
- if len(allChanges) < 25:
- # There is not enough revisions in the source.changes. It happens
- # quite a lot because buildbot mysteriously forget about changes
- # once in a while during restart.
- # Let's try to get more changes from the builders.
- # We check the last 10 builds of all builders, and stop when we
- # are done, or have looked at 100 builds.
- # We do this only once!
- if not self.initialRevs:
- self.initialRevs = self.fetchChangesFromHistory(status, 10, 100,
- debugInfo)
-
- allChanges.extend(self.initialRevs)
-
- # the new changes are not sorted, and can contain duplicates.
- # Sort the list.
- allChanges.sort(lambda a, b: cmp(getattr(a, self.comparator.getSortingKey()), getattr(b, self.comparator.getSortingKey())))
-
- # Remove the dups
- prevChange = None
- newChanges = []
- for change in allChanges:
- rev = change.revision
- if not prevChange or rev != prevChange.revision:
- newChanges.append(change)
- prevChange = change
- allChanges = newChanges
-
- return allChanges
-
- def stripRevisions(self, allChanges, numRevs, branch, devName):
- """Returns a subset of changesn from allChanges that matches the query.
-
- allChanges is the list of all changes we know about.
- numRevs is the number of changes we will inspect from allChanges. We
- do not want to inspect all of them or it would be too slow.
- branch is the branch we are interested in. Changes not in this branch
- will be ignored.
- devName is the committer username. Changes that have not been submitted
- by this person will be ignored.
- """
-
- revisions = []
-
- if not allChanges:
- return revisions
-
- totalRevs = len(allChanges)
- for i in range(totalRevs-1, totalRevs-numRevs, -1):
- if i < 0:
- break
- change = allChanges[i]
- if branch == ANYBRANCH or branch == change.branch:
- if not devName or change.who in devName:
- rev = DevRevision(change.revision, change.who,
- change.comments, change.getTime(),
- getattr(change, 'revlink', None),
- change.when)
- revisions.append(rev)
-
- return revisions
-
- def getBuildDetails(self, request, builderName, build):
- """Returns an HTML list of failures for a given build."""
- details = ""
- if build.getLogs():
- for step in build.getSteps():
- (result, reason) = step.getResults()
- if result == builder.FAILURE:
- name = step.getName()
-
- # Remove html tags from the error text.
- stripHtml = re.compile(r'<.*?>')
- strippedDetails = stripHtml .sub('', ' '.join(step.getText()))
-
- details += "<li> %s : %s. \n" % (builderName, strippedDetails)
- if step.getLogs():
- details += "[ "
- for log in step.getLogs():
- logname = log.getName()
- logurl = request.childLink(
- "../builders/%s/builds/%s/steps/%s/logs/%s" %
- (urllib.quote(builderName),
- build.getNumber(),
- urllib.quote(name),
- urllib.quote(logname)))
- details += "<a href=\"%s\">%s</a> " % (logurl,
- log.getName())
- details += "]"
- return details
-
- def getBuildsForRevision(self, request, builder, builderName, lastRevision,
- numBuilds, debugInfo):
- """Return the list of all the builds for a given builder that we will
- need to be able to display the console page. We start by the most recent
- build, and we go down until we find a build that was built prior to the
- last change we are interested in."""
-
- revision = lastRevision
- cachedRevision = self.cache.getRevision(builderName)
- if cachedRevision and cachedRevision > lastRevision:
- revision = cachedRevision
-
- builds = []
- build = self.getHeadBuild(builder)
- number = 0
- while build and number < numBuilds:
- debugInfo["builds_scanned"] += 1
- number += 1
-
- # Get the last revision in this build.
- # We first try "got_revision", but if it does not work, then
- # we try "revision".
- got_rev = -1
- try:
- got_rev = build.getProperty("got_revision")
- if not self.comparator.isValidRevision(got_rev):
- got_rev = -1
- except KeyError:
- pass
-
- try:
- if got_rev == -1:
- got_rev = build.getProperty("revision")
- if not self.comparator.isValidRevision(got_rev):
- got_rev = -1
- except:
- pass
-
- # We ignore all builds that don't have last revisions.
- # TODO(nsylvain): If the build is over, maybe it was a problem
- # with the update source step. We need to find a way to tell the
- # user that his change might have broken the source update.
- if got_rev and got_rev != -1:
- details = self.getBuildDetails(request, builderName, build)
- devBuild = DevBuild(got_rev, build.getResults(),
- getInProgressResults(build),
- build.getNumber(),
- build.isFinished(),
- build.getText(),
- build.getETA(),
- details,
- build.getTimes()[0])
-
- builds.append(devBuild)
-
- # Now break if we have enough builds.
- if self.comparator.getSortingKey() == "when":
- current_revision = self.getChangeForBuild(
- builder.getBuild(-1), revision)
- if self.comparator.isRevisionEarlier(
- devBuild, current_revision):
- break
- else:
- if int(got_rev) < int(revision):
- break;
-
-
- build = build.getPreviousBuild()
-
- return builds
-
- def getChangeForBuild(self, build, revision):
- if not build.getChanges(): # Forced build
- devBuild = DevBuild(revision, build.getResults(),
- None,
- build.getNumber(),
- build.isFinished(),
- build.getText(),
- build.getETA(),
- None,
- build.getTimes()[0])
-
- return devBuild
-
- for change in build.getChanges():
- if change.revision == revision:
- return change
-
- # No matching change, return the last change in build.
- changes = list(build.getChanges())
- changes.sort(lambda a, b: cmp(getattr(a, self.comparator.getSortingKey()), getattr(b, self.comparator.getSortingKey())))
- return changes[-1]
-
- def getAllBuildsForRevision(self, status, request, lastRevision, numBuilds,
- categories, builders, debugInfo):
- """Returns a dictionnary of builds we need to inspect to be able to
- display the console page. The key is the builder name, and the value is
- an array of build we care about. We also returns a dictionnary of
- builders we care about. The key is it's category.
-
- lastRevision is the last revision we want to display in the page.
- categories is a list of categories to display. It is coming from the
- HTTP GET parameters.
- builders is a list of builders to display. It is coming from the HTTP
- GET parameters.
- """
-
- allBuilds = dict()
-
- # List of all builders in the dictionnary.
- builderList = dict()
-
- debugInfo["builds_scanned"] = 0
- # Get all the builders.
- builderNames = status.getBuilderNames()[:]
- for builderName in builderNames:
- builder = status.getBuilder(builderName)
-
- # Make sure we are interested in this builder.
- if categories and builder.category not in categories:
- continue
- if builders and builderName not in builders:
- continue
-
- # We want to display this builder.
- category = builder.category or "default"
- # Strip the category to keep only the text before the first |.
- # This is a hack to support the chromium usecase where they have
- # multiple categories for each slave. We use only the first one.
- # TODO(nsylvain): Create another way to specify "display category"
- # in master.cfg.
- category = category.split('|')[0]
- if not builderList.get(category):
- builderList[category] = []
-
- # Append this builder to the dictionnary of builders.
- builderList[category].append(builderName)
- # Set the list of builds for this builder.
- allBuilds[builderName] = self.getBuildsForRevision(request,
- builder,
- builderName,
- lastRevision,
- numBuilds,
- debugInfo)
-
- return (builderList, allBuilds)
-
-
- ##
- ## Display functions
- ##
-
- def displayCategories(self, builderList, debugInfo, subs):
- """Display the top category line."""
-
- data = res.main_line_category_header.substitute(subs)
- count = 0
- for category in builderList:
- count += len(builderList[category])
-
- i = 0
- categories = builderList.keys()
- categories.sort()
- for category in categories:
- # First, we add a flag to say if it's the first or the last one.
- # This is useful is your css is doing rounding at the edge of the
- # tables.
- subs["first"] = ""
- subs["last"] = ""
- if i == 0:
- subs["first"] = "first"
- if i == len(builderList) -1:
- subs["last"] = "last"
-
- # TODO(nsylvain): Another hack to display the category in a pretty
- # way. If the master owner wants to display the categories in a
- # given order, he/she can prepend a number to it. This number won't
- # be shown.
- subs["category"] = category.lstrip('0123456789')
-
- # To be able to align the table correctly, we need to know
- # what percentage of space this category will be taking. This is
- # (#Builders in Category) / (#Builders Total) * 100.
- subs["size"] = (len(builderList[category]) * 100) / count
- data += res.main_line_category_name.substitute(subs)
- i += 1
- data += res.main_line_category_footer.substitute(subs)
- return data
-
- def displaySlaveLine(self, status, builderList, debugInfo, subs, jsonFormat=False):
- """Display a line the shows the current status for all the builders we
- care about."""
-
- data = ""
- json = ""
-
- # Display the first TD (empty) element.
- subs["last"] = ""
- if len(builderList) == 1:
- subs["last"] = "last"
- data += res.main_line_slave_header.substitute(subs)
-
- nbSlaves = 0
- subs["first"] = ""
-
- # Get the number of builders.
- for category in builderList:
- nbSlaves += len(builderList[category])
-
- i = 0
-
- # Get the catefories, and order them alphabetically.
- categories = builderList.keys()
- categories.sort()
- json += '['
-
- # For each category, we display each builder.
- for category in categories:
- subs["last"] = ""
-
- # If it's the last category, we set the "last" flag.
- if i == len(builderList) - 1:
- subs["last"] = "last"
-
- # This is not the first category, we need to add the spacing we have
- # between 2 categories.
- if i != 0:
- data += res.main_line_slave_section.substitute(subs)
-
- i += 1
-
- # For each builder in this category, we set the build info and we
- # display the box.
- for builder in builderList[category]:
- subs["color"] = "notstarted"
- subs["title"] = builder
- subs["url"] = "./builders/%s" % urllib.quote(builder)
- state, builds = status.getBuilder(builder).getState()
- # Check if it's offline, if so, the box is purple.
- if state == "offline":
- subs["color"] = "exception"
- else:
- # If not offline, then display the result of the last
- # finished build.
- build = self.getHeadBuild(status.getBuilder(builder))
- while build and not build.isFinished():
- build = build.getPreviousBuild()
-
- if build:
- subs["color"] = getResultsClass(build.getResults(), None,
- False)
-
- json += ("{'url': '%s', 'title': '%s', 'color': '%s',"
- " 'name': '%s'}," % (subs["url"], subs["title"],
- subs["color"],
- urllib.quote(builder)))
-
- data += res.main_line_slave_status.substitute(subs)
-
- json += ']'
- data += res.main_line_slave_footer.substitute(subs)
-
- if jsonFormat:
- return json
- return data
-
- def displayStatusLine(self, builderList, allBuilds, revision, tempCache,
- debugInfo, subs, jsonFormat=False):
- """Display the boxes that represent the status of each builder in the
- first build "revision" was in. Returns an HTML list of errors that
- happened during these builds."""
-
- data = ""
- json = ""
-
- # Display the first TD (empty) element.
- subs["last"] = ""
- if len(builderList) == 1:
- subs["last"] = "last"
- data += res.main_line_status_header.substitute(subs)
-
- details = ""
- nbSlaves = 0
- subs["first"] = ""
- for category in builderList:
- nbSlaves += len(builderList[category])
-
- i = 0
- # Sort the categories.
- categories = builderList.keys()
- categories.sort()
- json += '['
-
- # Display the boxes by category group.
- for category in categories:
- # Last category? We set the "last" flag.
- subs["last"] = ""
- if i == len(builderList) - 1:
- subs["last"] = "last"
-
- # Not the first category? We add the spacing between 2 categories.
- if i != 0:
- data += res.main_line_status_section.substitute(subs)
- i += 1
-
- # Display the boxes for each builder in this category.
- for builder in builderList[category]:
- introducedIn = None
- firstNotIn = None
-
- cached_value = self.cache.get(builder, revision.revision)
- if cached_value:
- debugInfo["from_cache"] += 1
- subs["url"] = cached_value.url
- subs["title"] = cached_value.title
- subs["color"] = cached_value.color
- subs["tag"] = cached_value.tag
- data += res.main_line_status_box.substitute(subs)
-
- json += ("{'url': '%s', 'title': '%s', 'color': '%s',"
- " 'name': '%s'}," % (subs["url"], subs["title"],
- subs["color"],
- urllib.quote(builder)))
-
- # If the box is red, we add the explaination in the details
- # section.
- if cached_value.details and cached_value.color == "failure":
- details += cached_value.details
-
- continue
-
-
- # Find the first build that does not include the revision.
- for build in allBuilds[builder]:
- if self.comparator.isRevisionEarlier(build, revision):
- firstNotIn = build
- break
- else:
- introducedIn = build
-
- # Get the results of the first build with the revision, and the
- # first build that does not include the revision.
- results = None
- inProgressResults = None
- previousResults = None
- if introducedIn:
- results = introducedIn.results
- inProgressResults = introducedIn.inProgressResults
- if firstNotIn:
- previousResults = firstNotIn.results
-
- isRunning = False
- if introducedIn and not introducedIn.isFinished:
- isRunning = True
-
- url = "./waterfall"
- title = builder
- tag = ""
- current_details = None
- if introducedIn:
- current_details = introducedIn.details or ""
- url = "./buildstatus?builder=%s&number=%s" % (urllib.quote(builder),
- introducedIn.number)
- title += " "
- title += urllib.quote(' '.join(introducedIn.text), ' \n\\/:')
-
- builderStrip = builder.replace(' ', '')
- builderStrip = builderStrip.replace('(', '')
- builderStrip = builderStrip.replace(')', '')
- builderStrip = builderStrip.replace('.', '')
- tag = "Tag%s%s" % (builderStrip, introducedIn.number)
-
- if isRunning:
- title += ' ETA: %ds' % (introducedIn.eta or 0)
-
- resultsClass = getResultsClass(results, previousResults, isRunning,
- inProgressResults)
- subs["url"] = url
- subs["title"] = title
- subs["color"] = resultsClass
- subs["tag"] = tag
-
- json += ("{'url': '%s', 'title': '%s', 'color': '%s',"
- " 'name': '%s'}," % (url, title, resultsClass,
- urllib.quote(builder)))
- data += res.main_line_status_box.substitute(subs)
-
- # If the box is red, we add the explaination in the details
- # section.
- if current_details and resultsClass == "failure":
- details += current_details
-
- # Add this box to the cache if it's completed so we don't have
- # to compute it again.
- if resultsClass != "running" and \
- resultsClass != "running_failure" and \
- resultsClass != "notstarted":
- debugInfo["added_blocks"] += 1
- self.cache.insert(builder, revision.revision, resultsClass, title,
- current_details, url, tag)
- tempCache.insert(builder, revision.revision)
-
- json += ']'
- data += res.main_line_status_footer.substitute(subs)
-
- if jsonFormat:
- return (json, details)
-
- return (data, details)
-
- def displayPage(self, request, status, builderList, allBuilds, revisions,
- categories, branch, tempCache, debugInfo, jsonFormat=False):
- """Display the console page."""
- # Build the main template directory with all the informations we have.
- subs = dict()
- subs["projectUrl"] = status.getProjectURL() or ""
- subs["projectName"] = status.getProjectName() or ""
- safe_branch = branch
- if safe_branch and safe_branch != ANYBRANCH:
- safe_branch = urllib.quote(safe_branch)
- subs["branch"] = safe_branch or 'trunk'
- if categories:
- subs["categories"] = urllib.quote(' '.join(categories)).replace(
- '%20', ' ')
- subs["welcomeUrl"] = self.path_to_root(request) + "index.html"
- subs["version"] = version
- subs["time"] = time.strftime("%a %d %b %Y %H:%M:%S",
- time.localtime(util.now()))
- subs["debugInfo"] = debugInfo
-
-
- #
- # Show the header.
- #
-
- json = "["
- data = res.top_header.substitute(subs)
- data += res.top_info_name.substitute(subs)
-
- if categories:
- data += res.top_info_categories.substitute(subs)
-
- if branch != ANYBRANCH:
- data += res.top_info_branch.substitute(subs)
-
- data += res.top_info_name_end.substitute(subs)
- # Display the legend.
- data += res.top_legend.substitute(subs)
-
- # Display the personalize box.
- data += res.top_personalize.substitute(subs)
-
- data += res.top_footer.substitute(subs)
-
-
- #
- # Display the main page
- #
- data += res.main_header.substitute(subs)
-
- # "Alt" is set for every other line, to be able to switch the background
- # color.
- subs["alt"] = "Alt"
- subs["first"] = ""
- subs["last"] = ""
-
- # Display the categories if there is more than 1.
- if builderList and len(builderList) > 1:
- dataToAdd = self.displayCategories(builderList, debugInfo, subs)
- data += dataToAdd
-
- # Display the build slaves status.
- if builderList:
- dataToAdd = self.displaySlaveLine(status, builderList, debugInfo,
- subs, jsonFormat)
- data += dataToAdd
- json += dataToAdd + ","
-
- # For each revision we show one line
- for revision in revisions:
- if not subs["alt"]:
- subs["alt"] = "Alt"
- else:
- subs["alt"] = ""
-
- # Fill the dictionnary with these new information
- subs["revision"] = revision.revision
- if revision.revlink:
- subs["revision_link"] = ("<a href=\"%s\">%s</a>"
- % (revision.revlink,
- revision.revision))
- else:
- subs["revision_link"] = revision.revision
- subs["who"] = revision.who
- subs["date"] = revision.date
- comment = revision.comments or ""
- subs["comments"] = comment.replace('<', '&lt;').replace('>', '&gt;')
- # Re-encode to make sure it doesn't throw an encoding error on the
- # server.
- try:
- comment_quoted = urllib.quote(
- subs["comments"].decode("utf-8", "ignore").encode(
- "ascii", "xmlcharrefreplace"))
- except UnicodeEncodeError:
- # TODO(maruel): Figure out what's happening.
- comment_quoted = urllib.quote(subs["comments"].encode("utf-8"))
- json += ( "{'revision': '%s', 'date': '%s', 'comments': '%s',"
- "'results' : " ) % (subs["revision"], subs["date"],
- comment_quoted)
-
- # Display the revision number and the committer.
- data += res.main_line_info.substitute(subs)
-
- # Display the status for all builders.
- (dataToAdd, details) = self.displayStatusLine(builderList,
- allBuilds,
- revision,
- tempCache,
- debugInfo,
- subs,
- jsonFormat)
- data += dataToAdd
- json += dataToAdd + "}"
-
- # Calculate the td span for the comment and the details.
- subs["span"] = len(builderList) + 2
-
- # Display the details of the failures, if any.
- if details:
- subs["details"] = details
- data += res.main_line_details.substitute(subs)
-
- # Display the comments for this revision
- data += res.main_line_comments.substitute(subs)
-
- data += res.main_footer.substitute(subs)
-
- #
- # Display the footer of the page.
- #
- debugInfo["load_time"] = time.time() - debugInfo["load_time"]
- data += res.bottom.substitute(subs)
-
- json += "]"
- if jsonFormat:
- return json
-
- return data
-
- def body(self, request):
- "This method builds the main console view display."
-
- # Debug information to display at the end of the page.
- debugInfo = dict()
- debugInfo["load_time"] = time.time()
-
- # get url parameters
- # Categories to show information for.
- categories = request.args.get("category", [])
- # List of all builders to show on the page.
- builders = request.args.get("builder", [])
- # Branch used to filter the changes shown.
- branch = request.args.get("branch", [ANYBRANCH])[0]
- # List of all the committers name to display on the page.
- devName = request.args.get("name", [])
- # json format.
- jsonFormat = request.args.get("json", [False])[0]
-
-
- # and the data we want to render
- status = self.getStatus(request)
-
- projectURL = status.getProjectURL()
- projectName = status.getProjectName()
-
- # Get all revisions we can find.
- source = self.getChangemaster(request)
- allChanges = self.getAllChanges(source, status, debugInfo)
-
- debugInfo["source_all"] = len(allChanges)
-
- # Keep only the revisions we care about.
- # By default we process the last 40 revisions.
- # If a dev name is passed, we look for the changes by this person in the
- # last 160 revisions.
- numRevs = 40
- if devName:
- numRevs *= 4
- numBuilds = numRevs
-
-
- revisions = self.stripRevisions(allChanges, numRevs, branch, devName)
- debugInfo["revision_final"] = len(revisions)
-
- # Fetch all the builds for all builders until we get the next build
- # after lastRevision.
- builderList = None
- allBuilds = None
- if revisions:
- lastRevision = revisions[len(revisions)-1].revision
- debugInfo["last_revision"] = lastRevision
-
- (builderList, allBuilds) = self.getAllBuildsForRevision(status,
- request,
- lastRevision,
- numBuilds,
- categories,
- builders,
- debugInfo)
-
- tempCache = TemporaryCache()
- debugInfo["added_blocks"] = 0
- debugInfo["from_cache"] = 0
-
- data = ""
-
- if request.args.get("display_cache", None):
- data += "<br>Global Cache"
- data += self.cache.display()
- data += "<br>Temporary Cache"
- data += tempCache.display()
-
- if (jsonFormat and int(jsonFormat) == 1):
- revisions = revisions[0:1]
- data += self.displayPage(request, status, builderList, allBuilds,
- revisions, categories, branch, tempCache,
- debugInfo, jsonFormat)
-
- if not devName and branch == ANYBRANCH and not categories and not jsonFormat:
- tempCache.updateGlobalCache(self.cache)
- self.cache.trim()
-
- return data
-
-class RevisionComparator(object):
- """Used for comparing between revisions, as some
- VCS use a plain counter for revisions (like SVN)
- while others use different concepts (see Git).
- """
-
- # TODO (avivby): Should this be a zope interface?
-
- def isRevisionEarlier(self, first_change, second_change):
- """Used for comparing 2 changes"""
- raise NotImplementedError
-
- def isValidRevision(self, revision):
- """Checks whether the revision seems like a VCS revision"""
- raise NotImplementedError
-
- def getSortingKey(self):
- raise NotImplementedError
-
-class TimeRevisionComparator(RevisionComparator):
- def isRevisionEarlier(self, first, second):
- return first.when < second.when
-
- def isValidRevision(self, revision):
- return True # No general way of determining
-
- def getSortingKey(self):
- return "when"
-
-class IntegerRevisionComparator(RevisionComparator):
- def isRevisionEarlier(self, first, second):
- return int(first.revision) < int(second.revision)
-
- def isValidRevision(self, revision):
- try:
- int(revision)
- return True
- except:
- return False
-
- def getSortingKey(self):
- return "revision"

Powered by Google App Engine
This is Rietveld 408576698