| Index: third_party/buildbot_7_12/buildbot/status/web/grid.py
|
| diff --git a/third_party/buildbot_7_12/buildbot/status/web/grid.py b/third_party/buildbot_7_12/buildbot/status/web/grid.py
|
| deleted file mode 100644
|
| index 09b0471df4dc784c8dd06011cc27cd0df56146d1..0000000000000000000000000000000000000000
|
| --- a/third_party/buildbot_7_12/buildbot/status/web/grid.py
|
| +++ /dev/null
|
| @@ -1,331 +0,0 @@
|
| -from __future__ import generators
|
| -
|
| -import sys, time, os.path
|
| -import urllib
|
| -
|
| -from twisted.web import html, resource
|
| -
|
| -from buildbot import util
|
| -from buildbot import version
|
| -from buildbot.status.web.base import HtmlResource
|
| -#from buildbot.status.web.base import Box, HtmlResource, IBox, ICurrentBox, \
|
| -# ITopBox, td, build_get_class, path_to_build, path_to_step, map_branches
|
| -from buildbot.status.web.base import build_get_class
|
| -
|
| -# set grid_css to the full pathname of the css file
|
| -if hasattr(sys, "frozen"):
|
| - # all 'data' files are in the directory of our executable
|
| - here = os.path.dirname(sys.executable)
|
| - grid_css = os.path.abspath(os.path.join(here, "grid.css"))
|
| -else:
|
| - # running from source; look for a sibling to __file__
|
| - up = os.path.dirname
|
| - grid_css = os.path.abspath(os.path.join(up(__file__), "grid.css"))
|
| -
|
| -class ANYBRANCH: pass # a flag value, used below
|
| -
|
| -class GridStatusMixin(object):
|
| - def getTitle(self, request):
|
| - status = self.getStatus(request)
|
| - p = status.getProjectName()
|
| - if p:
|
| - return "BuildBot: %s" % p
|
| - else:
|
| - return "BuildBot"
|
| -
|
| - def getChangemaster(self, request):
|
| - # TODO: this wants to go away, access it through IStatus
|
| - return request.site.buildbot_service.getChangeSvc()
|
| -
|
| - # handle reloads through an http header
|
| - # TODO: send this as a real header, rather than a tag
|
| - def get_reload_time(self, request):
|
| - if "reload" in request.args:
|
| - try:
|
| - reload_time = int(request.args["reload"][0])
|
| - return max(reload_time, 15)
|
| - except ValueError:
|
| - pass
|
| - return None
|
| -
|
| - def head(self, request):
|
| - head = ''
|
| - reload_time = self.get_reload_time(request)
|
| - if reload_time is not None:
|
| - head += '<meta http-equiv="refresh" content="%d">\n' % reload_time
|
| - return head
|
| -
|
| -# def setBuildmaster(self, buildmaster):
|
| -# self.status = buildmaster.getStatus()
|
| -# if self.allowForce:
|
| -# self.control = interfaces.IControl(buildmaster)
|
| -# else:
|
| -# self.control = None
|
| -# self.changemaster = buildmaster.change_svc
|
| -#
|
| -# # try to set the page title
|
| -# p = self.status.getProjectName()
|
| -# if p:
|
| -# self.title = "BuildBot: %s" % p
|
| -#
|
| - def build_td(self, request, build):
|
| - if not build:
|
| - return '<td class="build"> </td>\n'
|
| -
|
| - if build.isFinished():
|
| - # get the text and annotate the first line with a link
|
| - text = build.getText()
|
| - if not text: text = [ "(no information)" ]
|
| - if text == [ "build", "successful" ]: text = [ "OK" ]
|
| - else:
|
| - text = [ 'building' ]
|
| -
|
| - name = build.getBuilder().getName()
|
| - number = build.getNumber()
|
| - url = "builders/%s/builds/%d" % (name, number)
|
| - text[0] = '<a href="%s">%s</a>' % (url, text[0])
|
| - text = '<br />\n'.join(text)
|
| - class_ = build_get_class(build)
|
| -
|
| - return '<td class="build %s">%s</td>\n' % (class_, text)
|
| -
|
| - def builder_td(self, request, builder):
|
| - state, builds = builder.getState()
|
| -
|
| - # look for upcoming builds. We say the state is "waiting" if the
|
| - # builder is otherwise idle and there is a scheduler which tells us a
|
| - # build will be performed some time in the near future. TODO: this
|
| - # functionality used to be in BuilderStatus.. maybe this code should
|
| - # be merged back into it.
|
| - upcoming = []
|
| - builderName = builder.getName()
|
| - for s in self.getStatus(request).getSchedulers():
|
| - if builderName in s.listBuilderNames():
|
| - upcoming.extend(s.getPendingBuildTimes())
|
| - if state == "idle" and upcoming:
|
| - state = "waiting"
|
| -
|
| - # TODO: for now, this pending/upcoming stuff is in the "current
|
| - # activity" box, but really it should go into a "next activity" row
|
| - # instead. The only times it should show up in "current activity" is
|
| - # when the builder is otherwise idle.
|
| -
|
| - # are any builds pending? (waiting for a slave to be free)
|
| - url = 'builders/%s/' % urllib.quote(builder.getName(), safe='')
|
| - text = '<a href="%s">%s</a>' % (url, builder.getName())
|
| - pbs = builder.getPendingBuilds()
|
| - if state != 'idle' or pbs:
|
| - if pbs:
|
| - text += "<br />(%s with %d pending)" % (state, len(pbs))
|
| - else:
|
| - text += "<br />(%s)" % state
|
| -
|
| - return '<td valign="center" class="builder %s">%s</td>\n' % \
|
| - (state, text)
|
| -
|
| - def stamp_td(self, stamp):
|
| - text = stamp.getText()
|
| - return '<td valign="bottom" class="sourcestamp">%s</td>\n' % \
|
| - "<br />".join(text)
|
| -
|
| - def getSourceStampKey(self, ss):
|
| - """Given two source stamps, we want to assign them to the same row if
|
| - they are the same version of code, even if they differ in minor detail.
|
| -
|
| - This function returns an appropriate comparison key for that.
|
| - """
|
| - return (ss.branch, ss.revision, ss.patch)
|
| -
|
| - def getRecentSourcestamps(self, status, numBuilds, categories, branch):
|
| - """
|
| - get a list of the most recent NUMBUILDS SourceStamp tuples, sorted
|
| - by the earliest start we've seen for them
|
| - """
|
| - # TODO: use baseweb's getLastNBuilds?
|
| - sourcestamps = { } # { ss-tuple : earliest time }
|
| - for bn in status.getBuilderNames():
|
| - builder = status.getBuilder(bn)
|
| - if categories and builder.category not in categories:
|
| - continue
|
| - build = builder.getBuild(-1)
|
| - while build:
|
| - ss = build.getSourceStamp(absolute=True)
|
| - start = build.getTimes()[0]
|
| - build = build.getPreviousBuild()
|
| -
|
| - # skip un-started builds
|
| - if not start: continue
|
| -
|
| - # skip non-matching branches
|
| - if branch != ANYBRANCH and ss.branch != branch: continue
|
| -
|
| - key= self.getSourceStampKey(ss)
|
| - if key not in sourcestamps or sourcestamps[key][1] > start:
|
| - sourcestamps[key] = (ss, start)
|
| -
|
| - # now sort those and take the NUMBUILDS most recent
|
| - sourcestamps = sourcestamps.values()
|
| - sourcestamps.sort(lambda x, y: cmp(x[1], y[1]))
|
| - sourcestamps = map(lambda tup : tup[0], sourcestamps)
|
| - sourcestamps = sourcestamps[-numBuilds:]
|
| -
|
| - return sourcestamps
|
| -
|
| -class GridStatusResource(HtmlResource, GridStatusMixin):
|
| - # TODO: docs
|
| - status = None
|
| - control = None
|
| - changemaster = None
|
| -
|
| - def __init__(self, allowForce=True, css=None):
|
| - HtmlResource.__init__(self)
|
| -
|
| - self.allowForce = allowForce
|
| - self.css = css or grid_css
|
| -
|
| -
|
| - def body(self, request):
|
| - """This method builds the regular grid display.
|
| - That is, build stamps across the top, build hosts down the left side
|
| - """
|
| -
|
| - # get url parameters
|
| - numBuilds = int(request.args.get("width", [5])[0])
|
| - categories = request.args.get("category", [])
|
| - branch = request.args.get("branch", [ANYBRANCH])[0]
|
| - if branch == 'trunk': branch = None
|
| -
|
| - # and the data we want to render
|
| - status = self.getStatus(request)
|
| - stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch)
|
| -
|
| - projectURL = status.getProjectURL()
|
| - projectName = status.getProjectName()
|
| -
|
| - data = '<table class="Grid" border="0" cellspacing="0">\n'
|
| - data += '<tr>\n'
|
| - data += '<td class="title"><a href="%s">%s</a>' % (projectURL, projectName)
|
| - if categories:
|
| - html_categories = map(html.escape, categories)
|
| - if len(categories) > 1:
|
| - data += '\n<br /><b>Categories:</b><br/>%s' % ('<br/>'.join(html_categories))
|
| - else:
|
| - data += '\n<br /><b>Category:</b> %s' % html_categories[0]
|
| - if branch != ANYBRANCH:
|
| - data += '\n<br /><b>Branch:</b> %s' % (html.escape(branch or 'trunk'))
|
| - data += '</td>\n'
|
| - for stamp in stamps:
|
| - data += self.stamp_td(stamp)
|
| - data += '</tr>\n'
|
| -
|
| - sortedBuilderNames = status.getBuilderNames()[:]
|
| - sortedBuilderNames.sort()
|
| - for bn in sortedBuilderNames:
|
| - builds = [None] * len(stamps)
|
| -
|
| - builder = status.getBuilder(bn)
|
| - if categories and builder.category not in categories:
|
| - continue
|
| -
|
| - build = builder.getBuild(-1)
|
| - while build and None in builds:
|
| - ss = build.getSourceStamp(absolute=True)
|
| - key= self.getSourceStampKey(ss)
|
| - for i in range(len(stamps)):
|
| - if key == self.getSourceStampKey(stamps[i]) and builds[i] is None:
|
| - builds[i] = build
|
| - build = build.getPreviousBuild()
|
| -
|
| - data += '<tr>\n'
|
| - data += self.builder_td(request, builder)
|
| - for build in builds:
|
| - data += self.build_td(request, build)
|
| - data += '</tr>\n'
|
| -
|
| - data += '</table>\n'
|
| -
|
| - data += self.footer(status, request)
|
| - return data
|
| -
|
| -class TransposedGridStatusResource(HtmlResource, GridStatusMixin):
|
| - # TODO: docs
|
| - status = None
|
| - control = None
|
| - changemaster = None
|
| -
|
| - def __init__(self, allowForce=True, css=None):
|
| - HtmlResource.__init__(self)
|
| -
|
| - self.allowForce = allowForce
|
| - self.css = css or grid_css
|
| -
|
| -
|
| - def body(self, request):
|
| - """This method builds the transposed grid display.
|
| - That is, build hosts across the top, ebuild stamps down the left side
|
| - """
|
| -
|
| - # get url parameters
|
| - numBuilds = int(request.args.get("length", [5])[0])
|
| - categories = request.args.get("category", [])
|
| - branch = request.args.get("branch", [ANYBRANCH])[0]
|
| - if branch == 'trunk': branch = None
|
| -
|
| - # and the data we want to render
|
| - status = self.getStatus(request)
|
| - stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch)
|
| -
|
| - projectURL = status.getProjectURL()
|
| - projectName = status.getProjectName()
|
| -
|
| - data = '<table class="Grid" border="0" cellspacing="0">\n'
|
| - data += '<tr>\n'
|
| - data += '<td class="title"><a href="%s">%s</a>' % (projectURL, projectName)
|
| - if categories:
|
| - html_categories = map(html.escape, categories)
|
| - if len(categories) > 1:
|
| - data += '\n<br /><b>Categories:</b><br/>%s' % ('<br/>'.join(html_categories))
|
| - else:
|
| - data += '\n<br /><b>Category:</b> %s' % html_categories[0]
|
| - if branch != ANYBRANCH:
|
| - data += '\n<br /><b>Branch:</b> %s' % (html.escape(branch or 'trunk'))
|
| - data += '</td>\n'
|
| -
|
| - sortedBuilderNames = status.getBuilderNames()[:]
|
| - sortedBuilderNames.sort()
|
| -
|
| - builder_builds = []
|
| -
|
| - for bn in sortedBuilderNames:
|
| - builds = [None] * len(stamps)
|
| -
|
| - builder = status.getBuilder(bn)
|
| - if categories and builder.category not in categories:
|
| - continue
|
| -
|
| - build = builder.getBuild(-1)
|
| - while build and None in builds:
|
| - ss = build.getSourceStamp(absolute=True)
|
| - key = self.getSourceStampKey(ss)
|
| - for i in range(len(stamps)):
|
| - if key == self.getSourceStampKey(stamps[i]) and builds[i] is None:
|
| - builds[i] = build
|
| - build = build.getPreviousBuild()
|
| -
|
| - data += self.builder_td(request, builder)
|
| - builder_builds.append(builds)
|
| -
|
| - data += '</tr>\n'
|
| -
|
| - for i in range(len(stamps)):
|
| - data += '<tr>\n'
|
| - data += self.stamp_td(stamps[i])
|
| - for builds in builder_builds:
|
| - data += self.build_td(request, builds[i])
|
| - data += '</tr>\n'
|
| -
|
| - data += '</table>\n'
|
| -
|
| - data += self.footer(status, request)
|
| - return data
|
| -
|
|
|