diff options
Diffstat (limited to 'lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web')
73 files changed, 0 insertions, 10364 deletions
diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/__init__.py +++ /dev/null diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py deleted file mode 100644 index 0a5e068b..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/about.py +++ /dev/null @@ -1,35 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from buildbot.status.web.base import HtmlResource -import buildbot -import twisted -import sys -import jinja2 - -class AboutBuildbot(HtmlResource): - pageTitle = "About this Buildbot" - - def content(self, request, cxt): - cxt.update(dict(buildbot=buildbot.version, - twisted=twisted.__version__, - jinja=jinja2.__version__, - python=sys.version, - platform=sys.platform)) - - template = request.site.buildbot_service.templates.get_template("about.html") - template.autoescape = True - return template.render(**cxt) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py deleted file mode 100644 index e9b168c9..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/auth.py +++ /dev/null @@ -1,220 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -import os -from zope.interface import Interface, Attribute, implements -from buildbot.status.web.base import HtmlResource, ActionResource -from buildbot.status.web.base import path_to_authfail - -from buildbot.process.users import users - -class IAuth(Interface): - """ - Represent an authentication method. - - Note that each IAuth instance contains a link to the BuildMaster that - will be set once the IAuth instance is initialized. - """ - - master = Attribute('master', "Link to BuildMaster, set when initialized") - - def authenticate(self, user, passwd): - """Check whether C{user} / C{passwd} are valid.""" - - def getUserInfo(self, user): - """return dict with user info. - dict( fullName="", email="", groups=[]) - """ - - def errmsg(self): - """Get the reason authentication failed.""" - -class AuthBase: - master = None # set in status.web.baseweb - err = "" - - def errmsg(self): - return self.err - - def getUserInfo(self, user): - """default dummy impl""" - return dict(userName=user, fullName=user, email=user+"@localhost", groups=[ user ]) - -class BasicAuth(AuthBase): - implements(IAuth) - """Implement basic authentication against a list of user/passwd.""" - - userpass = [] - """List of user/pass tuples.""" - - def __init__(self, userpass): - """C{userpass} is a list of (user, passwd).""" - for item in userpass: - assert isinstance(item, tuple) or isinstance(item, list) - u, p = item - assert isinstance(u, str) - assert isinstance(p, str) - self.userpass = userpass - - def authenticate(self, user, passwd): - """Check that C{user}/C{passwd} is a valid user/pass tuple.""" - if not self.userpass: - self.err = "Bad self.userpass data" - return False - for u, p in self.userpass: - if user == u and passwd == p: - self.err = "" - return True - self.err = "Invalid username or password" - return False - -class HTPasswdAuth(AuthBase): - implements(IAuth) - """Implement authentication against an .htpasswd file.""" - - file = "" - """Path to the .htpasswd file to use.""" - - def __init__(self, file): - """C{file} is a path to an .htpasswd file.""" - assert os.path.exists(file) - self.file = file - - def authenticate(self, user, passwd): - """Authenticate C{user} and C{passwd} against an .htpasswd file""" - if not os.path.exists(self.file): - self.err = "No such file: " + self.file - return False - # Fetch each line from the .htpasswd file and split it into a - # [user, passwd] array. - lines = [l.rstrip().split(':', 1) - for l in file(self.file).readlines()] - # Keep only the line for this login - lines = [l for l in lines if l[0] == user] - if not lines: - self.err = "Invalid user/passwd" - return False - hash = lines[0][1] - res = self.validatePassword(passwd, hash) - if res: - self.err = "" - else: - self.err = "Invalid user/passwd" - return res - - def validatePassword(self, passwd, hash): - # This is the DES-hash of the password. The first two characters are - # the salt used to introduce disorder in the DES algorithm. - from crypt import crypt #@UnresolvedImport - return hash == crypt(passwd, hash[0:2]) - - -class HTPasswdAprAuth(HTPasswdAuth): - implements(IAuth) - """Implement authentication against an .htpasswd file based on libaprutil""" - - file = "" - """Path to the .htpasswd file to use.""" - - def __init__(self, file): - HTPasswdAuth.__init__(self, file) - - # Try to load libaprutil throug ctypes - self.apr = None - try: - from ctypes import CDLL - from ctypes.util import find_library - lib = find_library("aprutil-1") - if lib: - self.apr = CDLL(lib) - except: - self.apr = None - - def validatePassword(self, passwd, hash): - # Use apr_password_validate from libaprutil if libaprutil is available. - # Fallback to DES only checking from HTPasswdAuth - if self.apr: - return self.apr.apr_password_validate(passwd, hash) == 0 - else: - return HTPasswdAuth.validatePassword(self, passwd, hash) - -class UsersAuth(AuthBase): - """Implement authentication against users in database""" - implements(IAuth) - - def authenticate(self, user, passwd): - """ - It checks for a matching uid in the database for the credentials - and return True if a match is found, False otherwise. - - @param user: username portion of user credentials - @type user: string - - @param passwd: password portion of user credentials - @type passwd: string - - @returns: boolean via deferred. - """ - d = self.master.db.users.getUserByUsername(user) - def check_creds(user): - if user: - if users.check_passwd(passwd, user['bb_password']): - return True - self.err = "no user found with those credentials" - return False - d.addCallback(check_creds) - return d - -class AuthFailResource(HtmlResource): - pageTitle = "Authentication Failed" - - def content(self, request, cxt): - templates =request.site.buildbot_service.templates - template = templates.get_template("authfail.html") - return template.render(**cxt) - -class AuthzFailResource(HtmlResource): - pageTitle = "Authorization Failed" - - def content(self, request, cxt): - templates =request.site.buildbot_service.templates - template = templates.get_template("authzfail.html") - return template.render(**cxt) - -class LoginResource(ActionResource): - - def performAction(self, request): - authz = self.getAuthz(request) - d = authz.login(request) - def on_login(res): - if res: - status = request.site.buildbot_service.master.status - root = status.getBuildbotURL() - return request.requestHeaders.getRawHeaders('referer', - [root])[0] - else: - return path_to_authfail(request) - d.addBoth(on_login) - return d - -class LogoutResource(ActionResource): - - def performAction(self, request): - authz = self.getAuthz(request) - authz.logout(request) - status = request.site.buildbot_service.master.status - root = status.getBuildbotURL() - return request.requestHeaders.getRawHeaders('referer',[root])[0] diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py deleted file mode 100644 index dace7f23..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/authz.py +++ /dev/null @@ -1,188 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -from twisted.internet import defer -from buildbot.status.web.auth import IAuth -from buildbot.status.web.session import SessionManager - -COOKIE_KEY="BuildBotSession" -class Authz(object): - """Decide who can do what.""" - - knownActions = [ - # If you add a new action here, be sure to also update the documentation - # at docs/manual/cfg-statustargets.rst. - 'view', - 'gracefulShutdown', - 'forceBuild', - 'forceAllBuilds', - 'pingBuilder', - 'stopBuild', - 'stopAllBuilds', - 'cancelPendingBuild', - 'cancelAllPendingBuilds', - 'stopChange', - 'cleanShutdown', - 'showUsersPage', - 'pauseSlave', - ] - - def __init__(self, - default_action=False, - auth=None, - useHttpHeader=False, - httpLoginUrl=False, - view=True, - **kwargs): - self.auth = auth - if auth: - assert IAuth.providedBy(auth) - - self.useHttpHeader = useHttpHeader - self.httpLoginUrl = httpLoginUrl - - self.config = dict((a, default_action) for a in self.knownActions) - self.config['view'] = view - for act in self.knownActions: - if act in kwargs: - self.config[act] = kwargs[act] - del kwargs[act] - - self.sessions = SessionManager() - if kwargs: - raise ValueError("unknown authorization action(s) " + ", ".join(kwargs.keys())) - - def session(self, request): - if COOKIE_KEY in request.received_cookies: - cookie = request.received_cookies[COOKIE_KEY] - return self.sessions.get(cookie) - return None - - def authenticated(self, request): - if self.useHttpHeader: - return request.getUser() != '' - return self.session(request) is not None - - def getUserInfo(self, user): - if self.useHttpHeader: - return dict(userName=user, fullName=user, email=user, groups=[user]) - s = self.sessions.getUser(user) - if s: - return s.infos - - def getUsername(self, request): - """Get the userid of the user""" - if self.useHttpHeader: - return request.getUser() - s = self.session(request) - if s: - return s.user - return request.args.get("username", ["<unknown>"])[0] - - def getUsernameHTML(self, request): - """Get the user formatated in html (with possible link to email)""" - if self.useHttpHeader: - return request.getUser() - s = self.session(request) - if s: - return s.userInfosHTML() - return "not authenticated?!" - - def getUsernameFull(self, request): - """Get the full username as fullname <email>""" - if self.useHttpHeader: - return request.getUser() - s = self.session(request) - if s: - return "%(fullName)s <%(email)s>" % (s.infos) - else: - return request.args.get("username", ["<unknown>"])[0] - - - def getPassword(self, request): - if self.useHttpHeader: - return request.getPassword() - return request.args.get("passwd", ["<no-password>"])[0] - - def advertiseAction(self, action, request): - """Should the web interface even show the form for ACTION?""" - if action not in self.knownActions: - raise KeyError("unknown action") - cfg = self.config.get(action, False) - if cfg: - if cfg == 'auth' or callable(cfg): - return self.authenticated(request) - return cfg - - def actionAllowed(self, action, request, *args): - """Is this ACTION allowed, given this http REQUEST?""" - if action not in self.knownActions: - raise KeyError("unknown action") - cfg = self.config.get(action, False) - if cfg: - if cfg == 'auth' or callable(cfg): - if not self.auth: - return defer.succeed(False) - def check_authenticate(res): - if callable(cfg) and not cfg(self.getUsername(request), *args): - return False - return True - # retain old behaviour, if people have scripts - # without cookie support - passwd = self.getPassword(request) - if self.authenticated(request): - return defer.succeed(check_authenticate(None)) - elif passwd != "<no-password>": - def check_login(cookie): - ret = False - if isinstance(cookie, str): - ret = check_authenticate(None) - self.sessions.remove(cookie) - return ret - d = self.login(request) - d.addBoth(check_login) - return d - else: - return defer.succeed(False) - return defer.succeed(cfg) - - def login(self, request): - """Login one user, and return session cookie""" - if self.authenticated(request): - return defer.succeed(False) - - user = request.args.get("username", ["<unknown>"])[0] - passwd = request.args.get("passwd", ["<no-password>"])[0] - if user == "<unknown>" or passwd == "<no-password>": - return defer.succeed(False) - if not self.auth: - return defer.succeed(False) - d = defer.maybeDeferred(self.auth.authenticate, user, passwd) - - def check_authenticate(res): - if res: - cookie, s = self.sessions.new(user, self.auth.getUserInfo(user)) - request.addCookie(COOKIE_KEY, cookie, expires=s.getExpiration(), path="/") - request.received_cookies = {COOKIE_KEY: cookie} - return cookie - else: - return False - d.addBoth(check_authenticate) - return d - - def logout(self, request): - if COOKIE_KEY in request.received_cookies: - cookie = request.received_cookies[COOKIE_KEY] - self.sessions.remove(cookie) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py deleted file mode 100644 index 47a3f344..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/base.py +++ /dev/null @@ -1,806 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -import urlparse, urllib, time, re -import os, cgi, sys, locale -import jinja2 -from zope.interface import Interface -from twisted.internet import defer -from twisted.web import resource, static, server -from twisted.python import log -from buildbot.status import builder, buildstep, build -from buildbot.status.results import SUCCESS, WARNINGS, FAILURE, SKIPPED -from buildbot.status.results import EXCEPTION, RETRY -from buildbot import version, util -from buildbot.process.properties import Properties - -class ITopBox(Interface): - """I represent a box in the top row of the waterfall display: the one - which shows the status of the last build for each builder.""" - def getBox(self, request): - """Return a Box instance, which can produce a <td> cell. - """ - -class ICurrentBox(Interface): - """I represent the 'current activity' box, just above the builder name.""" - def getBox(self, status): - """Return a Box instance, which can produce a <td> cell. - """ - -class IBox(Interface): - """I represent a box in the waterfall display.""" - def getBox(self, request): - """Return a Box instance, which wraps an Event and can produce a <td> - cell. - """ - -class IHTMLLog(Interface): - pass - -css_classes = {SUCCESS: "success", - WARNINGS: "warnings", - FAILURE: "failure", - SKIPPED: "skipped", - EXCEPTION: "exception", - RETRY: "retry", - None: "", - } - - -def getAndCheckProperties(req): - """ - Fetch custom build properties from the HTTP request of a "Force build" or - "Resubmit build" HTML form. - Check the names for valid strings, and return None if a problem is found. - Return a new Properties object containing each property found in req. - """ - master = req.site.buildbot_service.master - pname_validate = master.config.validation['property_name'] - pval_validate = master.config.validation['property_value'] - properties = Properties() - i = 1 - while True: - pname = req.args.get("property%dname" % i, [""])[0] - pvalue = req.args.get("property%dvalue" % i, [""])[0] - if not pname: - break - if not pname_validate.match(pname) \ - or not pval_validate.match(pvalue): - log.msg("bad property name='%s', value='%s'" % (pname, pvalue)) - return None - properties.setProperty(pname, pvalue, "Force Build Form") - i = i + 1 - - return properties - -def build_get_class(b): - """ - Return the class to use for a finished build or buildstep, - based on the result. - """ - # FIXME: this getResults duplicity might need to be fixed - result = b.getResults() - if isinstance(b, build.BuildStatus): - result = b.getResults() - elif isinstance(b, buildstep.BuildStepStatus): - result = b.getResults()[0] - # after forcing a build, b.getResults() returns ((None, []), []), ugh - if isinstance(result, tuple): - result = result[0] - else: - raise TypeError, "%r is not a BuildStatus or BuildStepStatus" % b - - if result == None: - # FIXME: this happens when a buildstep is running ? - return "running" - return builder.Results[result] - -def path_to_root(request): - # /waterfall : ['waterfall'] -> './' - # /somewhere/lower : ['somewhere', 'lower'] -> '../' - # /somewhere/indexy/ : ['somewhere', 'indexy', ''] -> '../../' - # / : [] -> './' - if request.prepath: - segs = len(request.prepath) - 1 - else: - segs = 0 - root = "../" * segs if segs else './' - return root - -def path_to_authfail(request): - return path_to_root(request) + "authfail" - -def path_to_authzfail(request): - return path_to_root(request) + "authzfail" - -def path_to_builder(request, builderstatus): - return (path_to_root(request) + - "builders/" + - urllib.quote(builderstatus.getName(), safe='')) - -def path_to_build(request, buildstatus): - return (path_to_builder(request, buildstatus.getBuilder()) + - "/builds/%d" % buildstatus.getNumber()) - -def path_to_step(request, stepstatus): - return (path_to_build(request, stepstatus.getBuild()) + - "/steps/%s" % urllib.quote(stepstatus.getName(), safe='')) - -def path_to_slave(request, slave): - return (path_to_root(request) + - "buildslaves/" + - urllib.quote(slave.getName(), safe='')) - -def path_to_change(request, change): - return (path_to_root(request) + - "changes/%s" % change.number) - -class Box: - # a Box wraps an Event. The Box has HTML <td> parameters that Events - # lack, and it has a base URL to which each File's name is relative. - # Events don't know about HTML. - spacer = False - def __init__(self, text=[], class_=None, urlbase=None, - **parms): - self.text = text - self.class_ = class_ - self.urlbase = urlbase - self.show_idle = 0 - if parms.has_key('show_idle'): - del parms['show_idle'] - self.show_idle = 1 - - self.parms = parms - # parms is a dict of HTML parameters for the <td> element that will - # represent this Event in the waterfall display. - - def td(self, **props): - props.update(self.parms) - text = self.text - if not text and self.show_idle: - text = ["[idle]"] - props['class'] = self.class_ - props['text'] = text; - return props - - -class AccessorMixin(object): - def getStatus(self, request): - return request.site.buildbot_service.getStatus() - - def getPageTitle(self, request): - return self.pageTitle - - def getAuthz(self, request): - return request.site.buildbot_service.authz - - def getBuildmaster(self, request): - return request.site.buildbot_service.master - - -class ContextMixin(AccessorMixin): - def getContext(self, request): - status = self.getStatus(request) - rootpath = path_to_root(request) - locale_enc = locale.getdefaultlocale()[1] - if locale_enc is not None: - locale_tz = unicode(time.tzname[time.localtime()[-1]], locale_enc) - else: - locale_tz = unicode(time.tzname[time.localtime()[-1]]) - return dict(title_url = status.getTitleURL(), - title = status.getTitle(), - stylesheet = rootpath + 'default.css', - path_to_root = rootpath, - version = version, - time = time.strftime("%a %d %b %Y %H:%M:%S", - time.localtime(util.now())), - tz = locale_tz, - metatags = [], - pageTitle = self.getPageTitle(request), - welcomeurl = rootpath, - authz = self.getAuthz(request), - request = request, - alert_msg = request.args.get("alert_msg", [""])[0], - ) - - -class ActionResource(resource.Resource, AccessorMixin): - """A resource that performs some action, then redirects to a new URL.""" - - isLeaf = 1 - - def getChild(self, name, request): - return self - - def performAction(self, request): - """ - Perform the action, and return the URL to redirect to - - @param request: the web request - @returns: URL via Deferred - can also return (URL, alert_msg) to display simple - feedback to user in case of failure - """ - - def render(self, request): - d = defer.maybeDeferred(lambda : self.performAction(request)) - def redirect(url): - if isinstance(url, tuple): - url, alert_msg = url - if alert_msg: - url += "?alert_msg="+urllib.quote(alert_msg, safe='') - request.redirect(url) - request.write("see <a href='%s'>%s</a>" % (url,url)) - try: - request.finish() - except RuntimeError: - # this occurs when the client has already disconnected; ignore - # it (see #2027) - log.msg("http client disconnected before results were sent") - d.addCallback(redirect) - - def fail(f): - request.processingFailed(f) - return None # processingFailed will log this for us - d.addErrback(fail) - return server.NOT_DONE_YET - -class HtmlResource(resource.Resource, ContextMixin): - # this is a cheap sort of template thingy - contentType = "text/html; charset=utf-8" - pageTitle = "Buildbot" - addSlash = False # adapted from Nevow - - def getChild(self, path, request): - if self.addSlash and path == "" and len(request.postpath) == 0: - return self - return resource.Resource.getChild(self, path, request) - - - def content(self, req, context): - """ - Generate content using the standard layout and the result of the C{body} - method. - - This is suitable for the case where a resource just wants to generate - the body of a page. It depends on another method, C{body}, being - defined to accept the request object and return a C{str}. C{render} - will call this method and to generate the response body. - """ - body = self.body(req) - context['content'] = body - template = req.site.buildbot_service.templates.get_template( - "empty.html") - return template.render(**context) - - - def render(self, request): - # tell the WebStatus about the HTTPChannel that got opened, so they - # can close it if we get reconfigured and the WebStatus goes away. - # They keep a weakref to this, since chances are good that it will be - # closed by the browser or by us before we get reconfigured. See - # ticket #102 for details. - if hasattr(request, "channel"): - # web.distrib.Request has no .channel - request.site.buildbot_service.registerChannel(request.channel) - - # Our pages no longer require that their URL end in a slash. Instead, - # they all use request.childLink() or some equivalent which takes the - # last path component into account. This clause is left here for - # historical and educational purposes. - if False and self.addSlash and request.prepath[-1] != '': - # this is intended to behave like request.URLPath().child('') - # but we need a relative URL, since we might be living behind a - # reverse proxy - # - # note that the Location: header (as used in redirects) are - # required to have absolute URIs, and my attempt to handle - # reverse-proxies gracefully violates rfc2616. This frequently - # works, but single-component paths sometimes break. The best - # strategy is to avoid these redirects whenever possible by using - # HREFs with trailing slashes, and only use the redirects for - # manually entered URLs. - url = request.prePathURL() - scheme, netloc, path, query, fragment = urlparse.urlsplit(url) - new_url = request.prepath[-1] + "/" - if query: - new_url += "?" + query - request.redirect(new_url) - return '' - - ctx = self.getContext(request) - - d = defer.maybeDeferred(lambda : self.content(request, ctx)) - def handle(data): - request.setHeader("X-Clacks-Overhead", 'GNU N%C3%B3ir%C3%ADn Plunkett') - if isinstance(data, unicode): - data = data.encode("utf-8") - request.setHeader("content-type", self.contentType) - if request.method == "HEAD": - request.setHeader("content-length", len(data)) - return '' - return data - d.addCallback(handle) - def ok(data): - request.write(data) - try: - request.finish() - except RuntimeError: - # this occurs when the client has already disconnected; ignore - # it (see #2027) - log.msg("http client disconnected before results were sent") - def fail(f): - request.processingFailed(f) - return None # processingFailed will log this for us - d.addCallbacks(ok, fail) - return server.NOT_DONE_YET - -class StaticHTML(HtmlResource): - def __init__(self, body, pageTitle): - HtmlResource.__init__(self) - self.bodyHTML = body - self.pageTitle = pageTitle - def content(self, request, cxt): - cxt['content'] = self.bodyHTML - cxt['pageTitle'] = self.pageTitle - template = request.site.buildbot_service.templates.get_template("empty.html") - return template.render(**cxt) - -class DirectoryLister(static.DirectoryLister, ContextMixin): - """This variant of the static.DirectoryLister uses a template - for rendering.""" - - pageTitle = 'BuildBot' - - def render(self, request): - cxt = self.getContext(request) - - if self.dirs is None: - directory = os.listdir(self.path) - directory.sort() - else: - directory = self.dirs - - dirs, files = self._getFilesAndDirectories(directory) - - cxt['path'] = cgi.escape(urllib.unquote(request.uri)) - cxt['directories'] = dirs - cxt['files'] = files - template = request.site.buildbot_service.templates.get_template("directory.html") - data = template.render(**cxt) - if isinstance(data, unicode): - data = data.encode("utf-8") - return data - -class StaticFile(static.File): - """This class adds support for templated directory - views.""" - - def directoryListing(self): - return DirectoryLister(self.path, - self.listNames(), - self.contentTypes, - self.contentEncodings, - self.defaultType) - - -MINUTE = 60 -HOUR = 60*MINUTE -DAY = 24*HOUR -WEEK = 7*DAY -MONTH = 30*DAY - -def plural(word, words, num): - if int(num) == 1: - return "%d %s" % (num, word) - else: - return "%d %s" % (num, words) - -def abbreviate_age(age): - if age <= 90: - return "%s ago" % plural("second", "seconds", age) - if age < 90*MINUTE: - return "about %s ago" % plural("minute", "minutes", age / MINUTE) - if age < DAY: - return "about %s ago" % plural("hour", "hours", age / HOUR) - if age < 2*WEEK: - return "about %s ago" % plural("day", "days", age / DAY) - if age < 2*MONTH: - return "about %s ago" % plural("week", "weeks", age / WEEK) - return "a long time ago" - - -class BuildLineMixin: - LINE_TIME_FORMAT = "%b %d %H:%M" - - def get_line_values(self, req, build, include_builder=True): - ''' - Collect the data needed for each line display - ''' - builder_name = build.getBuilder().getName() - results = build.getResults() - text = build.getText() - all_got_revision = build.getAllGotRevisions() - css_class = css_classes.get(results, "") - ss_list = build.getSourceStamps() - if ss_list: - repo = ss_list[0].repository - if all_got_revision: - if len(ss_list) == 1: - rev = all_got_revision.get(ss_list[0].codebase, "??") - else: - rev = "multiple rev." - else: - rev = "??" - else: - repo = 'unknown, no information in build' - rev = 'unknown' - - if type(text) == list: - text = " ".join(text) - - values = {'class': css_class, - 'builder_name': builder_name, - 'buildnum': build.getNumber(), - 'results': css_class, - 'text': " ".join(build.getText()), - 'buildurl': path_to_build(req, build), - 'builderurl': path_to_builder(req, build.getBuilder()), - 'rev': rev, - 'rev_repo' : repo, - 'time': time.strftime(self.LINE_TIME_FORMAT, - time.localtime(build.getTimes()[0])), - 'text': text, - 'include_builder': include_builder - } - return values - -def map_branches(branches): - # when the query args say "trunk", present that to things like - # IBuilderStatus.generateFinishedBuilds as None, since that's the - # convention in use. But also include 'trunk', because some VC systems - # refer to it that way. In the long run we should clean this up better, - # maybe with Branch objects or something. - if "trunk" in branches: - return branches + [None] - return branches - - -# jinja utilities - -def createJinjaEnv(revlink=None, changecommentlink=None, - repositories=None, projects=None, jinja_loaders=None): - ''' Create a jinja environment changecommentlink is used to - render HTML in the WebStatus and for mail changes - - @type changecommentlink: C{None}, tuple (2 or 3 strings), dict (string -> 2- or 3-tuple) or callable - @param changecommentlink: see changelinkfilter() - - @type revlink: C{None}, format-string, dict (repository -> format string) or callable - @param revlink: see revlinkfilter() - - @type repositories: C{None} or dict (string -> url) - @param repositories: an (optinal) mapping from repository identifiers - (as given by Change sources) to URLs. Is used to create a link - on every place where a repository is listed in the WebStatus. - - @type projects: C{None} or dict (string -> url) - @param projects: similar to repositories, but for projects. - ''' - - # See http://buildbot.net/trac/ticket/658 - assert not hasattr(sys, "frozen"), 'Frozen config not supported with jinja (yet)' - - all_loaders = [jinja2.FileSystemLoader(os.path.join(os.getcwd(), 'templates'))] - if jinja_loaders: - all_loaders.extend(jinja_loaders) - all_loaders.append(jinja2.PackageLoader('buildbot.status.web', 'templates')) - loader = jinja2.ChoiceLoader(all_loaders) - - env = jinja2.Environment(loader=loader, - extensions=['jinja2.ext.i18n'], - trim_blocks=True, - undefined=AlmostStrictUndefined) - - env.install_null_translations() # needed until we have a proper i18n backend - - env.tests['mapping'] = lambda obj : isinstance(obj, dict) - - env.filters.update(dict( - urlencode = urllib.quote, - email = emailfilter, - user = userfilter, - shortrev = shortrevfilter(revlink, env), - revlink = revlinkfilter(revlink, env), - changecomment = changelinkfilter(changecommentlink), - repolink = dictlinkfilter(repositories), - projectlink = dictlinkfilter(projects) - )) - - return env - -def emailfilter(value): - ''' Escape & obfuscate e-mail addresses - - replacing @ with <span style="display:none> reportedly works well against web-spiders - and the next level is to use rot-13 (or something) and decode in javascript ''' - - user = jinja2.escape(value) - obfuscator = jinja2.Markup('<span style="display:none">ohnoyoudont</span>@') - output = user.replace('@', obfuscator) - return output - - -def userfilter(value): - ''' Hide e-mail address from user name when viewing changes - - We still include the (obfuscated) e-mail so that we can show - it on mouse-over or similar etc - ''' - r = re.compile('(.*) +<(.*)>') - m = r.search(value) - if m: - user = jinja2.escape(m.group(1)) - email = emailfilter(m.group(2)) - return jinja2.Markup('<div class="user">%s<div class="email">%s</div></div>' % (user, email)) - else: - return emailfilter(value) # filter for emails here for safety - -def _revlinkcfg(replace, templates): - '''Helper function that returns suitable macros and functions - for building revision links depending on replacement mechanism -''' - - assert not replace or callable(replace) or isinstance(replace, dict) or \ - isinstance(replace, str) or isinstance(replace, unicode) - - if not replace: - return lambda rev, repo: None - else: - if callable(replace): - return lambda rev, repo: replace(rev, repo) - elif isinstance(replace, dict): # TODO: test for [] instead - def filter(rev, repo): - url = replace.get(repo) - if url: - return url % urllib.quote(rev) - else: - return None - - return filter - else: - return lambda rev, repo: replace % urllib.quote(rev) - - assert False, '_replace has a bad type, but we should never get here' - - -def _revlinkmacros(replace, templates): - '''return macros for use with revision links, depending - on whether revlinks are configured or not''' - - macros = templates.get_template("revmacros.html").module - - if not replace: - id = macros.id - short = macros.shorten - else: - id = macros.id_replace - short = macros.shorten_replace - - return (id, short) - - -def shortrevfilter(replace, templates): - ''' Returns a function which shortens the revisison string - to 12-chars (chosen as this is the Mercurial short-id length) - and add link if replacement string is set. - - (The full id is still visible in HTML, for mouse-over events etc.) - - @param replace: see revlinkfilter() - @param templates: a jinja2 environment - ''' - - url_f = _revlinkcfg(replace, templates) - - def filter(rev, repo): - if not rev: - return u'' - - id_html, short_html = _revlinkmacros(replace, templates) - rev = unicode(rev) - url = url_f(rev, repo) - rev = jinja2.escape(rev) - shortrev = rev[:12] # TODO: customize this depending on vc type - - if shortrev == rev: - if url: - return id_html(rev=rev, url=url) - else: - return rev - else: - if url: - return short_html(short=shortrev, rev=rev, url=url) - else: - return shortrev + '...' - - return filter - - -def revlinkfilter(replace, templates): - ''' Returns a function which adds an url link to a - revision identifiers. - - Takes same params as shortrevfilter() - - @param replace: either a python format string with an %s, - or a dict mapping repositories to format strings, - or a callable taking (revision, repository) arguments - and return an URL (or None, if no URL is available), - or None, in which case revisions do not get decorated - with links - - @param templates: a jinja2 environment - ''' - - url_f = _revlinkcfg(replace, templates) - - def filter(rev, repo): - if not rev: - return u'' - - rev = unicode(rev) - url = url_f(rev, repo) - if url: - id_html, _ = _revlinkmacros(replace, templates) - return id_html(rev=rev, url=url) - else: - return jinja2.escape(rev) - - return filter - - -def changelinkfilter(changelink): - ''' Returns function that does regex search/replace in - comments to add links to bug ids and similar. - - @param changelink: - Either C{None} - or: a tuple (2 or 3 elements) - 1. a regex to match what we look for - 2. an url with regex refs (\g<0>, \1, \2, etc) that becomes the 'href' attribute - 3. (optional) an title string with regex ref regex - or: a dict mapping projects to above tuples - (no links will be added if the project isn't found) - or: a callable taking (changehtml, project) args - (where the changetext is HTML escaped in the - form of a jinja2.Markup instance) and - returning another jinja2.Markup instance with - the same change text plus any HTML tags added to it. - ''' - - assert not changelink or isinstance(changelink, dict) or \ - isinstance(changelink, tuple) or callable(changelink) - - def replace_from_tuple(t): - search, url_replace = t[:2] - if len(t) == 3: - title_replace = t[2] - else: - title_replace = '' - - search_re = re.compile(search) - - def replacement_unmatched(text): - return jinja2.escape(text) - def replacement_matched(mo): - # expand things *after* application of the regular expressions - url = jinja2.escape(mo.expand(url_replace)) - title = jinja2.escape(mo.expand(title_replace)) - body = jinja2.escape(mo.group()) - if title: - return '<a href="%s" title="%s">%s</a>' % (url, title, body) - else: - return '<a href="%s">%s</a>' % (url, body) - - def filter(text, project): - # now, we need to split the string into matched and unmatched portions, - # quoting the unmatched portions directly and quoting the components of - # the 'a' element for the matched portions. We can't use re.split here, - # because the user-supplied patterns may have multiple groups. - html = [] - last_idx = 0 - for mo in search_re.finditer(text): - html.append(replacement_unmatched(text[last_idx:mo.start()])) - html.append(replacement_matched(mo)) - last_idx = mo.end() - html.append(replacement_unmatched(text[last_idx:])) - return jinja2.Markup(''.join(html)) - - return filter - - if not changelink: - return lambda text, project: jinja2.escape(text) - - elif isinstance(changelink, dict): - def dict_filter(text, project): - # TODO: Optimize and cache return value from replace_from_tuple so - # we only compile regex once per project, not per view - - t = changelink.get(project) - if t: - return replace_from_tuple(t)(text, project) - else: - return cgi.escape(text) - - return dict_filter - - elif isinstance(changelink, tuple): - return replace_from_tuple(changelink) - - elif callable(changelink): - def callable_filter(text, project): - text = jinja2.escape(text) - return changelink(text, project) - - return callable_filter - - assert False, 'changelink has unsupported type, but that is checked before' - - -def dictlinkfilter(links): - '''A filter that encloses the given value in a link tag - given that the value exists in the dictionary''' - - assert not links or callable(links) or isinstance(links, dict) - - if not links: - return jinja2.escape - - def filter(key): - if callable(links): - url = links(key) - else: - url = links.get(key) - - safe_key = jinja2.escape(key) - - if url: - return jinja2.Markup(r'<a href="%s">%s</a>' % (url, safe_key)) - else: - return safe_key - - return filter - -class AlmostStrictUndefined(jinja2.StrictUndefined): - ''' An undefined that allows boolean testing but - fails properly on every other use. - - Much better than the default Undefined, but not - fully as strict as StrictUndefined ''' - def __nonzero__(self): - return False - -_charsetRe = re.compile('charset=([^;]*)', re.I) -def getRequestCharset(req): - """Get the charset for an x-www-form-urlencoded request""" - # per http://stackoverflow.com/questions/708915/detecting-the-character-encoding-of-an-http-post-request - hdr = req.getHeader('Content-Type') - if hdr: - mo = _charsetRe.search(hdr) - if mo: - return mo.group(1).strip() - return 'utf-8' # reasonable guess, works for ascii diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py deleted file mode 100644 index 9fe5e7fc..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/baseweb.py +++ /dev/null @@ -1,607 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -import os, weakref - -from zope.interface import implements -from twisted.python import log -from twisted.application import strports, service -from twisted.internet import defer -from twisted.web import server, distrib, static -from twisted.spread import pb -from twisted.web.util import Redirect -from buildbot import config -from buildbot.interfaces import IStatusReceiver -from buildbot.status.web.base import StaticFile, createJinjaEnv -from buildbot.status.web.feeds import Rss20StatusResource, \ - Atom10StatusResource -from buildbot.status.web.waterfall import WaterfallStatusResource -from buildbot.status.web.console import ConsoleStatusResource -from buildbot.status.web.olpb import OneLinePerBuild -from buildbot.status.web.grid import GridStatusResource -from buildbot.status.web.grid import TransposedGridStatusResource -from buildbot.status.web.changes import ChangesResource -from buildbot.status.web.builder import BuildersResource -from buildbot.status.web.buildstatus import BuildStatusStatusResource -from buildbot.status.web.slaves import BuildSlavesResource -from buildbot.status.web.status_json import JsonStatusResource -from buildbot.status.web.about import AboutBuildbot -from buildbot.status.web.authz import Authz -from buildbot.status.web.auth import AuthFailResource,AuthzFailResource, LoginResource, LogoutResource -from buildbot.status.web.root import RootPage -from buildbot.status.web.users import UsersResource -from buildbot.status.web.change_hook import ChangeHookResource -from twisted.cred.portal import IRealm, Portal -from twisted.cred import strcred -from twisted.cred.checkers import ICredentialsChecker -from twisted.cred.credentials import IUsernamePassword -from twisted.web import resource, guard - -# this class contains the WebStatus class. Basic utilities are in base.py, -# and specific pages are each in their own module. - -class WebStatus(service.MultiService): - implements(IStatusReceiver) - # TODO: IStatusReceiver is really about things which subscribe to hear - # about buildbot events. We need a different interface (perhaps a parent - # of IStatusReceiver) for status targets that don't subscribe, like the - # WebStatus class. buildbot.master.BuildMaster.loadConfig:737 asserts - # that everything in c['status'] provides IStatusReceiver, but really it - # should check that they provide IStatusTarget instead. - - """ - The webserver provided by this class has the following resources: - - /waterfall : the big time-oriented 'waterfall' display, with links - to individual changes, builders, builds, steps, and logs. - A number of query-arguments can be added to influence - the display. - /rss : a rss feed summarizing all failed builds. The same - query-arguments used by 'waterfall' can be added to - influence the feed output. - /atom : an atom feed summarizing all failed builds. The same - query-arguments used by 'waterfall' can be added to - influence the feed output. - /grid : another summary display that shows a grid of builds, with - sourcestamps on the x axis, and builders on the y. Query - arguments similar to those for the waterfall can be added. - /tgrid : similar to the grid display, but the commits are down the - left side, and the build hosts are across the top. - /builders/BUILDERNAME: a page summarizing the builder. This includes - references to the Schedulers that feed it, - any builds currently in the queue, which - buildslaves are designated or attached, and a - summary of the build process it uses. - /builders/BUILDERNAME/builds/NUM: a page describing a single Build - /builders/BUILDERNAME/builds/NUM/steps/STEPNAME: describes a single step - /builders/BUILDERNAME/builds/NUM/steps/STEPNAME/logs/LOGNAME: a StatusLog - /builders/_all/{force,stop}: force a build/stop building on all builders. - /buildstatus?builder=...&number=...: an embedded iframe for the console - /changes : summarize all ChangeSources - /changes/CHANGENUM: a page describing a single Change - /buildslaves : list all BuildSlaves - /buildslaves/SLAVENAME : describe a single BuildSlave - /one_line_per_build : summarize the last few builds, one line each - /one_line_per_build/BUILDERNAME : same, but only for a single builder - /about : describe this buildmaster (Buildbot and support library versions) - /change_hook[/DIALECT] : accepts changes from external sources, optionally - choosing the dialect that will be permitted - (i.e. github format, etc..) - - and more! see the manual. - - - All URLs for pages which are not defined here are used to look - for files in PUBLIC_HTML, which defaults to BASEDIR/public_html. - This means that /robots.txt or /favicon.ico can be placed in - that directory - - This webserver uses the jinja2 template system to generate the web pages - (see http://jinja.pocoo.org/2/) and by default loads pages from the - buildbot.status.web.templates package. Any file here can be overridden by placing - a corresponding file in the master's 'templates' directory. - - The main customization points are layout.html which loads style sheet - (css) and provides header and footer content, and root.html, which - generates the root page. - - All of the resources provided by this service use relative URLs to reach - each other. The only absolute links are the c['titleURL'] links at the - top and bottom of the page, and the buildbot home-page link at the - bottom. - - Buildbot uses some generic classes to identify the type of object, and - some more specific classes for the various kinds of those types. It does - this by specifying both in the class attributes where applicable, - separated by a space. It is important that in your CSS you declare the - more generic class styles above the more specific ones. For example, - first define a style for .Event, and below that for .SUCCESS - - The following CSS class names are used: - - Activity, Event, BuildStep, LastBuild: general classes - - waiting, interlocked, building, offline, idle: Activity states - - start, running, success, failure, warnings, skipped, exception: - LastBuild and BuildStep states - - Change: box with change - - Builder: box for builder name (at top) - - Project - - Time - - """ - - # we are not a ComparableMixin, and therefore the webserver will be - # rebuilt every time we reconfig. This is because WebStatus.putChild() - # makes it too difficult to tell whether two instances are the same or - # not (we'd have to do a recursive traversal of all children to discover - # all the changes). - - def __init__(self, http_port=None, distrib_port=None, allowForce=None, - public_html="public_html", site=None, numbuilds=20, - num_events=200, num_events_max=None, auth=None, - order_console_by_time=False, changecommentlink=None, - revlink=None, projects=None, repositories=None, - authz=None, logRotateLength=None, maxRotatedFiles=None, - change_hook_dialects = {}, provide_feeds=None, jinja_loaders=None, - change_hook_auth=None): - """Run a web server that provides Buildbot status. - - @type http_port: int or L{twisted.application.strports} string - @param http_port: a strports specification describing which port the - buildbot should use for its web server, with the - Waterfall display as the root page. For backwards - compatibility this can also be an int. Use - 'tcp:8000' to listen on that port, or - 'tcp:12345:interface=127.0.0.1' if you only want - local processes to connect to it (perhaps because - you are using an HTTP reverse proxy to make the - buildbot available to the outside world, and do not - want to make the raw port visible). - - @type distrib_port: int or L{twisted.application.strports} string - @param distrib_port: Use this if you want to publish the Waterfall - page using web.distrib instead. The most common - case is to provide a string that is an absolute - pathname to the unix socket on which the - publisher should listen - (C{os.path.expanduser(~/.twistd-web-pb)} will - match the default settings of a standard - twisted.web 'personal web server'). Another - possibility is to pass an integer, which means - the publisher should listen on a TCP socket, - allowing the web server to be on a different - machine entirely. Both forms are provided for - backwards compatibility; the preferred form is a - strports specification like - 'unix:/home/buildbot/.twistd-web-pb'. Providing - a non-absolute pathname will probably confuse - the strports parser. - - @param allowForce: deprecated; use authz instead - @param auth: deprecated; use with authz - - @param authz: a buildbot.status.web.authz.Authz instance giving the authorization - parameters for this view - - @param public_html: the path to the public_html directory for this display, - either absolute or relative to the basedir. The default - is 'public_html', which selects BASEDIR/public_html. - - @type site: None or L{twisted.web.server.Site} - @param site: Use this if you want to define your own object instead of - using the default.` - - @type numbuilds: int - @param numbuilds: Default number of entries in lists at the /one_line_per_build - and /builders/FOO URLs. This default can be overriden both programatically --- - by passing the equally named argument to constructors of OneLinePerBuildOneBuilder - and OneLinePerBuild --- and via the UI, by tacking ?numbuilds=xy onto the URL. - - @type num_events: int - @param num_events: Default number of events to show in the waterfall. - - @type num_events_max: int - @param num_events_max: The maximum number of events that are allowed to be - shown in the waterfall. The default value of C{None} will disable this - check - - @type auth: a L{status.web.auth.IAuth} or C{None} - @param auth: an object that performs authentication to restrict access - to the C{allowForce} features. Ignored if C{allowForce} - is not C{True}. If C{auth} is C{None}, people can force or - stop builds without auth. - - @type order_console_by_time: bool - @param order_console_by_time: Whether to order changes (commits) in the console - view according to the time they were created (for VCS like Git) or - according to their integer revision numbers (for VCS like SVN). - - @type changecommentlink: callable, dict, tuple (2 or 3 strings) or C{None} - @param changecommentlink: adds links to ticket/bug ids in change comments, - see buildbot.status.web.base.changecommentlink for details - - @type revlink: callable, dict, string or C{None} - @param revlink: decorations revision ids with links to a web-view, - see buildbot.status.web.base.revlink for details - - @type projects: callable, dict or c{None} - @param projects: maps project identifiers to URLs, so that any project listed - is automatically decorated with a link to it's front page. - see buildbot.status.web.base.dictlink for details - - @type repositories: callable, dict or c{None} - @param repositories: maps repository identifiers to URLs, so that any project listed - is automatically decorated with a link to it's web view. - see buildbot.status.web.base.dictlink for details - - @type logRotateLength: None or int - @param logRotateLength: file size at which the http.log is rotated/reset. - If not set, the value set in the buildbot.tac will be used, - falling back to the BuildMaster's default value (1 Mb). - - @type maxRotatedFiles: None or int - @param maxRotatedFiles: number of old http.log files to keep during log rotation. - If not set, the value set in the buildbot.tac will be used, - falling back to the BuildMaster's default value (10 files). - - @type change_hook_dialects: None or dict - @param change_hook_dialects: If empty, disables change_hook support, otherwise - whitelists valid dialects. In the format of - {"dialect1": "Option1", "dialect2", None} - Where the values are options that will be passed - to the dialect - - To enable the DEFAULT handler, use a key of DEFAULT - - - - - @type provide_feeds: None or list - @param provide_feeds: If empty, provides atom, json, and rss feeds. - Otherwise, a dictionary of strings of - the type of feeds provided. Current - possibilities are "atom", "json", and "rss" - - @type jinja_loaders: None or list - @param jinja_loaders: If not empty, a list of additional Jinja2 loader - objects to search for templates. - """ - - service.MultiService.__init__(self) - if type(http_port) is int: - http_port = "tcp:%d" % http_port - self.http_port = http_port - if distrib_port is not None: - if type(distrib_port) is int: - distrib_port = "tcp:%d" % distrib_port - if distrib_port[0] in "/~.": # pathnames - distrib_port = "unix:%s" % distrib_port - self.distrib_port = distrib_port - self.num_events = num_events - if num_events_max: - if num_events_max < num_events: - config.error( - "num_events_max must be greater than num_events") - self.num_events_max = num_events_max - self.public_html = public_html - - # make up an authz if allowForce was given - if authz: - if allowForce is not None: - config.error( - "cannot use both allowForce and authz parameters") - if auth: - config.error( - "cannot use both auth and authz parameters (pass " + - "auth as an Authz parameter)") - else: - # invent an authz - if allowForce and auth: - authz = Authz(auth=auth, default_action="auth") - elif allowForce: - authz = Authz(default_action=True) - else: - if auth: - log.msg("Warning: Ignoring authentication. Search for 'authorization'" - " in the manual") - authz = Authz() # no authorization for anything - - self.authz = authz - - # check for correctness of HTTP auth parameters - if change_hook_auth is not None: - self.change_hook_auth = [] - for checker in change_hook_auth: - if isinstance(checker, str): - try: - checker = strcred.makeChecker(checker) - except Exception, error: - config.error("Invalid change_hook checker description: %s" % (error,)) - continue - elif not ICredentialsChecker.providedBy(checker): - config.error("change_hook checker doesn't provide ICredentialChecker: %r" % (checker,)) - continue - - if IUsernamePassword not in checker.credentialInterfaces: - config.error("change_hook checker doesn't support IUsernamePassword: %r" % (checker,)) - continue - - self.change_hook_auth.append(checker) - else: - self.change_hook_auth = None - - self.orderConsoleByTime = order_console_by_time - - # If we were given a site object, go ahead and use it. (if not, we add one later) - self.site = site - - # keep track of our child services - self.http_svc = None - self.distrib_svc = None - - # store the log settings until we create the site object - self.logRotateLength = logRotateLength - self.maxRotatedFiles = maxRotatedFiles - - # create the web site page structure - self.childrenToBeAdded = {} - self.setupUsualPages(numbuilds=numbuilds, num_events=num_events, - num_events_max=num_events_max) - - self.revlink = revlink - self.changecommentlink = changecommentlink - self.repositories = repositories - self.projects = projects - - # keep track of cached connections so we can break them when we shut - # down. See ticket #102 for more details. - self.channels = weakref.WeakKeyDictionary() - - # do we want to allow change_hook - self.change_hook_dialects = {} - if change_hook_dialects: - self.change_hook_dialects = change_hook_dialects - resource_obj = ChangeHookResource(dialects=self.change_hook_dialects) - if self.change_hook_auth is not None: - resource_obj = self.setupProtectedResource( - resource_obj, self.change_hook_auth) - self.putChild("change_hook", resource_obj) - - # Set default feeds - if provide_feeds is None: - self.provide_feeds = ["atom", "json", "rss"] - else: - self.provide_feeds = provide_feeds - - self.jinja_loaders = jinja_loaders - - def setupProtectedResource(self, resource_obj, checkers): - class SimpleRealm(object): - """ - A realm which gives out L{ChangeHookResource} instances for authenticated - users. - """ - implements(IRealm) - - def requestAvatar(self, avatarId, mind, *interfaces): - if resource.IResource in interfaces: - return (resource.IResource, resource_obj, lambda: None) - raise NotImplementedError() - - portal = Portal(SimpleRealm(), checkers) - credentialFactory = guard.BasicCredentialFactory('Protected area') - wrapper = guard.HTTPAuthSessionWrapper(portal, [credentialFactory]) - return wrapper - - def setupUsualPages(self, numbuilds, num_events, num_events_max): - #self.putChild("", IndexOrWaterfallRedirection()) - self.putChild("waterfall", WaterfallStatusResource(num_events=num_events, - num_events_max=num_events_max)) - self.putChild("grid", GridStatusResource()) - self.putChild("console", ConsoleStatusResource( - orderByTime=self.orderConsoleByTime)) - self.putChild("tgrid", TransposedGridStatusResource()) - self.putChild("builders", BuildersResource(numbuilds=numbuilds)) # has builds/steps/logs - self.putChild("one_box_per_builder", Redirect("builders")) - self.putChild("changes", ChangesResource()) - self.putChild("buildslaves", BuildSlavesResource()) - self.putChild("buildstatus", BuildStatusStatusResource()) - self.putChild("one_line_per_build", - OneLinePerBuild(numbuilds=numbuilds)) - self.putChild("about", AboutBuildbot()) - self.putChild("authfail", AuthFailResource()) - self.putChild("authzfail", AuthzFailResource()) - self.putChild("users", UsersResource()) - self.putChild("login", LoginResource()) - self.putChild("logout", LogoutResource()) - - def __repr__(self): - if self.http_port is None: - return "<WebStatus on path %s at %s>" % (self.distrib_port, - hex(id(self))) - if self.distrib_port is None: - return "<WebStatus on port %s at %s>" % (self.http_port, - hex(id(self))) - return ("<WebStatus on port %s and path %s at %s>" % - (self.http_port, self.distrib_port, hex(id(self)))) - - def setServiceParent(self, parent): - # this class keeps a *separate* link to the buildmaster, rather than - # just using self.parent, so that when we are "disowned" (and thus - # parent=None), any remaining HTTP clients of this WebStatus will still - # be able to get reasonable results. - self.master = parent.master - - # set master in IAuth instance - if self.authz.auth: - self.authz.auth.master = self.master - - def either(a,b): # a if a else b for py2.4 - if a: - return a - else: - return b - - rotateLength = either(self.logRotateLength, self.master.log_rotation.rotateLength) - maxRotatedFiles = either(self.maxRotatedFiles, self.master.log_rotation.maxRotatedFiles) - - # Set up the jinja templating engine. - if self.revlink: - revlink = self.revlink - else: - revlink = self.master.config.revlink - self.templates = createJinjaEnv(revlink, self.changecommentlink, - self.repositories, self.projects, self.jinja_loaders) - - if not self.site: - - class RotateLogSite(server.Site): - def _openLogFile(self, path): - try: - from twisted.python.logfile import LogFile - log.msg("Setting up http.log rotating %s files of %s bytes each" % - (maxRotatedFiles, rotateLength)) - if hasattr(LogFile, "fromFullPath"): # not present in Twisted-2.5.0 - return LogFile.fromFullPath(path, rotateLength=rotateLength, maxRotatedFiles=maxRotatedFiles) - else: - log.msg("WebStatus: rotated http logs are not supported on this version of Twisted") - except ImportError, e: - log.msg("WebStatus: Unable to set up rotating http.log: %s" % e) - - # if all else fails, just call the parent method - return server.Site._openLogFile(self, path) - - # this will be replaced once we've been attached to a parent (and - # thus have a basedir and can reference BASEDIR) - root = static.Data("placeholder", "text/plain") - httplog = os.path.abspath(os.path.join(self.master.basedir, "http.log")) - self.site = RotateLogSite(root, logPath=httplog) - - # the following items are accessed by HtmlResource when it renders - # each page. - self.site.buildbot_service = self - - if self.http_port is not None: - self.http_svc = s = strports.service(self.http_port, self.site) - s.setServiceParent(self) - if self.distrib_port is not None: - f = pb.PBServerFactory(distrib.ResourcePublisher(self.site)) - self.distrib_svc = s = strports.service(self.distrib_port, f) - s.setServiceParent(self) - - self.setupSite() - - service.MultiService.setServiceParent(self, parent) - - def setupSite(self): - # this is responsible for creating the root resource. It isn't done - # at __init__ time because we need to reference the parent's basedir. - htmldir = os.path.abspath(os.path.join(self.master.basedir, self.public_html)) - if os.path.isdir(htmldir): - log.msg("WebStatus using (%s)" % htmldir) - else: - log.msg("WebStatus: warning: %s is missing. Do you need to run" - " 'buildbot upgrade-master' on this buildmaster?" % htmldir) - # all static pages will get a 404 until upgrade-master is used to - # populate this directory. Create the directory, though, since - # otherwise we get internal server errors instead of 404s. - os.mkdir(htmldir) - - root = StaticFile(htmldir) - root_page = RootPage() - root.putChild("", root_page) - root.putChild("shutdown", root_page) - root.putChild("cancel_shutdown", root_page) - - for name, child_resource in self.childrenToBeAdded.iteritems(): - root.putChild(name, child_resource) - - status = self.getStatus() - if "rss" in self.provide_feeds: - root.putChild("rss", Rss20StatusResource(status)) - if "atom" in self.provide_feeds: - root.putChild("atom", Atom10StatusResource(status)) - if "json" in self.provide_feeds: - root.putChild("json", JsonStatusResource(status)) - - self.site.resource = root - - def putChild(self, name, child_resource): - """This behaves a lot like root.putChild() . """ - self.childrenToBeAdded[name] = child_resource - - def registerChannel(self, channel): - self.channels[channel] = 1 # weakrefs - - @defer.inlineCallbacks - def stopService(self): - for channel in self.channels: - try: - channel.transport.loseConnection() - except: - log.msg("WebStatus.stopService: error while disconnecting" - " leftover clients") - log.err() - yield service.MultiService.stopService(self) - - # having shut them down, now remove our child services so they don't - # start up again if we're re-started - if self.http_svc: - yield self.http_svc.disownServiceParent() - self.http_svc = None - if self.distrib_svc: - yield self.distrib_svc.disownServiceParent() - self.distrib_svc = None - - def getStatus(self): - return self.master.getStatus() - - def getChangeSvc(self): - return self.master.change_svc - - def getPortnum(self): - # this is for the benefit of unit tests - s = list(self)[0] - return s._port.getHost().port - - # What happened to getControl?! - # - # instead of passing control objects all over the place in the web - # code, at the few places where a control instance is required we - # find the requisite object manually, starting at the buildmaster. - # This is in preparation for removal of the IControl hierarchy - # entirely. - - def checkConfig(self, otherStatusReceivers): - duplicate_webstatus=0 - for osr in otherStatusReceivers: - if isinstance(osr,WebStatus): - if osr is self: - continue - # compare against myself and complain if the settings conflict - if self.http_port == osr.http_port: - if duplicate_webstatus == 0: - duplicate_webstatus = 2 - else: - duplicate_webstatus += 1 - - if duplicate_webstatus: - config.error( - "%d Webstatus objects have same port: %s" - % (duplicate_webstatus, self.http_port), - ) - -# resources can get access to the IStatus by calling -# request.site.buildbot_service.getStatus() diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py deleted file mode 100644 index 1cf7f92f..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/build.py +++ /dev/null @@ -1,332 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from twisted.web import html -from twisted.internet import defer, reactor -from twisted.web.util import Redirect, DeferredResource - -import urllib, time -from twisted.python import log -from buildbot.status.web.base import HtmlResource, \ - css_classes, path_to_build, path_to_builder, path_to_slave, \ - getAndCheckProperties, ActionResource, path_to_authzfail, \ - getRequestCharset -from buildbot.schedulers.forcesched import ForceScheduler, TextParameter -from buildbot.status.web.step import StepsResource -from buildbot.status.web.tests import TestsResource -from buildbot import util, interfaces - -class ForceBuildActionResource(ActionResource): - - def __init__(self, build_status, builder): - self.build_status = build_status - self.builder = builder - self.action = "forceBuild" - - @defer.inlineCallbacks - def performAction(self, req): - url = None - authz = self.getAuthz(req) - res = yield authz.actionAllowed(self.action, req, self.builder) - - if not res: - url = path_to_authzfail(req) - else: - # get a control object - c = interfaces.IControl(self.getBuildmaster(req)) - bc = c.getBuilder(self.builder.getName()) - - b = self.build_status - builder_name = self.builder.getName() - log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber())) - name =authz.getUsernameFull(req) - comments = req.args.get("comments", ["<no reason specified>"])[0] - comments.decode(getRequestCharset(req)) - reason = ("The web-page 'rebuild' button was pressed by " - "'%s': %s\n" % (name, comments)) - msg = "" - extraProperties = getAndCheckProperties(req) - if not bc or not b.isFinished() or extraProperties is None: - msg = "could not rebuild: " - if b.isFinished(): - msg += "build still not finished " - if bc: - msg += "could not get builder control" - else: - tup = yield bc.rebuildBuild(b, reason, extraProperties) - # rebuildBuild returns None on error (?!) - if not tup: - msg = "rebuilding a build failed "+ str(tup) - # we're at - # http://localhost:8080/builders/NAME/builds/5/rebuild?[args] - # Where should we send them? - # - # Ideally it would be to the per-build page that they just started, - # but we don't know the build number for it yet (besides, it might - # have to wait for a current build to finish). The next-most - # preferred place is somewhere that the user can see tangible - # evidence of their build starting (or to see the reason that it - # didn't start). This should be the Builder page. - - url = path_to_builder(req, self.builder), msg - defer.returnValue(url) - - -class StopBuildActionResource(ActionResource): - - def __init__(self, build_status): - self.build_status = build_status - self.action = "stopBuild" - - @defer.inlineCallbacks - def performAction(self, req): - authz = self.getAuthz(req) - res = yield authz.actionAllowed(self.action, req, self.build_status) - - if not res: - defer.returnValue(path_to_authzfail(req)) - return - - b = self.build_status - log.msg("web stopBuild of build %s:%s" % \ - (b.getBuilder().getName(), b.getNumber())) - name = authz.getUsernameFull(req) - comments = req.args.get("comments", ["<no reason specified>"])[0] - comments.decode(getRequestCharset(req)) - # html-quote both the username and comments, just to be safe - reason = ("The web-page 'stop build' button was pressed by " - "'%s': %s\n" % (html.escape(name), html.escape(comments))) - - c = interfaces.IControl(self.getBuildmaster(req)) - bldrc = c.getBuilder(self.build_status.getBuilder().getName()) - if bldrc: - bldc = bldrc.getBuild(self.build_status.getNumber()) - if bldc: - bldc.stopBuild(reason) - - defer.returnValue(path_to_builder(req, self.build_status.getBuilder())) - -# /builders/$builder/builds/$buildnum -class StatusResourceBuild(HtmlResource): - addSlash = True - - def __init__(self, build_status): - HtmlResource.__init__(self) - self.build_status = build_status - - def getPageTitle(self, request): - return ("Buildbot: %s Build #%d" % - (self.build_status.getBuilder().getName(), - self.build_status.getNumber())) - - def content(self, req, cxt): - b = self.build_status - status = self.getStatus(req) - req.setHeader('Cache-Control', 'no-cache') - - cxt['b'] = b - cxt['path_to_builder'] = path_to_builder(req, b.getBuilder()) - - if not b.isFinished(): - step = b.getCurrentStep() - if not step: - cxt['current_step'] = "[waiting for Lock]" - else: - if step.isWaitingForLocks(): - cxt['current_step'] = "%s [waiting for Lock]" % step.getName() - else: - cxt['current_step'] = step.getName() - when = b.getETA() - if when is not None: - cxt['when'] = util.formatInterval(when) - cxt['when_time'] = time.strftime("%H:%M:%S", - time.localtime(time.time() + when)) - - else: - cxt['result_css'] = css_classes[b.getResults()] - if b.getTestResults(): - cxt['tests_link'] = req.childLink("tests") - - ssList = b.getSourceStamps() - sourcestamps = cxt['sourcestamps'] = ssList - - all_got_revisions = b.getAllGotRevisions() - cxt['got_revisions'] = all_got_revisions - - try: - cxt['slave_url'] = path_to_slave(req, status.getSlave(b.getSlavename())) - except KeyError: - pass - - cxt['steps'] = [] - - for s in b.getSteps(): - step = {'name': s.getName() } - - if s.isFinished(): - if s.isHidden(): - continue - - step['css_class'] = css_classes[s.getResults()[0]] - (start, end) = s.getTimes() - step['time_to_run'] = util.formatInterval(end - start) - elif s.isStarted(): - if s.isWaitingForLocks(): - step['css_class'] = "waiting" - step['time_to_run'] = "waiting for locks" - else: - start = s.getTimes()[0] - step['css_class'] = "running" - step['time_to_run'] = "running %s" % (util.formatInterval(util.now() - start)) - else: - step['css_class'] = "not_started" - step['time_to_run'] = "" - - cxt['steps'].append(step) - - step['link'] = req.childLink("steps/%s" % - urllib.quote(s.getName(), safe='')) - step['text'] = " ".join(s.getText()) - step['urls'] = map(lambda x:dict(url=x[1],logname=x[0]), s.getURLs().items()) - - step['logs']= [] - for l in s.getLogs(): - logname = l.getName() - step['logs'].append({ 'link': req.childLink("steps/%s/logs/%s" % - (urllib.quote(s.getName(), safe=''), - urllib.quote(logname, safe=''))), - 'name': logname }) - - scheduler = b.getProperty("scheduler", None) - parameters = {} - master = self.getBuildmaster(req) - for sch in master.allSchedulers(): - if isinstance(sch, ForceScheduler) and scheduler == sch.name: - for p in sch.all_fields: - parameters[p.name] = p - - ps = cxt['properties'] = [] - for name, value, source in b.getProperties().asList(): - if not isinstance(value, dict): - cxt_value = unicode(value) - else: - cxt_value = value - p = { 'name': name, 'value': cxt_value, 'source': source} - if len(cxt_value) > 500: - p['short_value'] = cxt_value[:500] - if name in parameters: - param = parameters[name] - if isinstance(param, TextParameter): - p['text'] = param.value_to_text(value) - p['cols'] = param.cols - p['rows'] = param.rows - p['label'] = param.label - ps.append(p) - - - cxt['responsible_users'] = list(b.getResponsibleUsers()) - - (start, end) = b.getTimes() - cxt['start'] = time.ctime(start) - if end: - cxt['end'] = time.ctime(end) - cxt['elapsed'] = util.formatInterval(end - start) - else: - now = util.now() - cxt['elapsed'] = util.formatInterval(now - start) - - exactly = True - has_changes = False - for ss in sourcestamps: - exactly = exactly and (ss.revision is not None) - has_changes = has_changes or ss.changes - cxt['exactly'] = (exactly) or b.getChanges() - cxt['has_changes'] = has_changes - cxt['build_url'] = path_to_build(req, b) - cxt['authz'] = self.getAuthz(req) - - template = req.site.buildbot_service.templates.get_template("build.html") - return template.render(**cxt) - - def stop(self, req, auth_ok=False): - # check if this is allowed - if not auth_ok: - return StopBuildActionResource(self.build_status) - - b = self.build_status - log.msg("web stopBuild of build %s:%s" % \ - (b.getBuilder().getName(), b.getNumber())) - - name = self.getAuthz(req).getUsernameFull(req) - comments = req.args.get("comments", ["<no reason specified>"])[0] - comments.decode(getRequestCharset(req)) - # html-quote both the username and comments, just to be safe - reason = ("The web-page 'stop build' button was pressed by " - "'%s': %s\n" % (html.escape(name), html.escape(comments))) - - c = interfaces.IControl(self.getBuildmaster(req)) - bldrc = c.getBuilder(self.build_status.getBuilder().getName()) - if bldrc: - bldc = bldrc.getBuild(self.build_status.getNumber()) - if bldc: - bldc.stopBuild(reason) - - # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and - # we want to go to: http://localhost:8080/svn-hello - r = Redirect(path_to_builder(req, self.build_status.getBuilder())) - d = defer.Deferred() - reactor.callLater(1, d.callback, r) - return DeferredResource(d) - - def rebuild(self, req): - return ForceBuildActionResource(self.build_status, - self.build_status.getBuilder()) - - def getChild(self, path, req): - if path == "stop": - return self.stop(req) - if path == "rebuild": - return self.rebuild(req) - if path == "steps": - return StepsResource(self.build_status) - if path == "tests": - return TestsResource(self.build_status) - - return HtmlResource.getChild(self, path, req) - -# /builders/$builder/builds -class BuildsResource(HtmlResource): - addSlash = True - - def __init__(self, builder_status): - HtmlResource.__init__(self) - self.builder_status = builder_status - - def content(self, req, cxt): - return "subpages shows data for each build" - - def getChild(self, path, req): - try: - num = int(path) - except ValueError: - num = None - if num is not None: - build_status = self.builder_status.getBuild(num) - if build_status: - return StatusResourceBuild(build_status) - - return HtmlResource.getChild(self, path, req) - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py deleted file mode 100644 index b4d15233..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/builder.py +++ /dev/null @@ -1,632 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from twisted.web import html -import urllib, time -from twisted.python import log -from twisted.internet import defer -from buildbot import interfaces -from buildbot.status.web.base import HtmlResource, BuildLineMixin, \ - path_to_build, path_to_slave, path_to_builder, path_to_change, \ - path_to_root, ICurrentBox, build_get_class, \ - map_branches, path_to_authzfail, ActionResource, \ - getRequestCharset -from buildbot.schedulers.forcesched import ForceScheduler -from buildbot.schedulers.forcesched import ValidationError -from buildbot.status.web.build import BuildsResource, StatusResourceBuild -from buildbot import util -import collections - -class ForceAction(ActionResource): - @defer.inlineCallbacks - def force(self, req, builderNames): - master = self.getBuildmaster(req) - owner = self.getAuthz(req).getUsernameFull(req) - schedulername = req.args.get("forcescheduler", ["<unknown>"])[0] - if schedulername == "<unknown>": - defer.returnValue((path_to_builder(req, self.builder_status), - "forcescheduler arg not found")) - return - - args = {} - # decode all of the args - encoding = getRequestCharset(req) - for name, argl in req.args.iteritems(): - if name == "checkbox": - # damn html's ungeneric checkbox implementation... - for cb in argl: - args[cb.decode(encoding)] = True - else: - args[name] = [ arg.decode(encoding) for arg in argl ] - - for sch in master.allSchedulers(): - if schedulername == sch.name: - try: - yield sch.force(owner, builderNames, **args) - msg = "" - except ValidationError, e: - msg = html.escape(e.message.encode('ascii','ignore')) - break - - # send the user back to the builder page - defer.returnValue(msg) - - -class ForceAllBuildsActionResource(ForceAction): - - def __init__(self, status, selectedOrAll): - self.status = status - self.selectedOrAll = selectedOrAll - self.action = "forceAllBuilds" - - @defer.inlineCallbacks - def performAction(self, req): - authz = self.getAuthz(req) - res = yield authz.actionAllowed('forceAllBuilds', req) - - if not res: - defer.returnValue(path_to_authzfail(req)) - return - - if self.selectedOrAll == 'all': - builderNames = None - elif self.selectedOrAll == 'selected': - builderNames = [b for b in req.args.get("selected", []) if b] - - msg = yield self.force(req, builderNames) - - # back to the welcome page - defer.returnValue((path_to_root(req) + "builders", msg)) - -class StopAllBuildsActionResource(ActionResource): - - def __init__(self, status, selectedOrAll): - self.status = status - self.selectedOrAll = selectedOrAll - self.action = "stopAllBuilds" - - @defer.inlineCallbacks - def performAction(self, req): - authz = self.getAuthz(req) - res = yield authz.actionAllowed('stopAllBuilds', req) - if not res: - defer.returnValue(path_to_authzfail(req)) - return - - builders = None - if self.selectedOrAll == 'all': - builders = self.status.getBuilderNames() - elif self.selectedOrAll == 'selected': - builders = [b for b in req.args.get("selected", []) if b] - - for bname in builders: - builder_status = self.status.getBuilder(bname) - (state, current_builds) = builder_status.getState() - if state != "building": - continue - for b in current_builds: - build_status = builder_status.getBuild(b.number) - if not build_status: - continue - build = StatusResourceBuild(build_status) - build.stop(req, auth_ok=True) - - # go back to the welcome page - defer.returnValue(path_to_root(req)) - - -class CancelAllPendingBuildsActionResource(ActionResource): - - def __init__(self, status, selectedOrAll): - self.status = status - self.selectedOrAll = selectedOrAll - self.action = 'cancelAllPendingBuilds' - - @defer.inlineCallbacks - def performAction(self, req): - authz = self.getAuthz(req) - res = yield authz.actionAllowed('cancelAllPendingBuilds', req) - if not res: - defer.returnValue(path_to_authzfail(req)) - return - - builders = None - if self.selectedOrAll == 'all': - builders = self.status.getBuilderNames() - elif self.selectedOrAll == 'selected': - builders = [b for b in req.args.get("selected", []) if b] - - c = interfaces.IControl(self.getBuildmaster(req)) - for bname in builders: - authz = self.getAuthz(req) - builder_control = c.getBuilder(bname) - - brcontrols = yield builder_control.getPendingBuildRequestControls() - - for build_req in brcontrols: - log.msg("Cancelling %s" % build_req) - build_req.cancel() - - # go back to the welcome page - defer.returnValue(path_to_root(req)) - - -class PingBuilderActionResource(ActionResource): - - def __init__(self, builder_status): - self.builder_status = builder_status - self.action = "pingBuilder" - - @defer.inlineCallbacks - def performAction(self, req): - log.msg("web ping of builder '%s'" % self.builder_status.getName()) - res = yield self.getAuthz(req).actionAllowed('pingBuilder', req, - self.builder_status) - if not res: - log.msg("..but not authorized") - defer.returnValue(path_to_authzfail(req)) - return - - c = interfaces.IControl(self.getBuildmaster(req)) - bc = c.getBuilder(self.builder_status.getName()) - bc.ping() - # send the user back to the builder page - defer.returnValue(path_to_builder(req, self.builder_status)) - -class ForceBuildActionResource(ForceAction): - - def __init__(self, builder_status): - self.builder_status = builder_status - self.action = "forceBuild" - - @defer.inlineCallbacks - def performAction(self, req): - # check if this is allowed - res = yield self.getAuthz(req).actionAllowed(self.action, req, - self.builder_status) - if not res: - log.msg("..but not authorized") - defer.returnValue(path_to_authzfail(req)) - return - - builderName = self.builder_status.getName() - - msg = yield self.force(req, [builderName]) - - # send the user back to the builder page - defer.returnValue((path_to_builder(req, self.builder_status), msg)) - -def buildForceContextForField(req, default_props, sch, field, master, buildername): - pname = "%s.%s"%(sch.name, field.fullName) - - default = field.default - - if "list" in field.type: - choices = field.getChoices(master, sch, buildername) - if choices: - default = choices[0] - default_props[pname+".choices"] = choices - - default = req.args.get(pname, [default])[0] - if "bool" in field.type: - default = "checked" if default else "" - elif isinstance(default, unicode): - # filter out unicode chars, and html stuff - default = html.escape(default.encode('utf-8','ignore')) - - default_props[pname] = default - - if "nested" in field.type: - for subfield in field.fields: - buildForceContextForField(req, default_props, sch, subfield, master, buildername) - -def buildForceContext(cxt, req, master, buildername=None): - force_schedulers = {} - default_props = collections.defaultdict(str) - for sch in master.allSchedulers(): - if isinstance(sch, ForceScheduler) and (buildername is None or(buildername in sch.builderNames)): - force_schedulers[sch.name] = sch - for field in sch.all_fields: - buildForceContextForField(req, default_props, sch, field, master, buildername) - - cxt['force_schedulers'] = force_schedulers - cxt['default_props'] = default_props - -# /builders/$builder -class StatusResourceBuilder(HtmlResource, BuildLineMixin): - addSlash = True - - def __init__(self, builder_status, numbuilds=20): - HtmlResource.__init__(self) - self.builder_status = builder_status - self.numbuilds = numbuilds - - def getPageTitle(self, request): - return "Buildbot: %s" % self.builder_status.getName() - - def builder(self, build, req): - b = {} - - b['num'] = build.getNumber() - b['link'] = path_to_build(req, build) - - when = build.getETA() - if when is not None: - b['when'] = util.formatInterval(when) - b['when_time'] = time.strftime("%H:%M:%S", - time.localtime(time.time() + when)) - - step = build.getCurrentStep() - # TODO: is this necessarily the case? - if not step: - b['current_step'] = "[waiting for Lock]" - else: - if step.isWaitingForLocks(): - b['current_step'] = "%s [waiting for Lock]" % step.getName() - else: - b['current_step'] = step.getName() - - b['stop_url'] = path_to_build(req, build) + '/stop' - - return b - - @defer.inlineCallbacks - def content(self, req, cxt): - b = self.builder_status - - cxt['name'] = b.getName() - cxt['description'] = b.getDescription() - req.setHeader('Cache-Control', 'no-cache') - slaves = b.getSlaves() - connected_slaves = [s for s in slaves if s.isConnected()] - - cxt['current'] = [self.builder(x, req) for x in b.getCurrentBuilds()] - - cxt['pending'] = [] - statuses = yield b.getPendingBuildRequestStatuses() - for pb in statuses: - changes = [] - - source = yield pb.getSourceStamp() - submitTime = yield pb.getSubmitTime() - bsid = yield pb.getBsid() - - properties = yield \ - pb.master.db.buildsets.getBuildsetProperties(bsid) - - if source.changes: - for c in source.changes: - changes.append({ 'url' : path_to_change(req, c), - 'who' : c.who, - 'revision' : c.revision, - 'repo' : c.repository }) - - cxt['pending'].append({ - 'when': time.strftime("%b %d %H:%M:%S", - time.localtime(submitTime)), - 'delay': util.formatInterval(util.now() - submitTime), - 'id': pb.brid, - 'changes' : changes, - 'num_changes' : len(changes), - 'properties' : properties, - }) - - numbuilds = cxt['numbuilds'] = int(req.args.get('numbuilds', [self.numbuilds])[0]) - recent = cxt['recent'] = [] - for build in b.generateFinishedBuilds(num_builds=int(numbuilds)): - recent.append(self.get_line_values(req, build, False)) - - sl = cxt['slaves'] = [] - connected_slaves = 0 - for slave in slaves: - s = {} - sl.append(s) - s['link'] = path_to_slave(req, slave) - s['name'] = slave.getName() - c = s['connected'] = slave.isConnected() - s['paused'] = slave.isPaused() - s['admin'] = unicode(slave.getAdmin() or '', 'utf-8') - if c: - connected_slaves += 1 - cxt['connected_slaves'] = connected_slaves - - cxt['authz'] = self.getAuthz(req) - cxt['builder_url'] = path_to_builder(req, b) - buildForceContext(cxt, req, self.getBuildmaster(req), b.getName()) - template = req.site.buildbot_service.templates.get_template("builder.html") - defer.returnValue(template.render(**cxt)) - - def ping(self, req): - return PingBuilderActionResource(self.builder_status) - - def getChild(self, path, req): - if path == "force": - return ForceBuildActionResource(self.builder_status) - if path == "ping": - return self.ping(req) - if path == "cancelbuild": - return CancelChangeResource(self.builder_status) - if path == "stopchange": - return StopChangeResource(self.builder_status) - if path == "builds": - return BuildsResource(self.builder_status) - - return HtmlResource.getChild(self, path, req) - -class CancelChangeResource(ActionResource): - - def __init__(self, builder_status): - ActionResource.__init__(self) - self.builder_status = builder_status - - @defer.inlineCallbacks - def performAction(self, req): - try: - request_id = req.args.get("id", [None])[0] - if request_id == "all": - cancel_all = True - else: - cancel_all = False - request_id = int(request_id) - except: - request_id = None - - authz = self.getAuthz(req) - if request_id: - c = interfaces.IControl(self.getBuildmaster(req)) - builder_control = c.getBuilder(self.builder_status.getName()) - - brcontrols = yield builder_control.getPendingBuildRequestControls() - - for build_req in brcontrols: - if cancel_all or (build_req.brid == request_id): - log.msg("Cancelling %s" % build_req) - res = yield authz.actionAllowed('cancelPendingBuild', req, - build_req) - if res: - build_req.cancel() - else: - defer.returnValue(path_to_authzfail(req)) - return - if not cancel_all: - break - - defer.returnValue(path_to_builder(req, self.builder_status)) - -class StopChangeMixin(object): - - @defer.inlineCallbacks - def stopChangeForBuilder(self, req, builder_status, auth_ok=False): - try: - request_change = req.args.get("change", [None])[0] - request_change = int(request_change) - except: - request_change = None - - authz = self.getAuthz(req) - if request_change: - c = interfaces.IControl(self.getBuildmaster(req)) - builder_control = c.getBuilder(builder_status.getName()) - - brcontrols = yield builder_control.getPendingBuildRequestControls() - build_controls = dict((x.brid, x) for x in brcontrols) - - build_req_statuses = yield \ - builder_status.getPendingBuildRequestStatuses() - - for build_req in build_req_statuses: - ss = yield build_req.getSourceStamp() - - if not ss.changes: - continue - - for change in ss.changes: - if change.number == request_change: - control = build_controls[build_req.brid] - log.msg("Cancelling %s" % control) - res = yield authz.actionAllowed('stopChange', req, control) - if (auth_ok or res): - control.cancel() - else: - defer.returnValue(False) - return - - defer.returnValue(True) - - -class StopChangeResource(StopChangeMixin, ActionResource): - - def __init__(self, builder_status): - ActionResource.__init__(self) - self.builder_status = builder_status - - @defer.inlineCallbacks - def performAction(self, req): - """Cancel all pending builds that include a given numbered change.""" - success = yield self.stopChangeForBuilder(req, self.builder_status) - - if not success: - defer.returnValue(path_to_authzfail(req)) - else: - defer.returnValue(path_to_builder(req, self.builder_status)) - - -class StopChangeAllResource(StopChangeMixin, ActionResource): - - def __init__(self, status): - ActionResource.__init__(self) - self.status = status - - @defer.inlineCallbacks - def performAction(self, req): - """Cancel all pending builds that include a given numbered change.""" - authz = self.getAuthz(req) - res = yield authz.actionAllowed('stopChange', req) - if not res: - defer.returnValue(path_to_authzfail(req)) - return - - for bname in self.status.getBuilderNames(): - builder_status = self.status.getBuilder(bname) - res = yield self.stopChangeForBuilder(req, builder_status, auth_ok=True) - if not res: - defer.returnValue(path_to_authzfail(req)) - return - - defer.returnValue(path_to_root(req)) - - -# /builders/_all -class StatusResourceAllBuilders(HtmlResource, BuildLineMixin): - - def __init__(self, status): - HtmlResource.__init__(self) - self.status = status - - def getChild(self, path, req): - if path == "forceall": - return self.forceall(req) - if path == "stopall": - return self.stopall(req) - if path == "stopchangeall": - return StopChangeAllResource(self.status) - if path == "cancelpendingall": - return CancelAllPendingBuildsActionResource(self.status, 'all') - - return HtmlResource.getChild(self, path, req) - - def forceall(self, req): - return ForceAllBuildsActionResource(self.status, 'all') - - def stopall(self, req): - return StopAllBuildsActionResource(self.status, 'all') - -# /builders/_selected - - -class StatusResourceSelectedBuilders(HtmlResource, BuildLineMixin): - - def __init__(self, status): - HtmlResource.__init__(self) - self.status = status - - def getChild(self, path, req): - if path == "forceselected": - return self.forceselected(req) - if path == "stopselected": - return self.stopselected(req) - if path == "cancelpendingselected": - return CancelAllPendingBuildsActionResource(self.status, 'selected') - - return HtmlResource.getChild(self, path, req) - - def forceselected(self, req): - return ForceAllBuildsActionResource(self.status, 'selected') - - def stopselected(self, req): - return StopAllBuildsActionResource(self.status, 'selected') - -# /builders - - -class BuildersResource(HtmlResource): - pageTitle = "Builders" - addSlash = True - - def __init__(self, numbuilds=20): - HtmlResource.__init__(self) - self.numbuilds = numbuilds - - @defer.inlineCallbacks - def content(self, req, cxt): - status = self.getStatus(req) - encoding = getRequestCharset(req) - - builders = req.args.get("builder", status.getBuilderNames()) - branches = [ b.decode(encoding) - for b in req.args.get("branch", []) - if b ] - - # get counts of pending builds for each builder - brstatus_ds = [] - brcounts = {} - def keep_count(statuses, builderName): - brcounts[builderName] = len(statuses) - for builderName in builders: - builder_status = status.getBuilder(builderName) - d = builder_status.getPendingBuildRequestStatuses() - d.addCallback(keep_count, builderName) - brstatus_ds.append(d) - yield defer.gatherResults(brstatus_ds) - - cxt['branches'] = branches - bs = cxt['builders'] = [] - - building = 0 - online = 0 - base_builders_url = path_to_root(req) + "builders/" - for bn in builders: - bld = { 'link': base_builders_url + urllib.quote(bn, safe=''), - 'name': bn } - bs.append(bld) - - builder = status.getBuilder(bn) - builds = list(builder.generateFinishedBuilds(map_branches(branches), - num_builds=1)) - if builds: - b = builds[0] - bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber()) - label = None - all_got_revisions = b.getAllGotRevisions() - # If len = 1 then try if revision can be used as label. - if len(all_got_revisions) == 1: - label = all_got_revisions[all_got_revisions.keys()[0]] - if not label or len(str(label)) > 20: - label = "#%d" % b.getNumber() - - bld['build_label'] = label - bld['build_text'] = " ".join(b.getText()) - bld['build_css_class'] = build_get_class(b) - - current_box = ICurrentBox(builder).getBox(status, brcounts) - bld['current_box'] = current_box.td() - - builder_status = builder.getState()[0] - if builder_status == "building": - building += 1 - online += 1 - elif builder_status != "offline": - online += 1 - - cxt['authz'] = self.getAuthz(req) - cxt['num_building'] = building - cxt['num_online'] = online - buildForceContext(cxt, req, self.getBuildmaster(req)) - template = req.site.buildbot_service.templates.get_template("builders.html") - defer.returnValue(template.render(**cxt)) - - def getChild(self, path, req): - s = self.getStatus(req) - if path in s.getBuilderNames(): - builder_status = s.getBuilder(path) - return StatusResourceBuilder(builder_status, self.numbuilds) - if path == "_all": - return StatusResourceAllBuilders(self.getStatus(req)) - if path == "_selected": - return StatusResourceSelectedBuilders(self.getStatus(req)) - - return HtmlResource.getChild(self, path, req) - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py deleted file mode 100644 index 9dd57b6c..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/buildstatus.py +++ /dev/null @@ -1,66 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -from buildbot.status.web.base import HtmlResource, IBox - -class BuildStatusStatusResource(HtmlResource): - def __init__(self, categories=None): - HtmlResource.__init__(self) - - def content(self, request, ctx): - """Display a build in the same format as the waterfall page. - The HTTP GET parameters are the builder name and the build - number.""" - - status = self.getStatus(request) - request.setHeader('Cache-Control', 'no-cache') - - # Get the parameters. - name = request.args.get("builder", [None])[0] - number = request.args.get("number", [None])[0] - if not name or not number: - return "builder and number parameter missing" - number = int(number) - - # Check if the builder in parameter exists. - try: - builder = status.getBuilder(name) - except: - return "unknown builder" - - # Check if the build in parameter exists. - build = builder.getBuild(int(number)) - if not build: - return "unknown build %s" % number - - rows = ctx['rows'] = [] - - # Display each step, starting by the last one. - for i in range(len(build.getSteps()) - 1, -1, -1): - step = build.getSteps()[i] - if step.isStarted() and step.getText(): - rows.append(IBox(step).getBox(request).td(align="center")) - - # Display the bottom box with the build number in it. - ctx['build'] = IBox(build).getBox(request).td(align="center") - - template = request.site.buildbot_service.templates.get_template("buildstatus.html") - data = template.render(**ctx) - - # We want all links to display in a new tab/window instead of in the - # current one. - # TODO: Move to template - data = data.replace('<a ', '<a target="_blank"') - return data diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py deleted file mode 100644 index cc53e34b..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/change_hook.py +++ /dev/null @@ -1,136 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -# code inspired/copied from contrib/github_buildbot -# and inspired from code from the Chromium project -# otherwise, Andrew Melo <andrew.melo@gmail.com> wrote the rest -# but "the rest" is pretty minimal - -import re -from twisted.web import resource, server -from twisted.python.reflect import namedModule -from twisted.python import log -from twisted.internet import defer - -class ChangeHookResource(resource.Resource): - # this is a cheap sort of template thingy - contentType = "text/html; charset=utf-8" - children = {} - def __init__(self, dialects={}): - """ - The keys of 'dialects' select a modules to load under - master/buildbot/status/web/hooks/ - The value is passed to the module's getChanges function, providing - configuration options to the dialect. - """ - self.dialects = dialects - self.request_dialect = None - - def getChild(self, name, request): - return self - - def render_GET(self, request): - """ - Reponds to events and starts the build process - different implementations can decide on what methods they will accept - """ - return self.render_POST(request) - - def render_POST(self, request): - """ - Reponds to events and starts the build process - different implementations can decide on what methods they will accept - - :arguments: - request - the http request object - """ - - try: - changes, src = self.getChanges( request ) - except ValueError, err: - request.setResponseCode(400, err.args[0]) - return err.args[0] - except Exception, e: - log.err(e, "processing changes from web hook") - msg = "Error processing changes." - request.setResponseCode(500, msg) - return msg - - log.msg("Payload: " + str(request.args)) - - if not changes: - log.msg("No changes found") - return "no changes found" - d = self.submitChanges( changes, request, src ) - def ok(_): - request.setResponseCode(202) - request.finish() - def err(why): - log.err(why, "adding changes from web hook") - request.setResponseCode(500) - request.finish() - d.addCallbacks(ok, err) - return server.NOT_DONE_YET - - - def getChanges(self, request): - """ - Take the logic from the change hook, and then delegate it - to the proper handler - http://localhost/change_hook/DIALECT will load up - buildmaster/status/web/hooks/DIALECT.py - - and call getChanges() - - the return value is a list of changes - - if DIALECT is unspecified, a sample implementation is provided - """ - uriRE = re.search(r'^/change_hook/?([a-zA-Z0-9_]*)', request.uri) - - if not uriRE: - log.msg("URI doesn't match change_hook regex: %s" % request.uri) - raise ValueError("URI doesn't match change_hook regex: %s" % request.uri) - - changes = [] - src = None - - # Was there a dialect provided? - if uriRE.group(1): - dialect = uriRE.group(1) - else: - dialect = 'base' - - if dialect in self.dialects.keys(): - log.msg("Attempting to load module buildbot.status.web.hooks." + dialect) - tempModule = namedModule('buildbot.status.web.hooks.' + dialect) - changes, src = tempModule.getChanges(request,self.dialects[dialect]) - log.msg("Got the following changes %s" % changes) - self.request_dialect = dialect - else: - m = "The dialect specified, '%s', wasn't whitelisted in change_hook" % dialect - log.msg(m) - log.msg("Note: if dialect is 'base' then it's possible your URL is malformed and we didn't regex it properly") - raise ValueError(m) - - return (changes, src) - - @defer.inlineCallbacks - def submitChanges(self, changes, request, src): - master = request.site.buildbot_service.master - for chdict in changes: - change = yield master.addChange(src=src, **chdict) - log.msg("injected change %s" % change) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py deleted file mode 100644 index e579669e..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/changes.py +++ /dev/null @@ -1,71 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from zope.interface import implements -from twisted.python import components -from twisted.web.resource import NoResource - -from buildbot.changes.changes import Change -from buildbot.status.web.base import HtmlResource, IBox, Box - -class ChangeResource(HtmlResource): - def __init__(self, changeid): - self.changeid = changeid - self.pageTitle = "Change #%d" % changeid - - def content(self, req, cxt): - d = self.getStatus(req).getChange(self.changeid) - def cb(change): - if not change: - return "No change number %d" % self.changeid - templates = req.site.buildbot_service.templates - cxt['c'] = change.asDict() - template = templates.get_template("change.html") - data = template.render(cxt) - return data - d.addCallback(cb) - return d - -# /changes/NN -class ChangesResource(HtmlResource): - - def content(self, req, cxt): - cxt['sources'] = self.getStatus(req).getChangeSources() - template = req.site.buildbot_service.templates.get_template("change_sources.html") - return template.render(**cxt) - - def getChild(self, path, req): - try: - changeid = int(path) - except ValueError: - return NoResource("Expected a change number") - - return ChangeResource(changeid) - -class ChangeBox(components.Adapter): - implements(IBox) - - def getBox(self, req): - url = req.childLink("../changes/%d" % self.original.number) - template = req.site.buildbot_service.templates.get_template("change_macros.html") - text = template.module.box_contents(url=url, - who=self.original.getShortAuthor(), - pageTitle=self.original.comments, - revision=self.original.revision, - project=self.original.project) - return Box([text], class_="Change") -components.registerAdapter(ChangeBox, Change, IBox) - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py deleted file mode 100644 index 60eb67c0..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/console.py +++ /dev/null @@ -1,744 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -import time -import operator -import re -import urllib -from twisted.internet import defer -from buildbot import util -from buildbot.status import builder -from buildbot.status.web.base import HtmlResource -from buildbot.changes import changes - -class DoesNotPassFilter(Exception): pass # Used for filtering revs - -def getResultsClass(results, prevResults, inProgress): - """Given the current and past results, return the class that will be used - by the css to display the right color for a box.""" - - if inProgress: - return "running" - - if results is None: - return "notstarted" - - if results == builder.SUCCESS: - return "success" - - if results == builder.WARNINGS: - return "warnings" - - 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 "failure-again" - - # Any other results? Like EXCEPTION? - return "exception" - -class ANYBRANCH: pass # a flag value, used below - -class DevRevision: - """Helper class that contains all the information we need for a revision.""" - - def __init__(self, change): - self.revision = change.revision - self.comments = change.comments - self.who = change.who - self.date = change.getTime() - self.revlink = getattr(change, 'revlink', None) - self.when = change.when - self.repository = change.repository - self.project = change.project - - -class DevBuild: - """Helper class that contains all the information we need for a build.""" - - def __init__(self, revision, build, details): - self.revision = revision - self.results = build.getResults() - self.number = build.getNumber() - self.isFinished = build.isFinished() - self.text = build.getText() - self.eta = build.getETA() - self.details = details - self.when = build.getTimes()[0] - #TODO: support multiple sourcestamps - self.source = build.getSourceStamps()[0] - - -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, orderByTime=False): - HtmlResource.__init__(self) - - self.status = None - - if orderByTime: - self.comparator = TimeRevisionComparator() - else: - self.comparator = IntegerRevisionComparator() - - def getPageTitle(self, request): - status = self.getStatus(request) - title = status.getTitle() - if title: - return "BuildBot: %s" % title - else: - return "BuildBot" - - def getChangeManager(self, request): - return request.site.buildbot_service.parent.change_svc - - ## - ## 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.getSourceStamps()[0] - allChanges.extend(sourcestamp.changes[:]) - build = build.getPreviousBuild() - - debugInfo["source_fetch_len"] = len(allChanges) - return allChanges - - @defer.inlineCallbacks - def getAllChanges(self, request, status, debugInfo): - master = request.site.buildbot_service.master - - chdicts = yield master.db.changes.getRecentChanges(25) - - # convert those to Change instances - allChanges = yield defer.gatherResults([ - changes.Change.fromChdict(master, chdict) - for chdict in chdicts ]) - - allChanges.sort(key=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 - - defer.returnValue(allChanges) - - def getBuildDetails(self, request, builderName, build): - """Returns an HTML list of failures for a given build.""" - details = {} - if not build.getLogs(): - return details - - 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['buildername'] = builderName - details['status'] = strippedDetails - details['reason'] = reason - logs = details['logs'] = [] - - if step.getLogs(): - 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))) - logs.append(dict(url=logurl, name=logname)) - return details - - def getBuildsForRevision(self, request, builder, builderName, codebase, - 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 - - builds = [] - build = self.getHeadBuild(builder) - number = 0 - while build and number < numBuilds: - debugInfo["builds_scanned"] += 1 - - got_rev = None - sourceStamps = build.getSourceStamps(absolute=True) - - # The console page cannot handle builds that have more than 1 revision - if codebase is not None: - # Get the last revision in this build for this codebase. - for ss in sourceStamps: - if ss.codebase == codebase: - got_rev = ss.revision - break - elif len(sourceStamps) == 1: - ss = sourceStamps[0] - # Get the last revision in this build. - got_rev = ss.revision - - # 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 is not None: - number += 1 - details = self.getBuildDetails(request, builderName, build) - devBuild = DevBuild(got_rev, build, details) - builds.append(devBuild) - - # Now break if we have enough builds. - current_revision = self.getChangeForBuild( - build, revision) - if self.comparator.isRevisionEarlier( - devBuild, current_revision): - break - - build = build.getPreviousBuild() - - return builds - - def getChangeForBuild(self, build, revision): - if not build or not build.getChanges(): # Forced build - return DevBuild(revision, build, None) - - 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(key=self.comparator.getSortingKey()) - return changes[-1] - - def getAllBuildsForRevision(self, status, request, codebase, lastRevision, - numBuilds, categories, builders, debugInfo): - """Returns a dictionary 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 dictionary of - builders we care about. The key is it's category. - - codebase is the codebase to get revisions from - 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 dictionary. - 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 dictionary of builders. - builderList[category].append(builderName) - # Set the list of builds for this builder. - allBuilds[builderName] = self.getBuildsForRevision(request, - builder, - builderName, - codebase, - lastRevision, - numBuilds, - debugInfo) - - return (builderList, allBuilds) - - - ## - ## Display functions - ## - - def displayCategories(self, builderList, debugInfo): - """Display the top category line.""" - - count = 0 - for category in builderList: - count += len(builderList[category]) - - categories = builderList.keys() - categories.sort() - - cs = [] - - for category in categories: - c = {} - - c["name"] = category - - # 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. - c["size"] = (len(builderList[category]) * 100) / count - cs.append(c) - - return cs - - def displaySlaveLine(self, status, builderList, debugInfo): - """Display a line the shows the current status for all the builders we - care about.""" - - nbSlaves = 0 - - # Get the number of builders. - for category in builderList: - nbSlaves += len(builderList[category]) - - # Get the categories, and order them alphabetically. - categories = builderList.keys() - categories.sort() - - slaves = {} - - # For each category, we display each builder. - for category in categories: - slaves[category] = [] - # For each builder in this category, we set the build info and we - # display the box. - for builder in builderList[category]: - s = {} - s["color"] = "notstarted" - s["pageTitle"] = builder - s["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": - s["color"] = "offline" - 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: - s["color"] = getResultsClass(build.getResults(), None, - False) - - slaves[category].append(s) - - return slaves - - def displayStatusLine(self, builderList, allBuilds, revision, debugInfo): - """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.""" - - details = [] - nbSlaves = 0 - for category in builderList: - nbSlaves += len(builderList[category]) - - # Sort the categories. - categories = builderList.keys() - categories.sort() - - builds = {} - - # Display the boxes by category group. - for category in categories: - - builds[category] = [] - - # Display the boxes for each builder in this category. - for builder in builderList[category]: - introducedIn = None - firstNotIn = None - - # 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 - previousResults = None - if introducedIn: - results = introducedIn.results - if firstNotIn: - previousResults = firstNotIn.results - - isRunning = False - if introducedIn and not introducedIn.isFinished: - isRunning = True - - url = "./waterfall" - pageTitle = builder - tag = "" - current_details = {} - if introducedIn: - current_details = introducedIn.details or "" - url = "./buildstatus?builder=%s&number=%s" % (urllib.quote(builder), - introducedIn.number) - pageTitle += " " - pageTitle += 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: - pageTitle += ' ETA: %ds' % (introducedIn.eta or 0) - - resultsClass = getResultsClass(results, previousResults, isRunning) - - b = {} - b["url"] = url - b["pageTitle"] = pageTitle - b["color"] = resultsClass - b["tag"] = tag - - builds[category].append(b) - - # If the box is red, we add the explaination in the details - # section. - if current_details and resultsClass == "failure": - details.append(current_details) - - return (builds, details) - - def filterRevisions(self, revisions, filter=None, max_revs=None): - """Filter a set of revisions based on any number of filter criteria. - If specified, filter should be a dict with keys corresponding to - revision attributes, and values of 1+ strings""" - if not filter: - if max_revs is None: - for rev in reversed(revisions): - yield DevRevision(rev) - else: - for index,rev in enumerate(reversed(revisions)): - if index >= max_revs: - break - yield DevRevision(rev) - else: - for index, rev in enumerate(reversed(revisions)): - if max_revs and index >= max_revs: - break - try: - for field,acceptable in filter.iteritems(): - if not hasattr(rev, field): - raise DoesNotPassFilter - if type(acceptable) in (str, unicode): - if getattr(rev, field) != acceptable: - raise DoesNotPassFilter - elif type(acceptable) in (list, tuple, set): - if getattr(rev, field) not in acceptable: - raise DoesNotPassFilter - yield DevRevision(rev) - except DoesNotPassFilter: - pass - - def displayPage(self, request, status, builderList, allBuilds, codebase, - revisions, categories, repository, project, branch, - debugInfo): - """Display the console page.""" - # Build the main template directory with all the informations we have. - subs = dict() - subs["branch"] = branch or 'trunk' - subs["repository"] = repository - subs["project"] = project - subs["codebase"] = codebase - if categories: - subs["categories"] = ' '.join(categories) - subs["time"] = time.strftime("%a %d %b %Y %H:%M:%S", - time.localtime(util.now())) - subs["debugInfo"] = debugInfo - subs["ANYBRANCH"] = ANYBRANCH - - if builderList: - subs["categories"] = self.displayCategories(builderList, debugInfo) - subs['slaves'] = self.displaySlaveLine(status, builderList, debugInfo) - else: - subs["categories"] = [] - - subs['revisions'] = [] - - # For each revision we show one line - for revision in revisions: - r = {} - - # Fill the dictionary with this new information - r['id'] = revision.revision - r['link'] = revision.revlink - r['who'] = revision.who - r['date'] = revision.date - r['comments'] = revision.comments - r['repository'] = revision.repository - r['project'] = revision.project - - # Display the status for all builders. - (builds, details) = self.displayStatusLine(builderList, - allBuilds, - revision, - debugInfo) - r['builds'] = builds - r['details'] = details - - # Calculate the td span for the comment and the details. - r["span"] = len(builderList) + 2 - - subs['revisions'].append(r) - - # - # Display the footer of the page. - # - debugInfo["load_time"] = time.time() - debugInfo["load_time"] - return subs - - - def content(self, request, cxt): - "This method builds the main console view display." - - 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 - - request.setHeader('Cache-Control', 'no-cache') - - # Sets the default reload time to 60 seconds. - if not reload_time: - reload_time = 60 - - # Append the tag to refresh the page. - if reload_time is not None and reload_time != 0: - cxt['refresh'] = reload_time - - # Debug information to display at the end of the page. - debugInfo = cxt['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", []) - # Repo used to filter the changes shown. - repository = request.args.get("repository", [None])[0] - # Project used to filter the changes shown. - project = request.args.get("project", [None])[0] - # Branch used to filter the changes shown. - branch = request.args.get("branch", [ANYBRANCH])[0] - # Codebase used to filter the changes shown. - codebase = request.args.get("codebase", [None])[0] - # List of all the committers name to display on the page. - devName = request.args.get("name", []) - - # and the data we want to render - status = self.getStatus(request) - - # 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 80 revisions. - numRevs = int(request.args.get("revs", [40])[0]) - if devName: - numRevs *= 2 - numBuilds = numRevs - - # Get all changes we can find. This is a DB operation, so it must use - # a deferred. - d = self.getAllChanges(request, status, debugInfo) - def got_changes(allChanges): - debugInfo["source_all"] = len(allChanges) - - revFilter = {} - if branch != ANYBRANCH: - revFilter['branch'] = branch - if devName: - revFilter['who'] = devName - if repository: - revFilter['repository'] = repository - if project: - revFilter['project'] = project - if codebase is not None: - revFilter['codebase'] = codebase - revisions = list(self.filterRevisions(allChanges, max_revs=numRevs, - filter=revFilter)) - 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, - codebase, - lastRevision, - numBuilds, - categories, - builders, - debugInfo) - - debugInfo["added_blocks"] = 0 - - cxt.update(self.displayPage(request, status, builderList, - allBuilds, codebase, revisions, - categories, repository, project, - branch, debugInfo)) - - templates = request.site.buildbot_service.templates - template = templates.get_template("console.html") - data = template.render(cxt) - return data - d.addCallback(got_changes) - return d - -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 operator.attrgetter('when') - -class IntegerRevisionComparator(RevisionComparator): - def isRevisionEarlier(self, first, second): - try: - return int(first.revision) < int(second.revision) - except (TypeError, ValueError): - return False - - def isValidRevision(self, revision): - try: - int(revision) - return True - except: - return False - - def getSortingKey(self): - return operator.attrgetter('revision') - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py deleted file mode 100644 index f29a11ca..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/feeds.py +++ /dev/null @@ -1,275 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -# This module enables ATOM and RSS feeds from webstatus. -# -# It is based on "feeder.py" which was part of the Buildbot -# configuration for the Subversion project. The original file was -# created by Lieven Gobaerts and later adjusted by API -# (apinheiro@igalia.coma) and also here -# http://code.google.com/p/pybots/source/browse/trunk/master/Feeder.py -# -# All subsequent changes to feeder.py where made by Chandan-Dutta -# Chowdhury <chandan-dutta.chowdhury @ hp.com> and Gareth Armstrong -# <gareth.armstrong @ hp.com>. -# -# Those modifications are as follows: -# 1) the feeds are usable from baseweb.WebStatus -# 2) feeds are fully validated ATOM 1.0 and RSS 2.0 feeds, verified -# with code from http://feedvalidator.org -# 3) nicer xml output -# 4) feeds can be filtered as per the /waterfall display with the -# builder and category filters -# 5) cleaned up white space and imports -# -# Finally, the code was directly integrated into these two files, -# buildbot/status/web/feeds.py (you're reading it, ;-)) and -# buildbot/status/web/baseweb.py. - -import os -import re -import time -from twisted.web import resource -from buildbot.status import results - -class XmlResource(resource.Resource): - contentType = "text/xml; charset=UTF-8" - docType = '' - - def getChild(self, name, request): - return self - - def render(self, request): - data = self.content(request) - request.setHeader("content-type", self.contentType) - if request.method == "HEAD": - request.setHeader("content-length", len(data)) - return '' - return data - -_abbr_day = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] -_abbr_mon = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', - 'Sep', 'Oct', 'Nov', 'Dec'] - -def rfc822_time(tstamp): - res = time.strftime("%%s, %d %%s %Y %H:%M:%S GMT", - tstamp) - res = res % (_abbr_day[tstamp.tm_wday], _abbr_mon[tstamp.tm_mon]) - return res - -class FeedResource(XmlResource): - pageTitle = None - link = 'http://dummylink' - language = 'en-us' - description = 'Dummy rss' - status = None - - def __init__(self, status, categories=None, pageTitle=None): - self.status = status - self.categories = categories - self.pageTitle = pageTitle - self.title = self.status.getTitle() - self.link = self.status.getBuildbotURL() - self.description = 'List of builds' - self.pubdate = time.gmtime(int(time.time())) - self.user = self.getEnv(['USER', 'USERNAME'], 'buildmaster') - self.hostname = self.getEnv(['HOSTNAME', 'COMPUTERNAME'], - 'buildmaster') - self.children = {} - - def getEnv(self, keys, fallback): - for key in keys: - if key in os.environ: - return os.environ[key] - return fallback - - def getBuilds(self, request): - builds = [] - # THIS is lifted straight from the WaterfallStatusResource Class in - # status/web/waterfall.py - # - # we start with all Builders available to this Waterfall: this is - # limited by the config-file -time categories= argument, and defaults - # to all defined Builders. - allBuilderNames = self.status.getBuilderNames(categories=self.categories) - builders = [self.status.getBuilder(name) for name in allBuilderNames] - - # but if the URL has one or more builder= arguments (or the old show= - # argument, which is still accepted for backwards compatibility), we - # use that set of builders instead. We still don't show anything - # outside the config-file time set limited by categories=. - showBuilders = request.args.get("show", []) - showBuilders.extend(request.args.get("builder", [])) - if showBuilders: - builders = [b for b in builders if b.name in showBuilders] - - # now, if the URL has one or category= arguments, use them as a - # filter: only show those builders which belong to one of the given - # categories. - showCategories = request.args.get("category", []) - if showCategories: - builders = [b for b in builders if b.category in showCategories] - - failures_only = request.args.get("failures_only", ["false"]) - failures_only = failures_only[0] not in ('false', '0', 'no', 'off') - - maxFeeds = 25 - - # Copy all failed builds in a new list. - # This could clearly be implemented much better if we had - # access to a global list of builds. - for b in builders: - if failures_only: - res = (results.FAILURE,) - else: - res = None - builds.extend(b.generateFinishedBuilds(results=res, max_search=maxFeeds)) - - # Sort build list by date, youngest first. - # To keep compatibility with python < 2.4, use this for sorting instead: - # We apply Decorate-Sort-Undecorate - deco = [(build.getTimes(), build) for build in builds] - deco.sort() - deco.reverse() - builds = [build for (b1, build) in deco] - - if builds: - builds = builds[:min(len(builds), maxFeeds)] - return builds - - def content(self, request): - builds = self.getBuilds(request) - - build_cxts = [] - - for build in builds: - start, finished = build.getTimes() - finishedTime = time.gmtime(int(finished)) - link = re.sub(r'index.html', "", self.status.getURLForThing(build)) - - # title: trunk r22191 (plus patch) failed on - # 'i686-debian-sarge1 shared gcc-3.3.5' - ss_list = build.getSourceStamps() - all_got_revisions = build.getAllGotRevisions() - src_cxts = [] - for ss in ss_list: - sc = {} - sc['codebase'] = ss.codebase - if (ss.branch is None and ss.revision is None and ss.patch is None - and not ss.changes): - sc['repository'] = None - sc['branch'] = None - sc['revision'] = "Latest revision" - else: - sc['repository'] = ss.repository - sc['branch'] = ss.branch - got_revision = all_got_revisions.get(ss.codebase, None) - if got_revision: - sc['revision'] = got_revision - else: - sc['revision'] = str(ss.revision) - if ss.patch: - sc['revision'] += " (plus patch)" - if ss.changes: - pass - src_cxts.append(sc) - res = build.getResults() - pageTitle = ('Builder "%s": %s' % - (build.getBuilder().getName(), results.Results[res])) - - # Add information about the failing steps. - failed_steps = [] - log_lines = [] - for s in build.getSteps(): - res = s.getResults()[0] - if res not in (results.SUCCESS, results.WARNINGS, - results.SKIPPED): - failed_steps.append(s.getName()) - - # Add the last 30 lines of each log. - for log in s.getLogs(): - log_lines.append('Last lines of build log "%s":' % - log.getName()) - log_lines.append([]) - try: - logdata = log.getText() - except IOError: - # Probably the log file has been removed - logdata ='** log file not available **' - unilist = list() - for line in logdata.split('\n')[-30:]: - unilist.append(unicode(line,'utf-8')) - log_lines.extend(unilist) - - bc = {} - bc['sources'] = src_cxts - bc['date'] = rfc822_time(finishedTime) - bc['summary_link'] = ('%sbuilders/%s' % - (self.link, - build.getBuilder().getName())) - bc['name'] = build.getBuilder().getName() - bc['number'] = build.getNumber() - bc['responsible_users'] = build.getResponsibleUsers() - bc['failed_steps'] = failed_steps - bc['pageTitle'] = pageTitle - bc['link'] = link - bc['log_lines'] = log_lines - - if finishedTime is not None: - bc['rfc822_pubdate'] = rfc822_time(finishedTime) - bc['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", - finishedTime) - - # Every RSS/Atom item must have a globally unique ID - guid = ('tag:%s@%s,%s:%s' % - (self.user, self.hostname, - time.strftime("%Y-%m-%d", finishedTime), - time.strftime("%Y%m%d%H%M%S", finishedTime))) - bc['guid'] = guid - - build_cxts.append(bc) - - pageTitle = self.pageTitle - if not pageTitle: - pageTitle = 'Build status of %s' % self.title - - cxt = {} - cxt['pageTitle'] = pageTitle - cxt['title_url'] = self.link - cxt['title'] = self.title - cxt['language'] = self.language - cxt['description'] = self.description - if self.pubdate is not None: - cxt['rfc822_pubdate'] = rfc822_time( self.pubdate) - cxt['rfc3339_pubdate'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", - self.pubdate) - - cxt['builds'] = build_cxts - template = request.site.buildbot_service.templates.get_template(self.template_file) - return template.render(**cxt).encode('utf-8').strip() - -class Rss20StatusResource(FeedResource): - # contentType = 'application/rss+xml' (browser dependent) - template_file = 'feed_rss20.xml' - - def __init__(self, status, categories=None, pageTitle=None): - FeedResource.__init__(self, status, categories, pageTitle) - -class Atom10StatusResource(FeedResource): - # contentType = 'application/atom+xml' (browser dependent) - template_file = 'feed_atom10.xml' - - def __init__(self, status, categories=None, pageTitle=None): - FeedResource.__init__(self, status, categories, pageTitle) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpg b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpg Binary files differdeleted file mode 100644 index 6c2e5ddf..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/bg_gradient.jpg +++ /dev/null diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css deleted file mode 100644 index d769f73a..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/default.css +++ /dev/null @@ -1,604 +0,0 @@ -body.interface { - margin-left: 30px; - margin-right: 30px; - margin-top: 20px; - margin-bottom: 50px; - padding: 0; - background: url(bg_gradient.jpg) repeat-x; - font-family: Verdana, sans-serif; - font-size: 10px; - background-color: #fff; - color: #333; -} - -.auth { -position:absolute; -top:5px; -right:40px; -} - -.alert { - color: #c30000; - background-color: #f2dcdc; - padding: 5px 5px 5px 25px; - margin-bottom: 20px; - border-top:1px solid #ccc; - border-bottom:1px solid #ccc; - border-color: #c30000; - font-size: 20px; -} -a:link,a:visited,a:active { - color: #444; -} - -table { - border-spacing: 1px 1px; -} - -table td { - padding: 3px 4px 3px 4px; - text-align: center; -} - -.Project { - min-width: 6em; -} - -.LastBuild,.Activity { - padding: 0 0 0 4px; -} - -.LastBuild,.Activity,.Builder,.BuildStep { - min-width: 5em; -} - -/* Chromium Specific styles */ -div.BuildResultInfo { - color: #444; -} - -div.Announcement { - margin-bottom: 1em; -} - -div.Announcement>a:hover { - color: black; -} - -div.Announcement>div.Notice { - background-color: #afdaff; - padding: 0.5em; - font-size: 16px; - text-align: center; -} - -div.Announcement>div.Open { - border: 3px solid #8fdf5f; - padding: 0.5em; - font-size: 16px; - text-align: center; -} - -div.Announcement>div.Closed { - border: 5px solid #e98080; - padding: 0.5em; - font-size: 24px; - font-weight: bold; - text-align: center; -} - -td.Time { - color: #000; - border-bottom: 1px solid #aaa; - background-color: #eee; -} - -td.Activity,td.Change,td.Builder { - color: #333333; - background-color: #CCCCCC; -} - -td.Change { - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; -} - -td.Event { - color: #777; - background-color: #ddd; - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; -} - -td.Activity { - border-top-left-radius: 10px; - -webkit-border-top-left-radius: 10px; - -moz-border-radius-topleft: 10px; - min-height: 20px; - padding: 2px 0 2px 0; -} - -td.idle,td.waiting,td.offline,td.building { - border-top-left-radius: 0px; - -webkit-border-top-left-radius: 0px; - -moz-border-radius-topleft: 0px; -} - -.LastBuild { - border-top-left-radius: 5px; - -webkit-border-top-left-radius: 5px; - -moz-border-radius-topleft: 5px; - border-top-right-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topright: 5px; -} - -/* Console view styles */ -td.DevRev { - padding: 4px 8px 4px 8px; - color: #333333; - border-top-left-radius: 5px; - -webkit-border-top-left-radius: 5px; - -moz-border-radius-topleft: 5px; - background-color: #eee; - width: 1%; -} - -td.DevRevCollapse { - border-bottom-left-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomleft: 5px; -} - -td.DevName { - padding: 4px 8px 4px 8px; - color: #333333; - background-color: #eee; - width: 1%; - text-align: left; -} - -td.DevStatus { - padding: 4px 4px 4px 4px; - color: #333333; - background-color: #eee; -} - -td.DevSlave { - padding: 4px 4px 4px 4px; - color: #333333; - background-color: #eee; -} - -td.first { - border-top-left-radius: 5px; - -webkit-border-top-left-radius: 5px; - -moz-border-radius-topleft: 5px; -} - -td.last { - border-top-right-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topright: 5px; -} - -td.DevStatusCategory { - border-radius: 5px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-width: 1px; - border-style: solid; -} - -td.DevStatusCollapse { - border-bottom-right-radius: 5px; - -webkit-border-bottom-right-radius: 5px; - -moz-border-radius-bottomright: 5px; -} - -td.DevDetails { - font-weight: normal; - padding: 8px 8px 8px 8px; - color: #333333; - background-color: #eee; - text-align: left; -} - -td.DevDetails li a { - padding-right: 5px; -} - -td.DevComment { - font-weight: normal; - padding: 8px 8px 8px 8px; - color: #333333; - background-color: #eee; - text-align: left; -} - -td.DevBottom { - border-bottom-right-radius: 5px; - -webkit-border-bottom-right-radius: 5px; - -moz-border-radius-bottomright: 5px; - border-bottom-left-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomleft: 5px; -} - -td.Alt { - background-color: #ddd; -} - -.legend { - border-radius: 5px !important; - -webkit-border-radius: 5px !important; - -moz-border-radius: 5px !important; - width: 100px; - max-width: 100px; - text-align: center; - padding: 2px 2px 2px 2px; - height: 14px; - white-space: nowrap; -} - -.DevStatusBox { - text-align: center; - height: 20px; - padding: 0 2px; - line-height: 0; - white-space: nowrap; -} - -.DevStatusBox a { - opacity: 0.85; - border-width: 1px; - border-style: solid; - border-radius: 4px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - display: block; - width: 90%; - height: 20px; - line-height: 20px; - margin-left: auto; - margin-right: auto; -} - -.DevSlaveBox { - text-align: center; - height: 10px; - padding: 0 2px; - line-height: 0; - white-space: nowrap; -} - -.DevSlaveBox a { - opacity: 0.85; - border-width: 1px; - border-style: solid; - border-radius: 4px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - display: block; - width: 90%; - height: 10px; - line-height: 20px; - margin-left: auto; - margin-right: auto; -} - -a.noround { - border-radius: 0px; - -webkit-border-radius: 0px; - -moz-border-radius: 0px; - position: relative; - margin-top: -8px; - margin-bottom: -8px; - height: 36px; - border-top-width: 0; - border-bottom-width: 0; -} - -a.begin { - border-top-width: 1px; - position: relative; - margin-top: 0px; - margin-bottom: -7px; - height: 27px; - border-top-left-radius: 4px; - -webkit-border-top-left-radius: 4px; - -moz-border-radius-topleft: 4px; - border-top-right-radius: 4px; - -webkit-border-top-right-radius: 4px; - -moz-border-radius-topright: 4px; -} - -a.end { - border-bottom-width: 1px; - position: relative; - margin-top: -7px; - margin-bottom: 0px; - height: 27px; - border-bottom-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-bottomleft: 4px; - border-bottom-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-bottomright: 4px; -} - -.center_align { - text-align: center; -} - -.right_align { - text-align: right; -} - -.left_align { - text-align: left; -} - -div.BuildWaterfall { - border-radius: 7px; - -webkit-border-radius: 7px; - -moz-border-radius: 7px; - position: absolute; - left: 0px; - top: 0px; - background-color: #FFFFFF; - padding: 4px 4px 4px 4px; - float: left; - display: none; - border-width: 1px; - border-style: solid; -} - -/* LastBuild, BuildStep states */ -.success { - color: #000; - background-color: #8d4; - border-color: #4F8530; -} - -.failure { - color: #000; - background-color: #e88; - border-color: #A77272; -} - -.failure-again { - color: #000; - background-color: #eA9; - border-color: #A77272; -} - -.warnings { - color: #FFFFFF; - background-color: #fa3; - border-color: #C29D46; -} - -.skipped { - color: #000; - background: #AADDEE; - border-color: #AADDEE; -} - -.exception,.retry { - color: #FFFFFF; - background-color: #c6c; - border-color: #ACA0B3; -} - -.start { - color: #000; - background-color: #ccc; - border-color: #ccc; -} - -.running,.waiting,td.building { - color: #000; - background-color: #fd3; - border-color: #C5C56D; -} - -.paused { - color: #FFFFFF; - background-color: #8080FF; - border-color: #dddddd; -} - -.offline,td.offline { - color: #FFFFFF; - background-color: #777777; - border-color: #dddddd; -} - - -.start { - border-bottom-left-radius: 10px; - -webkit-border-bottom-left-radius: 10px; - -moz-border-radius-bottomleft: 10px; - border-bottom-right-radius: 10px; - -webkit-border-bottom-right-radius: 10px; - -moz-border-radius-bottomright: 10px; -} - -.notstarted { - border-width: 1px; - border-style: solid; - border-color: #aaa; - background-color: #fff; -} - -.closed { - background-color: #ff0000; -} - -.closed .large { - font-size: 1.5em; - font-weight: bolder; -} - -td.Project a:hover,td.start a:hover { - color: #000; -} - -.mini-box { - text-align: center; - height: 20px; - padding: 0 2px; - line-height: 0; - white-space: nowrap; -} - -.mini-box a { - border-radius: 0; - -webkit-border-radius: 0; - -moz-border-radius: 0; - display: block; - width: 100%; - height: 20px; - line-height: 20px; - margin-top: -30px; -} - -.mini-closed { - -box-sizing: border-box; - -webkit-box-sizing: border-box; - border: 4px solid red; -} - -/* grid styles */ -table.Grid { - border-collapse: collapse; -} - -table.Grid tr td { - padding: 0.2em; - margin: 0px; - text-align: center; -} - -table.Grid tr td.title { - font-size: 90%; - border-right: 1px gray solid; - border-bottom: 1px gray solid; -} - -table.Grid tr td.sourcestamp { - font-size: 90%; -} - -table.Grid tr td.builder { - text-align: right; - font-size: 90%; -} - -table.Grid tr td.build { - border: 1px gray solid; -} - -/* column container */ -div.column { - margin: 0 2em 2em 0; - float: left; -} - -/* info tables */ -table.info { - border-spacing: 1px; -} - -table.info td { - padding: 0.1em 1em 0.1em 1em; - text-align: center; -} - -table.info th { - padding: 0.2em 1.5em 0.2em 1.5em; - text-align: center; -} - -table.info td.left { - text-align: left -} - -.alt { - background-color: #f6f6f6; -} - -li { - padding: 0.1em 1em 0.1em 1em; -} - -.result { - padding: 0.3em 1em 0.3em 1em; -} - -/* log view */ -.log * { - vlink: #800080; - font-family: "Courier New", courier, monotype, monospace; -} - -span.stdout { - color: black; -} - -span.stderr { - color: red; -} - -span.header { - color: blue; -} - -/* revision & email */ -.revision .full { - display: none; -} - -.user .email { - display: none; -} - -pre { - white-space: pre-wrap; -} - -/* change comments (use regular colors here) */ -pre.comments>a:link,pre.comments>a:visited { - color: blue; -} - -pre.comments>a:active { - color: purple; -} - -form.command_forcebuild { - border-top: 1px solid black; - padding: .5em; - margin: .5em; -} - -form.command_forcebuild > .row { - border-top: 1px dotted gray; - padding: .5em 0; -} - -form.command_forcebuild .force-textarea > .label { - display: block; -} - -form.command_forcebuild .force-nested > .label { - font-weight: bold; - display: list-item; -} - -form.command_forcebuild .force-any .force-text { - display: inline; -} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.ico b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.ico Binary files differdeleted file mode 100644 index b0b0845d..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/favicon.ico +++ /dev/null diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt deleted file mode 100644 index 7b5fc8da..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/robots.txt +++ /dev/null @@ -1,11 +0,0 @@ -User-agent: * -Disallow: /waterfall -Disallow: /builders -Disallow: /changes -Disallow: /buildslaves -Disallow: /schedulers -Disallow: /one_line_per_build -Disallow: /builders -Disallow: /grid -Disallow: /tgrid -Disallow: /json diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt deleted file mode 100644 index 78201578..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/files/templates_readme.txt +++ /dev/null @@ -1,12 +0,0 @@ -This is the directory to place customized templates for webstatus. - -You can find the sources for the templates used in: -buildbot/status/web/templates - -You can copy any of those files to this directory, make changes, and buildbot will automatically -use your modified templates. - -Also of note is that you will not need to restart/reconfig buildbot master to have these changes take effect. - -The syntax of the templates is Jinja2: -http://jinja.pocoo.org/
\ No newline at end of file diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py deleted file mode 100644 index dc4fbd62..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/grid.py +++ /dev/null @@ -1,341 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -from twisted.internet import defer -from buildbot.status.web.base import HtmlResource -from buildbot.status.web.base import build_get_class, path_to_builder, path_to_build -from buildbot.sourcestamp import SourceStamp - -class ANYBRANCH: pass # a flag value, used below - -class GridStatusMixin(object): - def getPageTitle(self, request): - status = self.getStatus(request) - p = status.getTitle() - if p: - return "BuildBot: %s" % p - else: - return "BuildBot" - - # 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 build_cxt(self, request, build): - if not build: - return {} - - 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() - - cxt = {} - cxt['name'] = name - cxt['got_revision'] = build.getProperty("got_revision") - cxt['DEST'] = build.getProperty("DEST") - cxt['url'] = path_to_build(request, build) - cxt['text'] = text - cxt['class'] = build_get_class(build) - - if build.getProperty("repourl_poky"): - if build.getProperty("repourl_poky") == "git://git.yoctoproject.org/poky": - cxt['repository'] = "poky" - cxt['cgiturl'] = "http://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?h=" - elif "git://git.yoctoproject.org/poky-contrib" in build.getProperty("repourl_poky"): - cxt['repository'] = "poky-contrib" - cxt['cgiturl'] = "http://git.yoctoproject.org/cgit/cgit.cgi/poky-contrib/commit/?h=" - else: - cxt['repository'] = build.getProperty("repourl_poky") - - if build.getProperty("branch_poky"): - if build.getProperty("branch_poky") == "stage/master_under_test": - cxt['branchshortname']="mut" - else: - cxt['branchshortname']=build.getProperty("branch_poky") - cxt['branch'] = build.getProperty("branch_poky") - if 'cgiturl' in cxt and 'got_revision' in cxt and cxt['cgiturl'] is not None and cxt['got_revision'] is not None: - cxt['cgiturl'] = cxt['cgiturl'] + build.getProperty("branch_poky") + "&id=" + cxt['got_revision'] - if build.getProperty("custom_release_name_nightly"): - cxt['release_name'] = build.getProperty("custom_release_name_nightly") - else: - cxt['commit_desc'] = build.getProperty("commit-description") - - return cxt - - @defer.inlineCallbacks - def builder_cxt(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" - - n_pending = len((yield builder.getPendingBuildRequestStatuses())) - - cxt = { 'url': path_to_builder(request, builder), - 'name': builder.getName(), - 'state': state, - 'n_pending': n_pending } - - defer.returnValue(cxt) - - def getSourceStampKey(self, sourcestamps): - """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. - """ - # TODO: Maybe order sourcestamps in key by codebases names? - return tuple([(ss.branch, ss.revision, ss.patch) for ss in sourcestamps]) - - def clearRecentBuildsCache(self): - self.__recentBuildsCache__ = {} - - def getRecentBuilds(self, builder, numBuilds, branch): - cache = getattr(self, '__recentBuildsCache__', {}) - key = (builder.getName(), branch, numBuilds) - try: - return cache[key] - except KeyError: - # cache miss, get the value and store it in the cache - result = [b for b in self.__getRecentBuilds(builder, numBuilds, branch)] - cache[key] = result - return result - - def __getRecentBuilds(self, builder, numBuilds, branch): - """ - get a list of most recent builds on given builder - """ - build = builder.getBuild(-1) - num = 0 - while build and num < numBuilds: - start = build.getTimes()[0] - #TODO: support multiple sourcestamps - ss = build.getSourceStamps(absolute=True)[0] - - okay_build = True - - # skip un-started builds - if not start: - okay_build = False - - # skip non-matching branches - if branch != ANYBRANCH and ss.branch != branch: - okay_build = False - - if okay_build: - num += 1 - yield build - - build = build.getPreviousBuild() - return - - 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 - for build in self.getRecentBuilds(builder, numBuilds, branch): - ss = build.getSourceStamps(absolute=True) - key = self.getSourceStampKey(ss) - start = min(x for x in build.getTimes() if x is not None) - if key not in sourcestamps or sourcestamps[key][1] > start: - sourcestamps[key] = (ss, start) - - # now sort those and take the NUMBUILDS most recent - sourcestamps = sorted(sourcestamps.itervalues(), key = lambda stamp: stamp[1]) - sourcestamps = [stamp[0] for stamp in sourcestamps][-numBuilds:] - - return sourcestamps - -class GridStatusResource(HtmlResource, GridStatusMixin): - # TODO: docs - status = None - changemaster = None - - @defer.inlineCallbacks - def content(self, request, cxt): - """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) - - cxt['refresh'] = self.get_reload_time(request) - - cxt.update({'categories': categories, - 'branch': branch, - 'ANYBRANCH': ANYBRANCH, - 'stamps': [map(SourceStamp.asDict, sstamp) for sstamp in stamps], - }) - sortedBuilderNames = sorted(status.getBuilderNames()) - - cxt['builders'] = [] - cxt['build_triggers'] = build_triggers = [] - cxt['range'] = range(len(stamps)) - - # For each sstamp we want to know the name of the builder which - # triggered the builds and the buildid of that builder. We'll keep - # that in a list of dicts which align with the stamps objects list. - for _ in range(len(stamps)): - build_triggers.append({'builder': '', 'id': ''}) - - for bn in sortedBuilderNames: - builds = [None] * len(stamps) - - builder = status.getBuilder(bn) - if categories and builder.category not in categories: - continue - - for build in self.getRecentBuilds(builder, numBuilds, branch): - ss = build.getSourceStamps(absolute=True) - key = self.getSourceStampKey(ss) - - for i, sstamp in enumerate(stamps): - if key == self.getSourceStampKey(sstamp) and builds[i] is None: - builds[i] = build - if build_triggers[i].get('builder', None) != 'nightly': - build_triggers[i]['builder'] = bn - build_triggers[i]['id'] = str(build.getNumber()) - - b = yield self.builder_cxt(request, builder) - - b['builds'] = [] - for build in builds: - b['builds'].append(self.build_cxt(request, build)) - - cxt['builders'].append(b) - - self.clearRecentBuildsCache() - template = request.site.buildbot_service.templates.get_template("grid.html") - defer.returnValue(template.render(**cxt)) - - -class TransposedGridStatusResource(HtmlResource, GridStatusMixin): - # TODO: docs - status = None - changemaster = None - default_rev_order = "desc" - - @defer.inlineCallbacks - def content(self, request, cxt): - """This method builds the transposed grid display. - That is, build hosts across the top, build 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 - - rev_order = request.args.get("rev_order", [self.default_rev_order])[0] - if rev_order not in ["asc", "desc"]: - rev_order = self.default_rev_order - - cxt['refresh'] = self.get_reload_time(request) - - # and the data we want to render - status = self.getStatus(request) - stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch) - - cxt.update({'categories': categories, - 'branch': branch, - 'ANYBRANCH': ANYBRANCH, - 'stamps': [map(SourceStamp.asDict, sstamp) for sstamp in stamps], - }) - - sortedBuilderNames = sorted(status.getBuilderNames()) - - cxt['sorted_builder_names'] = sortedBuilderNames - cxt['builder_builds'] = builder_builds = [] - cxt['builders'] = builders = [] - cxt['build_triggers'] = build_triggers = [] - cxt['range'] = range(len(stamps)) - if rev_order == "desc": - cxt['range'].reverse() - - # For each sstamp we want to know the name of the builder which - # triggered the builds and the buildid of that builder. We'll keep - # that in a list of dicts which align with the stamps objects list. - for _ in range(len(stamps)): - build_triggers.append({'builder': '', 'id': ''}) - - for bn in sortedBuilderNames: - builds = [None] * len(stamps) - - builder = status.getBuilder(bn) - if categories and builder.category not in categories: - continue - - for build in self.getRecentBuilds(builder, numBuilds, branch): - #TODO: support multiple sourcestamps - ss = build.getSourceStamps(absolute=True) - key = self.getSourceStampKey(ss) - - for i, sstamp in enumerate(stamps): - if key == self.getSourceStampKey(sstamp) and builds[i] is None: - builds[i] = build - # At this point we know that there's a build for the sstamp by this builder - # update the corresponding dict in the build_triggers list with the builder - # name and buildid unless 'nightly' is already set as the builder name. - if build_triggers[i].get('builder', None) != 'nightly': - build_triggers[i]['builder'] = bn - build_triggers[i]['id'] = str(build.getNumber()) - - b = yield self.builder_cxt(request, builder) - builders.append(b) - - builder_builds.append(map(lambda b: self.build_cxt(request, b), builds)) - - self.clearRecentBuildsCache() - template = request.site.buildbot_service.templates.get_template('grid_transposed.html') - defer.returnValue(template.render(**cxt)) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py deleted file mode 100644 index 00bcb6e3..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# test
\ No newline at end of file diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py deleted file mode 100644 index 3980e8f9..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/base.py +++ /dev/null @@ -1,80 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -# code inspired/copied from contrib/github_buildbot -# and inspired from code from the Chromium project -# otherwise, Andrew Melo <andrew.melo@gmail.com> wrote the rest -# but "the rest" is pretty minimal - -from buildbot.util import json - -def getChanges(request, options=None): - """ - Consumes a naive build notification (the default for now) - basically, set POST variables to match commit object parameters: - revision, revlink, comments, branch, who, files, links - - files, links and properties will be de-json'd, the rest are interpreted as strings - """ - - def firstOrNothing( value ): - """ - Small helper function to return the first value (if value is a list) - or return the whole thing otherwise - """ - if ( type(value) == type([])): - return value[0] - else: - return value - - args = request.args - - # first, convert files, links and properties - files = None - if args.get('files'): - files = json.loads( args.get('files')[0] ) - else: - files = [] - - properties = None - if args.get('properties'): - properties = json.loads( args.get('properties')[0] ) - else: - properties = {} - - revision = firstOrNothing(args.get('revision')) - when = firstOrNothing(args.get('when')) - if when is not None: - when = float(when) - author = firstOrNothing(args.get('author')) - if not author: - author = firstOrNothing(args.get('who')) - comments = firstOrNothing(args.get('comments')) - isdir = firstOrNothing(args.get('isdir',0)) - branch = firstOrNothing(args.get('branch')) - category = firstOrNothing(args.get('category')) - revlink = firstOrNothing(args.get('revlink')) - repository = firstOrNothing(args.get('repository')) - project = firstOrNothing(args.get('project')) - - chdict = dict(author=author, files=files, comments=comments, - isdir=isdir, revision=revision, when=when, - branch=branch, category=category, revlink=revlink, - properties=properties, repository=repository, - project=project) - return ([ chdict ], None) - - - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py deleted file mode 100644 index 2ff05f12..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/github.py +++ /dev/null @@ -1,147 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -#!/usr/bin/env python -""" -github_buildbot.py is based on git_buildbot.py - -github_buildbot.py will determine the repository information from the JSON -HTTP POST it receives from github.com and build the appropriate repository. -If your github repository is private, you must add a ssh key to the github -repository for the user who initiated the build on the buildslave. - -""" - -import re -import datetime -from twisted.python import log -import calendar - -try: - import json - assert json -except ImportError: - import simplejson as json - -# python is silly about how it handles timezones -class fixedOffset(datetime.tzinfo): - """ - fixed offset timezone - """ - def __init__(self, minutes, hours, offsetSign = 1): - self.minutes = int(minutes) * offsetSign - self.hours = int(hours) * offsetSign - self.offset = datetime.timedelta(minutes = self.minutes, - hours = self.hours) - - def utcoffset(self, dt): - return self.offset - - def dst(self, dt): - return datetime.timedelta(0) - -def convertTime(myTestTimestamp): - #"1970-01-01T00:00:00+00:00" - matcher = re.compile(r'(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)([-+])(\d\d):(\d\d)') - result = matcher.match(myTestTimestamp) - (year, month, day, hour, minute, second, offsetsign, houroffset, minoffset) = \ - result.groups() - if offsetsign == '+': - offsetsign = 1 - else: - offsetsign = -1 - - offsetTimezone = fixedOffset( minoffset, houroffset, offsetsign ) - myDatetime = datetime.datetime( int(year), - int(month), - int(day), - int(hour), - int(minute), - int(second), - 0, - offsetTimezone) - return calendar.timegm( myDatetime.utctimetuple() ) - -def getChanges(request, options = None): - """ - Reponds only to POST events and starts the build process - - :arguments: - request - the http request object - """ - payload = json.loads(request.args['payload'][0]) - user = payload['repository']['owner']['name'] - repo = payload['repository']['name'] - repo_url = payload['repository']['url'] - project = request.args.get('project', None) - if project: - project = project[0] - elif project is None: - project = '' - # This field is unused: - #private = payload['repository']['private'] - changes = process_change(payload, user, repo, repo_url, project) - log.msg("Received %s changes from github" % len(changes)) - return (changes, 'git') - -def process_change(payload, user, repo, repo_url, project): - """ - Consumes the JSON as a python object and actually starts the build. - - :arguments: - payload - Python Object that represents the JSON sent by GitHub Service - Hook. - """ - changes = [] - newrev = payload['after'] - refname = payload['ref'] - - # We only care about regular heads, i.e. branches - match = re.match(r"^refs\/heads\/(.+)$", refname) - if not match: - log.msg("Ignoring refname `%s': Not a branch" % refname) - return [] - - branch = match.group(1) - if re.match(r"^0*$", newrev): - log.msg("Branch `%s' deleted, ignoring" % branch) - return [] - else: - for commit in payload['commits']: - files = [] - if 'added' in commit: - files.extend(commit['added']) - if 'modified' in commit: - files.extend(commit['modified']) - if 'removed' in commit: - files.extend(commit['removed']) - when = convertTime( commit['timestamp']) - log.msg("New revision: %s" % commit['id'][:8]) - chdict = dict( - who = commit['author']['name'] - + " <" + commit['author']['email'] + ">", - files = files, - comments = commit['message'], - revision = commit['id'], - when = when, - branch = branch, - revlink = commit['url'], - repository = repo_url, - project = project) - changes.append(chdict) - return changes - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py deleted file mode 100644 index f40cf174..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/googlecode.py +++ /dev/null @@ -1,87 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2011, Louis Opter <kalessin@kalessin.fr> - -# Quite inspired from the github hook. - -import hmac -from twisted.python import log -from buildbot.util import json - -class GoogleCodeAuthFailed(Exception): - pass - -class Payload(object): - def __init__(self, headers, body, branch): - self._auth_code = headers['Google-Code-Project-Hosting-Hook-Hmac'] - self._body = body # we need to save it if we want to authenticate it - self._branch = branch - - payload = json.loads(body) - self.project = payload['project_name'] - self.repository = payload['repository_path'] - self.revisions = payload['revisions'] - self.revision_count = payload['revision_count'] - - def authenticate(self, secret_key): - m = hmac.new(secret_key) - m.update(self._body) - digest = m.hexdigest() - return digest == self._auth_code - - def changes(self): - changes = [] - - for r in self.revisions: - files = set() - files.update(r['added']) - files.update(r['modified']) - files.update(r['removed']) - changes.append(dict( - author=r['author'], - files=list(files), - comments=r['message'], - revision=r['revision'], - when=r['timestamp'], - # Let's hope Google add the branch one day: - branch=r.get('branch', self._branch), - revlink=r['url'], - repository=self.repository, - project=self.project - )) - - return changes - -def getChanges(request, options=None): - headers = request.received_headers - body = request.content.getvalue() - - # Instantiate a Payload object: this will parse the body, get the - # authentication code from the headers and remember the branch picked - # up by the user (Google Code doesn't send on which branch the changes - # were made) - payload = Payload(headers, body, options.get('branch', 'default')) - - if 'secret_key' in options: - if not payload.authenticate(options['secret_key']): - raise GoogleCodeAuthFailed() - else: - log.msg("Missing secret_key in the Google Code WebHook options: " - "cannot authenticate the request!") - - log.msg('Received %d changes from Google Code' % - (payload.revision_count,)) - changes = payload.changes() - - return changes, 'Google Code' diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py deleted file mode 100644 index 1ac29a4f..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/hooks/poller.py +++ /dev/null @@ -1,54 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -# This change hook allows GitHub or a hand crafted curl inovcation to "knock on -# the door" and trigger a change source to poll. - -from buildbot.changes.base import PollingChangeSource - - -def getChanges(req, options=None): - change_svc = req.site.buildbot_service.master.change_svc - poll_all = not "poller" in req.args - - allow_all = True - allowed = [] - if isinstance(options, dict) and "allowed" in options: - allow_all = False - allowed = options["allowed"] - - pollers = [] - - for source in change_svc: - if not isinstance(source, PollingChangeSource): - continue - if not hasattr(source, "name"): - continue - if not poll_all and not source.name in req.args['poller']: - continue - if not allow_all and not source.name in allowed: - continue - pollers.append(source) - - if not poll_all: - missing = set(req.args['poller']) - set(s.name for s in pollers) - if missing: - raise ValueError("Could not find pollers: %s" % ",".join(missing)) - - for p in pollers: - p.doPoll() - - return [], None - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py deleted file mode 100644 index d7da8111..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/logs.py +++ /dev/null @@ -1,177 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from zope.interface import implements -from twisted.python import components -from twisted.spread import pb -from twisted.web import server -from twisted.web.resource import Resource, NoResource - -from buildbot import interfaces -from buildbot.status import logfile -from buildbot.status.web.base import IHTMLLog, HtmlResource, path_to_root - -class ChunkConsumer: - implements(interfaces.IStatusLogConsumer) - - def __init__(self, original, textlog): - self.original = original - self.textlog = textlog - def registerProducer(self, producer, streaming): - self.producer = producer - self.original.registerProducer(producer, streaming) - def unregisterProducer(self): - self.original.unregisterProducer() - def writeChunk(self, chunk): - formatted = self.textlog.content([chunk]) - try: - if isinstance(formatted, unicode): - formatted = formatted.encode('utf-8') - self.original.write(formatted) - except pb.DeadReferenceError: - self.producing.stopProducing() - def finish(self): - self.textlog.finished() - - -# /builders/$builder/builds/$buildnum/steps/$stepname/logs/$logname -class TextLog(Resource): - # a new instance of this Resource is created for each client who views - # it, so we can afford to track the request in the Resource. - implements(IHTMLLog) - - asText = False - subscribed = False - - def __init__(self, original): - Resource.__init__(self) - self.original = original - - def getChild(self, path, req): - if path == "text": - self.asText = True - return self - return Resource.getChild(self, path, req) - - def content(self, entries): - html_entries = [] - text_data = '' - for type, entry in entries: - if type >= len(logfile.ChunkTypes) or type < 0: - # non-std channel, don't display - continue - - is_header = type == logfile.HEADER - - if not self.asText: - # jinja only works with unicode, or pure ascii, so assume utf-8 in logs - if not isinstance(entry, unicode): - entry = unicode(entry, 'utf-8', 'replace') - html_entries.append(dict(type = logfile.ChunkTypes[type], - text = entry, - is_header = is_header)) - elif not is_header: - text_data += entry - - if self.asText: - return text_data - else: - return self.template.module.chunks(html_entries) - - def render_HEAD(self, req): - self._setContentType(req) - - # vague approximation, ignores markup - req.setHeader("content-length", self.original.length) - return '' - - def render_GET(self, req): - self._setContentType(req) - self.req = req - - if self.original.isFinished(): - req.setHeader("Cache-Control", "max-age=604800") - else: - req.setHeader("Cache-Control", "no-cache") - - if not self.asText: - self.template = req.site.buildbot_service.templates.get_template("logs.html") - - data = self.template.module.page_header( - pageTitle = "Log File contents", - texturl = req.childLink("text"), - path_to_root = path_to_root(req)) - data = data.encode('utf-8') - req.write(data) - - self.original.subscribeConsumer(ChunkConsumer(req, self)) - return server.NOT_DONE_YET - - def _setContentType(self, req): - if self.asText: - req.setHeader("content-type", "text/plain; charset=utf-8") - else: - req.setHeader("content-type", "text/html; charset=utf-8") - - def finished(self): - if not self.req: - return - try: - if not self.asText: - data = self.template.module.page_footer() - data = data.encode('utf-8') - self.req.write(data) - self.req.finish() - except pb.DeadReferenceError: - pass - # break the cycle, the Request's .notifications list includes the - # Deferred (from req.notifyFinish) that's pointing at us. - self.req = None - - # release template - self.template = None - -components.registerAdapter(TextLog, interfaces.IStatusLog, IHTMLLog) - - -class HTMLLog(Resource): - implements(IHTMLLog) - - def __init__(self, original): - Resource.__init__(self) - self.original = original - - def render(self, request): - request.setHeader("content-type", "text/html") - return self.original.html - -components.registerAdapter(HTMLLog, logfile.HTMLLogFile, IHTMLLog) - - -class LogsResource(HtmlResource): - addSlash = True - - def __init__(self, step_status): - HtmlResource.__init__(self) - self.step_status = step_status - - def getChild(self, path, req): - for log in self.step_status.getLogs(): - if path == log.getName(): - if log.hasContents(): - return IHTMLLog(interfaces.IStatusLog(log)) - return NoResource("Empty Log '%s'" % path) - return HtmlResource.getChild(self, path, req) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py deleted file mode 100644 index 1bfd647c..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/olpb.py +++ /dev/null @@ -1,118 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from buildbot.status.web.base import HtmlResource, BuildLineMixin, map_branches - -# /one_line_per_build -# accepts builder=, branch=, numbuilds=, reload= -class OneLinePerBuild(HtmlResource, BuildLineMixin): - """This shows one line per build, combining all builders together. Useful - query arguments: - - numbuilds=: how many lines to display - builder=: show only builds for this builder. Multiple builder= arguments - can be used to see builds from any builder in the set. - reload=: reload the page after this many seconds - """ - - pageTitle = "Recent Builds" - - def __init__(self, numbuilds=20): - HtmlResource.__init__(self) - self.numbuilds = numbuilds - - def getChild(self, path, req): - status = self.getStatus(req) - builder = status.getBuilder(path) - return OneLinePerBuildOneBuilder(builder, numbuilds=self.numbuilds) - - 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 content(self, req, cxt): - status = self.getStatus(req) - numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) - builders = req.args.get("builder", []) - branches = [b for b in req.args.get("branch", []) if b] - - g = status.generateFinishedBuilds(builders, map_branches(branches), - numbuilds, max_search=numbuilds) - - cxt['refresh'] = self.get_reload_time(req) - cxt['num_builds'] = numbuilds - cxt['branches'] = branches - cxt['builders'] = builders - - builds = cxt['builds'] = [] - for build in g: - builds.append(self.get_line_values(req, build)) - - cxt['authz'] = self.getAuthz(req) - - # get information on the builders - mostly just a count - building = 0 - online = 0 - for bn in builders: - builder = status.getBuilder(bn) - builder_status = builder.getState()[0] - if builder_status == "building": - building += 1 - online += 1 - elif builder_status != "offline": - online += 1 - - cxt['num_online'] = online - cxt['num_building'] = building - - template = req.site.buildbot_service.templates.get_template('onelineperbuild.html') - return template.render(**cxt) - - - -# /one_line_per_build/$BUILDERNAME -# accepts branch=, numbuilds= - -class OneLinePerBuildOneBuilder(HtmlResource, BuildLineMixin): - def __init__(self, builder, numbuilds=20): - HtmlResource.__init__(self) - self.builder = builder - self.builder_name = builder.getName() - self.numbuilds = numbuilds - self.pageTitle = "Recent Builds of %s" % self.builder_name - - def content(self, req, cxt): - numbuilds = int(req.args.get("numbuilds", [self.numbuilds])[0]) - branches = [b for b in req.args.get("branch", []) if b] - - # walk backwards through all builds of a single builder - g = self.builder.generateFinishedBuilds(map_branches(branches), - numbuilds) - - cxt['builds'] = map(lambda b: self.get_line_values(req, b), g) - cxt.update(dict(num_builds=numbuilds, - builder_name=self.builder_name, - branches=branches)) - - template = req.site.buildbot_service.templates.get_template('onelineperbuildonebuilder.html') - return template.render(**cxt) - - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py deleted file mode 100644 index 01a926ed..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/root.py +++ /dev/null @@ -1,57 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -from twisted.web.util import redirectTo -from twisted.internet import defer - -from buildbot.status.web.base import HtmlResource, path_to_authzfail -from buildbot.util.eventual import eventually - -class RootPage(HtmlResource): - pageTitle = "Buildbot" - - @defer.inlineCallbacks - def content(self, request, cxt): - status = self.getStatus(request) - - res = yield self.getAuthz(request).actionAllowed("cleanShutdown", - request) - - if request.path == '/shutdown': - if res: - eventually(status.cleanShutdown) - defer.returnValue(redirectTo("/", request)) - return - else: - defer.returnValue( - redirectTo(path_to_authzfail(request), request)) - return - elif request.path == '/cancel_shutdown': - if res: - eventually(status.cancelCleanShutdown) - defer.returnValue(redirectTo("/", request)) - return - else: - defer.returnValue( - redirectTo(path_to_authzfail(request), request)) - return - - cxt.update( - shutting_down = status.shuttingDown, - shutdown_url = request.childLink("shutdown"), - cancel_shutdown_url = request.childLink("cancel_shutdown"), - ) - template = request.site.buildbot_service.templates.get_template("root.html") - defer.returnValue(template.render(**cxt)) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py deleted file mode 100644 index 35c0ad24..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/session.py +++ /dev/null @@ -1,121 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members -# -# Insipration, and some code, from: -# :copyright: (c) 2011 by the Werkzeug Team, see Werkzeug's AUTHORS for more -# details. - -try: - from hashlib import sha1 - sha1 = sha1 # make pyflakes happy -except ImportError: - from sha import new as sha1 -from time import time -from random import random -from datetime import datetime, timedelta -import os -def _urandom(): - if hasattr(os, 'urandom'): - return os.urandom(30) - return random() - -def generate_cookie(): - return sha1('%s%s' % (time(), _urandom())).hexdigest() - - -class Session(object): - """I'm a user's session. Contains information about a user's session - a user can have several session - a session is associated with a cookie - """ - user = "" - infos = {} - def __init__(self, user, infos): - self.user = user - self.infos = infos - self.renew() - - def renew(self): - # one day expiration. hardcoded for now... - self.expiration = datetime.now()+ timedelta(1) - return self.expiration - - def expired(self): - return datetime.now() > self.expiration - - def userInfosHTML(self): - return ('%(fullName)s [<a href="mailto:%(email)s">%(email)s</a>]' % - (self.infos)) - - def getExpiration(self): - delim = '-' - d = self.expiration.utctimetuple() - return '%s, %02d%s%s%s%s %02d:%02d:%02d GMT' % ( - ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')[d.tm_wday], - d.tm_mday, delim, - ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec')[d.tm_mon - 1], - delim, str(d.tm_year), d.tm_hour, d.tm_min, d.tm_sec - ) - -class SessionManager(object): - """I'm the session manager. Holding the current sessions - managing cookies, and their expiration - - KISS version for the moment: - - The sessions are stored in RAM so that you have to relogin after buildbot - reboot - - Old sessions are searched at every connection, which is not very good for - scaling - - """ - - # borg pattern (similar to singleton) not too loose sessions with reconfig - __shared_state = dict(sessions={},users={}) - - def __init__(self): - self.__dict__ = self.__shared_state - - def new(self, user, infos): - cookie = generate_cookie() - user = infos["userName"] - self.users[user] = self.sessions[cookie] = s = Session(user, infos) - return cookie, s - - def gc(self): - """remove old cookies""" - expired = [] - for cookie in self.sessions: - s = self.sessions[cookie] - if s.expired(): - expired.append(cookie) - for cookie in expired: - del self.sessions[cookie] - - def get(self, cookie): - self.gc() - if cookie in self.sessions: - return self.sessions[cookie] - return None - - def remove(self, cookie): - if cookie in self.sessions: - del self.sessions[cookie] - - def getUser(self, user): - return self.users.get(user) - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py deleted file mode 100644 index 323b5463..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/slaves.py +++ /dev/null @@ -1,203 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -import time, urllib -from twisted.web import html -from twisted.web.util import Redirect -from twisted.web.resource import NoResource -from twisted.internet import defer - -from buildbot.status.web.base import HtmlResource, abbreviate_age, \ - BuildLineMixin, ActionResource, path_to_slave, path_to_authzfail -from buildbot import util - -class ShutdownActionResource(ActionResource): - - def __init__(self, slave): - self.slave = slave - self.action = "gracefulShutdown" - - @defer.inlineCallbacks - def performAction(self, request): - res = yield self.getAuthz(request).actionAllowed(self.action, - request, - self.slave) - - url = None - if res: - self.slave.setGraceful(True) - url = path_to_slave(request, self.slave) - else: - url = path_to_authzfail(request) - defer.returnValue(url) - -class PauseActionResource(ActionResource): - - def __init__(self, slave, state): - self.slave = slave - self.action = "pauseSlave" - self.state = state - - @defer.inlineCallbacks - def performAction(self, request): - res = yield self.getAuthz(request).actionAllowed(self.action, - request, - self.slave) - - url = None - if res: - self.slave.setPaused(self.state) - url = path_to_slave(request, self.slave) - else: - url = path_to_authzfail(request) - defer.returnValue(url) - -# /buildslaves/$slavename -class OneBuildSlaveResource(HtmlResource, BuildLineMixin): - addSlash = False - def __init__(self, slavename): - HtmlResource.__init__(self) - self.slavename = slavename - - def getPageTitle(self, req): - return "Buildbot: %s" % self.slavename - - def getChild(self, path, req): - s = self.getStatus(req) - slave = s.getSlave(self.slavename) - if path == "shutdown": - return ShutdownActionResource(slave) - if path == "pause" or path == "unpause": - return PauseActionResource(slave, path == "pause") - return Redirect(path_to_slave(req, slave)) - - def content(self, request, ctx): - s = self.getStatus(request) - slave = s.getSlave(self.slavename) - - my_builders = [] - for bname in s.getBuilderNames(): - b = s.getBuilder(bname) - for bs in b.getSlaves(): - if bs.getName() == self.slavename: - my_builders.append(b) - - # Current builds - current_builds = [] - for b in my_builders: - for cb in b.getCurrentBuilds(): - if cb.getSlavename() == self.slavename: - current_builds.append(self.get_line_values(request, cb)) - - try: - max_builds = int(request.args.get('numbuilds')[0]) - except: - max_builds = 10 - - recent_builds = [] - n = 0 - for rb in s.generateFinishedBuilds(builders=[b.getName() for b in my_builders]): - if rb.getSlavename() == self.slavename: - n += 1 - recent_builds.append(self.get_line_values(request, rb)) - if n > max_builds: - break - - # connects over the last hour - slave = s.getSlave(self.slavename) - connect_count = slave.getConnectCount() - - if slave.isPaused(): - pause_url = request.childLink("unpause") - else: - pause_url = request.childLink("pause") - - ctx.update(dict(slave=slave, - slavename = self.slavename, - current = current_builds, - recent = recent_builds, - shutdown_url = request.childLink("shutdown"), - pause_url = pause_url, - authz = self.getAuthz(request), - this_url = "../../../" + path_to_slave(request, slave), - access_uri = slave.getAccessURI()), - admin = unicode(slave.getAdmin() or '', 'utf-8'), - host = unicode(slave.getHost() or '', 'utf-8'), - slave_version = slave.getVersion(), - show_builder_column = True, - connect_count = connect_count) - template = request.site.buildbot_service.templates.get_template("buildslave.html") - data = template.render(**ctx) - return data - -# /buildslaves -class BuildSlavesResource(HtmlResource): - pageTitle = "BuildSlaves" - addSlash = True - - def content(self, request, ctx): - s = self.getStatus(request) - - #?no_builders=1 disables build column - show_builder_column = not (request.args.get('no_builders', '0')[0])=='1' - ctx['show_builder_column'] = show_builder_column - - used_by_builder = {} - for bname in s.getBuilderNames(): - b = s.getBuilder(bname) - for bs in b.getSlaves(): - slavename = bs.getName() - if slavename not in used_by_builder: - used_by_builder[slavename] = [] - used_by_builder[slavename].append(bname) - - slaves = ctx['slaves'] = [] - for name in util.naturalSort(s.getSlaveNames()): - info = {} - slaves.append(info) - slave = s.getSlave(name) - slave_status = s.botmaster.slaves[name].slave_status - info['running_builds'] = len(slave_status.getRunningBuilds()) - info['link'] = request.childLink(urllib.quote(name,'')) - info['name'] = name - - if show_builder_column: - info['builders'] = [] - for b in used_by_builder.get(name, []): - info['builders'].append(dict(link=request.childLink("../builders/%s" % b), name=b)) - - info['version'] = slave.getVersion() - info['connected'] = slave.isConnected() - info['connectCount'] = slave.getConnectCount() - info['paused'] = slave.isPaused() - - info['admin'] = unicode(slave.getAdmin() or '', 'utf-8') - last = slave.lastMessageReceived() - if last: - info['last_heard_from_age'] = abbreviate_age(time.time() - last) - info['last_heard_from_time'] = time.strftime("%Y-%b-%d %H:%M:%S", - time.localtime(last)) - - template = request.site.buildbot_service.templates.get_template("buildslaves.html") - data = template.render(**ctx) - return data - - def getChild(self, path, req): - try: - self.getStatus(req).getSlave(path) - return OneBuildSlaveResource(path) - except KeyError: - return NoResource("No such slave '%s'" % html.escape(path)) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py deleted file mode 100644 index a725a35d..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/status_json.py +++ /dev/null @@ -1,741 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Portions Copyright Buildbot Team Members -# Original Copyright (c) 2010 The Chromium Authors. - -"""Simple JSON exporter.""" - -import datetime -import os -import re - -from twisted.internet import defer -from twisted.web import html, resource, server - -from buildbot.status.web.base import HtmlResource -from buildbot.util import json - - -_IS_INT = re.compile('^[-+]?\d+$') - - -FLAGS = """\ - - as_text - - By default, application/json is used. Setting as_text=1 change the type - to text/plain and implicitly sets compact=0 and filter=1. Mainly useful to - look at the result in a web browser. - - compact - - By default, the json data is compact and defaults to 1. For easier to read - indented output, set compact=0. - - select - - By default, most children data is listed. You can do a random selection - of data by using select=<sub-url> multiple times to coagulate data. - "select=" includes the actual url otherwise it is skipped. - - numbuilds - - By default, only in memory cached builds are listed. You can as for more data - by using numbuilds=<number>. - - filter - - Filters out null, false, and empty string, list and dict. This reduce the - amount of useless data sent. - - callback - - Enable uses of JSONP as described in - http://en.wikipedia.org/wiki/JSONP. Note that - Access-Control-Allow-Origin:* is set in the HTTP response header so you - can use this in compatible browsers. -""" - -EXAMPLES = """\ - - /json - - Root node, that *doesn't* mean all the data. Many things (like logs) must - be explicitly queried for performance reasons. - - /json/builders/ - - All builders. - - /json/builders/<A_BUILDER> - - A specific builder as compact text. - - /json/builders/<A_BUILDER>/builds - - All *cached* builds. - - /json/builders/<A_BUILDER>/builds/_all - - All builds. Warning, reads all previous build data. - - /json/builders/<A_BUILDER>/builds/<A_BUILD> - - Where <A_BUILD> is either positive, a build number, or negative, a past - build. - - /json/builders/<A_BUILDER>/builds/-1/source_stamp/changes - - Build changes - - /json/builders/<A_BUILDER>/builds?select=-1&select=-2 - - Two last builds on '<A_BUILDER>' builder. - - /json/builders/<A_BUILDER>/builds?select=-1/source_stamp/changes&select=-2/source_stamp/changes - - Changes of the two last builds on '<A_BUILDER>' builder. - - /json/builders/<A_BUILDER>/slaves - - Slaves associated to this builder. - - /json/builders/<A_BUILDER>?select=&select=slaves - - Builder information plus details information about its slaves. Neat eh? - - /json/slaves/<A_SLAVE> - - A specific slave. - - /json?select=slaves/<A_SLAVE>/&select=project&select=builders/<A_BUILDER>/builds/<A_BUILD> - - A selection of random unrelated stuff as an random example. :) -""" - - -def RequestArg(request, arg, default): - return request.args.get(arg, [default])[0] - - -def RequestArgToBool(request, arg, default): - value = RequestArg(request, arg, default) - if value in (False, True): - return value - value = value.lower() - if value in ('1', 'true'): - return True - if value in ('0', 'false'): - return False - # Ignore value. - return default - - -def FilterOut(data): - """Returns a copy with None, False, "", [], () and {} removed. - Warning: converts tuple to list.""" - if isinstance(data, (list, tuple)): - # Recurse in every items and filter them out. - items = map(FilterOut, data) - if not filter(lambda x: not x in ('', False, None, [], {}, ()), items): - return None - return items - elif isinstance(data, dict): - return dict(filter(lambda x: not x[1] in ('', False, None, [], {}, ()), - [(k, FilterOut(v)) for (k, v) in data.iteritems()])) - else: - return data - - -class JsonResource(resource.Resource): - """Base class for json data.""" - - contentType = "application/json" - cache_seconds = 60 - help = None - pageTitle = None - level = 0 - - def __init__(self, status): - """Adds transparent lazy-child initialization.""" - resource.Resource.__init__(self) - # buildbot.status.builder.Status - self.status = status - - def getChildWithDefault(self, path, request): - """Adds transparent support for url ending with /""" - if path == "" and len(request.postpath) == 0: - return self - if path == 'help' and self.help: - pageTitle = '' - if self.pageTitle: - pageTitle = self.pageTitle + ' help' - return HelpResource(self.help, - pageTitle=pageTitle, - parent_node=self) - # Equivalent to resource.Resource.getChildWithDefault() - if self.children.has_key(path): - return self.children[path] - return self.getChild(path, request) - - def putChild(self, name, res): - """Adds the resource's level for help links generation.""" - - def RecurseFix(res, level): - res.level = level + 1 - for c in res.children.itervalues(): - RecurseFix(c, res.level) - - RecurseFix(res, self.level) - resource.Resource.putChild(self, name, res) - - def render_GET(self, request): - """Renders a HTTP GET at the http request level.""" - d = defer.maybeDeferred(lambda : self.content(request)) - def handle(data): - if isinstance(data, unicode): - data = data.encode("utf-8") - request.setHeader("Access-Control-Allow-Origin", "*") - if RequestArgToBool(request, 'as_text', False): - request.setHeader("content-type", 'text/plain') - else: - request.setHeader("content-type", self.contentType) - request.setHeader("content-disposition", - "attachment; filename=\"%s.json\"" % request.path) - # Make sure we get fresh pages. - if self.cache_seconds: - now = datetime.datetime.utcnow() - expires = now + datetime.timedelta(seconds=self.cache_seconds) - request.setHeader("Expires", - expires.strftime("%a, %d %b %Y %H:%M:%S GMT")) - request.setHeader("Pragma", "no-cache") - return data - d.addCallback(handle) - def ok(data): - request.write(data) - request.finish() - def fail(f): - request.processingFailed(f) - return None # processingFailed will log this for us - d.addCallbacks(ok, fail) - return server.NOT_DONE_YET - - @defer.inlineCallbacks - def content(self, request): - """Renders the json dictionaries.""" - # Supported flags. - select = request.args.get('select') - as_text = RequestArgToBool(request, 'as_text', False) - filter_out = RequestArgToBool(request, 'filter', as_text) - compact = RequestArgToBool(request, 'compact', not as_text) - callback = request.args.get('callback') - - # Implement filtering at global level and every child. - if select is not None: - del request.args['select'] - # Do not render self.asDict()! - data = {} - # Remove superfluous / - select = [s.strip('/') for s in select] - select.sort(cmp=lambda x,y: cmp(x.count('/'), y.count('/')), - reverse=True) - for item in select: - # Start back at root. - node = data - # Implementation similar to twisted.web.resource.getChildForRequest - # but with a hacked up request. - child = self - prepath = request.prepath[:] - postpath = request.postpath[:] - request.postpath = filter(None, item.split('/')) - while request.postpath and not child.isLeaf: - pathElement = request.postpath.pop(0) - node[pathElement] = {} - node = node[pathElement] - request.prepath.append(pathElement) - child = child.getChildWithDefault(pathElement, request) - - # some asDict methods return a Deferred, so handle that - # properly - if hasattr(child, 'asDict'): - child_dict = yield defer.maybeDeferred(lambda : - child.asDict(request)) - else: - child_dict = { - 'error' : 'Not available', - } - node.update(child_dict) - - request.prepath = prepath - request.postpath = postpath - else: - data = yield defer.maybeDeferred(lambda : self.asDict(request)) - - if filter_out: - data = FilterOut(data) - if compact: - data = json.dumps(data, sort_keys=True, separators=(',',':')) - else: - data = json.dumps(data, sort_keys=True, indent=2) - if callback: - # Only accept things that look like identifiers for now - callback = callback[0] - if re.match(r'^[a-zA-Z$][a-zA-Z$0-9.]*$', callback): - data = '%s(%s);' % (callback, data) - defer.returnValue(data) - - @defer.inlineCallbacks - def asDict(self, request): - """Generates the json dictionary. - - By default, renders every childs.""" - if self.children: - data = {} - for name in self.children: - child = self.getChildWithDefault(name, request) - if isinstance(child, JsonResource): - data[name] = yield defer.maybeDeferred(lambda : - child.asDict(request)) - # else silently pass over non-json resources. - defer.returnValue(data) - else: - raise NotImplementedError() - - -def ToHtml(text): - """Convert a string in a wiki-style format into HTML.""" - indent = 0 - in_item = False - output = [] - for line in text.splitlines(False): - match = re.match(r'^( +)\- (.*)$', line) - if match: - if indent < len(match.group(1)): - output.append('<ul>') - indent = len(match.group(1)) - elif indent > len(match.group(1)): - while indent > len(match.group(1)): - output.append('</ul>') - indent -= 2 - if in_item: - # Close previous item - output.append('</li>') - output.append('<li>') - in_item = True - line = match.group(2) - elif indent: - if line.startswith((' ' * indent) + ' '): - # List continuation - line = line.strip() - else: - # List is done - if in_item: - output.append('</li>') - in_item = False - while indent > 0: - output.append('</ul>') - indent -= 2 - - if line.startswith('/'): - if not '?' in line: - line_full = line + '?as_text=1' - else: - line_full = line + '&as_text=1' - output.append('<a href="' + html.escape(line_full) + '">' + - html.escape(line) + '</a>') - else: - output.append(html.escape(line).replace(' ', ' ')) - if not in_item: - output.append('<br>') - - if in_item: - output.append('</li>') - while indent > 0: - output.append('</ul>') - indent -= 2 - return '\n'.join(output) - - -class HelpResource(HtmlResource): - def __init__(self, text, pageTitle, parent_node): - HtmlResource.__init__(self) - self.text = text - self.pageTitle = pageTitle - self.parent_level = parent_node.level - self.parent_children = parent_node.children.keys() - - def content(self, request, cxt): - cxt['level'] = self.parent_level - cxt['text'] = ToHtml(self.text) - cxt['children'] = [ n for n in self.parent_children if n != 'help' ] - cxt['flags'] = ToHtml(FLAGS) - cxt['examples'] = ToHtml(EXAMPLES).replace( - 'href="/json', - 'href="../%sjson' % (self.parent_level * '../')) - - template = request.site.buildbot_service.templates.get_template("jsonhelp.html") - return template.render(**cxt) - -class BuilderPendingBuildsJsonResource(JsonResource): - help = """Describe pending builds for a builder. -""" - pageTitle = 'Builder' - - def __init__(self, status, builder_status): - JsonResource.__init__(self, status) - self.builder_status = builder_status - - def asDict(self, request): - # buildbot.status.builder.BuilderStatus - d = self.builder_status.getPendingBuildRequestStatuses() - def to_dict(statuses): - return defer.gatherResults( - [ b.asDict_async() for b in statuses ]) - d.addCallback(to_dict) - return d - - -class BuilderJsonResource(JsonResource): - help = """Describe a single builder. -""" - pageTitle = 'Builder' - - def __init__(self, status, builder_status): - JsonResource.__init__(self, status) - self.builder_status = builder_status - self.putChild('builds', BuildsJsonResource(status, builder_status)) - self.putChild('slaves', BuilderSlavesJsonResources(status, - builder_status)) - self.putChild( - 'pendingBuilds', - BuilderPendingBuildsJsonResource(status, builder_status)) - - def asDict(self, request): - # buildbot.status.builder.BuilderStatus - return self.builder_status.asDict_async() - - -class BuildersJsonResource(JsonResource): - help = """List of all the builders defined on a master. -""" - pageTitle = 'Builders' - - def __init__(self, status): - JsonResource.__init__(self, status) - for builder_name in self.status.getBuilderNames(): - self.putChild(builder_name, - BuilderJsonResource(status, - status.getBuilder(builder_name))) - - -class BuilderSlavesJsonResources(JsonResource): - help = """Describe the slaves attached to a single builder. -""" - pageTitle = 'BuilderSlaves' - - def __init__(self, status, builder_status): - JsonResource.__init__(self, status) - self.builder_status = builder_status - for slave_name in self.builder_status.slavenames: - self.putChild(slave_name, - SlaveJsonResource(status, - self.status.getSlave(slave_name))) - - -class BuildJsonResource(JsonResource): - help = """Describe a single build. -""" - pageTitle = 'Build' - - def __init__(self, status, build_status): - JsonResource.__init__(self, status) - self.build_status = build_status - # TODO: support multiple sourcestamps - sourcestamp = build_status.getSourceStamps()[0] - self.putChild('source_stamp', - SourceStampJsonResource(status, sourcestamp)) - self.putChild('steps', BuildStepsJsonResource(status, build_status)) - - def asDict(self, request): - return self.build_status.asDict() - - -class AllBuildsJsonResource(JsonResource): - help = """All the builds that were run on a builder. -""" - pageTitle = 'AllBuilds' - - def __init__(self, status, builder_status): - JsonResource.__init__(self, status) - self.builder_status = builder_status - - def getChild(self, path, request): - # Dynamic childs. - if isinstance(path, int) or _IS_INT.match(path): - build_status = self.builder_status.getBuild(int(path)) - if build_status: - return BuildJsonResource(self.status, build_status) - return JsonResource.getChild(self, path, request) - - def asDict(self, request): - results = {} - # If max > buildCacheSize, it'll trash the cache... - cache_size = self.builder_status.master.config.caches['Builds'] - max = int(RequestArg(request, 'max', cache_size)) - for i in range(0, max): - child = self.getChildWithDefault(-i, request) - if not isinstance(child, BuildJsonResource): - continue - results[child.build_status.getNumber()] = child.asDict(request) - return results - - -class BuildsJsonResource(AllBuildsJsonResource): - help = """Builds that were run on a builder. -""" - pageTitle = 'Builds' - - def __init__(self, status, builder_status): - AllBuildsJsonResource.__init__(self, status, builder_status) - self.putChild('_all', AllBuildsJsonResource(status, builder_status)) - - def getChild(self, path, request): - # Transparently redirects to _all if path is not ''. - return self.children['_all'].getChildWithDefault(path, request) - - def asDict(self, request): - # This would load all the pickles and is way too heavy, especially that - # it would trash the cache: - # self.children['builds'].asDict(request) - # TODO(maruel) This list should also need to be cached but how? - builds = dict([ - (int(file), None) - for file in os.listdir(self.builder_status.basedir) - if _IS_INT.match(file) - ]) - return builds - - -class BuildStepJsonResource(JsonResource): - help = """A single build step. -""" - pageTitle = 'BuildStep' - - def __init__(self, status, build_step_status): - # buildbot.status.buildstep.BuildStepStatus - JsonResource.__init__(self, status) - self.build_step_status = build_step_status - # TODO self.putChild('logs', LogsJsonResource()) - - def asDict(self, request): - return self.build_step_status.asDict() - - -class BuildStepsJsonResource(JsonResource): - help = """A list of build steps that occurred during a build. -""" - pageTitle = 'BuildSteps' - - def __init__(self, status, build_status): - JsonResource.__init__(self, status) - self.build_status = build_status - # The build steps are constantly changing until the build is done so - # keep a reference to build_status instead - - def getChild(self, path, request): - # Dynamic childs. - build_step_status = None - if isinstance(path, int) or _IS_INT.match(path): - build_step_status = self.build_status.getSteps()[int(path)] - else: - steps_dict = dict([(step.getName(), step) - for step in self.build_status.getSteps()]) - build_step_status = steps_dict.get(path) - if build_step_status: - # Create it on-demand. - child = BuildStepJsonResource(self.status, build_step_status) - # Cache it. - index = self.build_status.getSteps().index(build_step_status) - self.putChild(str(index), child) - self.putChild(build_step_status.getName(), child) - return child - return JsonResource.getChild(self, path, request) - - def asDict(self, request): - # Only use the number and not the names! - results = {} - index = 0 - for step in self.build_status.getSteps(): - results[index] = step.asDict() - index += 1 - return results - - -class ChangeJsonResource(JsonResource): - help = """Describe a single change that originates from a change source. -""" - pageTitle = 'Change' - - def __init__(self, status, change): - # buildbot.changes.changes.Change - JsonResource.__init__(self, status) - self.change = change - - def asDict(self, request): - return self.change.asDict() - - -class ChangesJsonResource(JsonResource): - help = """List of changes. -""" - pageTitle = 'Changes' - - def __init__(self, status, changes): - JsonResource.__init__(self, status) - for c in changes: - # c.number can be None or clash another change if the change was - # generated inside buildbot or if using multiple pollers. - if c.number is not None and str(c.number) not in self.children: - self.putChild(str(c.number), ChangeJsonResource(status, c)) - else: - # Temporary hack since it creates information exposure. - self.putChild(str(id(c)), ChangeJsonResource(status, c)) - - def asDict(self, request): - """Don't throw an exception when there is no child.""" - if not self.children: - return {} - return JsonResource.asDict(self, request) - - -class ChangeSourcesJsonResource(JsonResource): - help = """Describe a change source. -""" - pageTitle = 'ChangeSources' - - def asDict(self, request): - result = {} - n = 0 - for c in self.status.getChangeSources(): - # buildbot.changes.changes.ChangeMaster - change = {} - change['description'] = c.describe() - result[n] = change - n += 1 - return result - - -class ProjectJsonResource(JsonResource): - help = """Project-wide settings. -""" - pageTitle = 'Project' - - def asDict(self, request): - return self.status.asDict() - - -class SlaveJsonResource(JsonResource): - help = """Describe a slave. -""" - pageTitle = 'Slave' - - def __init__(self, status, slave_status): - JsonResource.__init__(self, status) - self.slave_status = slave_status - self.name = self.slave_status.getName() - self.builders = None - - def getBuilders(self): - if self.builders is None: - # Figure out all the builders to which it's attached - self.builders = [] - for builderName in self.status.getBuilderNames(): - if self.name in self.status.getBuilder(builderName).slavenames: - self.builders.append(builderName) - return self.builders - - def asDict(self, request): - results = self.slave_status.asDict() - # Enhance it by adding more informations. - results['builders'] = {} - for builderName in self.getBuilders(): - builds = [] - builder_status = self.status.getBuilder(builderName) - cache_size = builder_status.master.config.caches['Builds'] - numbuilds = int(request.args.get('numbuilds', [cache_size - 1])[0]) - for i in range(1, numbuilds): - build_status = builder_status.getBuild(-i) - if not build_status or not build_status.isFinished(): - # If not finished, it will appear in runningBuilds. - break - if build_status.getSlavename() == self.name: - builds.append(build_status.getNumber()) - results['builders'][builderName] = builds - return results - - -class SlavesJsonResource(JsonResource): - help = """List the registered slaves. -""" - pageTitle = 'Slaves' - - def __init__(self, status): - JsonResource.__init__(self, status) - for slave_name in status.getSlaveNames(): - self.putChild(slave_name, - SlaveJsonResource(status, - status.getSlave(slave_name))) - - -class SourceStampJsonResource(JsonResource): - help = """Describe the sources for a SourceStamp. -""" - pageTitle = 'SourceStamp' - - def __init__(self, status, source_stamp): - # buildbot.sourcestamp.SourceStamp - JsonResource.__init__(self, status) - self.source_stamp = source_stamp - self.putChild('changes', - ChangesJsonResource(status, source_stamp.changes)) - # TODO(maruel): Should redirect to the patch's url instead. - #if source_stamp.patch: - # self.putChild('patch', StaticHTML(source_stamp.path)) - - def asDict(self, request): - return self.source_stamp.asDict() - -class MetricsJsonResource(JsonResource): - help = """Master metrics. -""" - title = "Metrics" - - def asDict(self, request): - metrics = self.status.getMetrics() - if metrics: - return metrics.asDict() - else: - # Metrics are disabled - return None - - - -class JsonStatusResource(JsonResource): - """Retrieves all json data.""" - help = """JSON status - -Root page to give a fair amount of information in the current buildbot master -status. You may want to use a child instead to reduce the load on the server. - -For help on any sub directory, use url /child/help -""" - pageTitle = 'Buildbot JSON' - - def __init__(self, status): - JsonResource.__init__(self, status) - self.level = 1 - self.putChild('builders', BuildersJsonResource(status)) - self.putChild('change_sources', ChangeSourcesJsonResource(status)) - self.putChild('project', ProjectJsonResource(status)) - self.putChild('slaves', SlavesJsonResource(status)) - self.putChild('metrics', MetricsJsonResource(status)) - # This needs to be called before the first HelpResource().body call. - self.hackExamples() - - def content(self, request): - result = JsonResource.content(self, request) - # This is done to hook the downloaded filename. - request.path = 'buildbot' - return result - - def hackExamples(self): - global EXAMPLES - # Find the first builder with a previous build or select the last one. - builder = None - for b in self.status.getBuilderNames(): - builder = self.status.getBuilder(b) - if builder.getBuild(-1): - break - if not builder: - return - EXAMPLES = EXAMPLES.replace('<A_BUILDER>', builder.getName()) - build = builder.getBuild(-1) - if build: - EXAMPLES = EXAMPLES.replace('<A_BUILD>', str(build.getNumber())) - if builder.slavenames: - EXAMPLES = EXAMPLES.replace('<A_SLAVE>', builder.slavenames[0]) - -# vim: set ts=4 sts=4 sw=4 et: diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py deleted file mode 100644 index 138fa3cc..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/step.py +++ /dev/null @@ -1,96 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -import urllib -from buildbot.status.web.base import HtmlResource, path_to_builder, \ - path_to_build, css_classes -from buildbot.status.web.logs import LogsResource -from buildbot import util -from time import ctime - -# /builders/$builder/builds/$buildnum/steps/$stepname -class StatusResourceBuildStep(HtmlResource): - pageTitle = "Build Step" - addSlash = True - - def __init__(self, build_status, step_status): - HtmlResource.__init__(self) - self.status = build_status - self.step_status = step_status - - def content(self, req, cxt): - s = self.step_status - b = s.getBuild() - - logs = cxt['logs'] = [] - for l in s.getLogs(): - # FIXME: If the step name has a / in it, this is broken - # either way. If we quote it but say '/'s are safe, - # it chops up the step name. If we quote it and '/'s - # are not safe, it escapes the / that separates the - # step name from the log number. - logs.append({'has_contents': l.hasContents(), - 'name': l.getName(), - 'link': req.childLink("logs/%s" % urllib.quote(l.getName())) }) - - stepStatistics = s.getStatistics() - statistics = cxt['statistics'] = [] - for stat in stepStatistics: - statistics.append({'name': stat, 'value': stepStatistics[stat]}) - - start, end = s.getTimes() - - if start: - cxt['start'] = ctime(start) - if end: - cxt['end'] = ctime(end) - cxt['elapsed'] = util.formatInterval(end - start) - else: - cxt['end'] = "Not Finished" - cxt['elapsed'] = util.formatInterval(util.now() - start) - - cxt.update(dict(builder_link = path_to_builder(req, b.getBuilder()), - build_link = path_to_build(req, b), - b = b, - s = s, - result_css = css_classes[s.getResults()[0]])) - - template = req.site.buildbot_service.templates.get_template("buildstep.html"); - return template.render(**cxt) - - def getChild(self, path, req): - if path == "logs": - return LogsResource(self.step_status) - return HtmlResource.getChild(self, path, req) - - - -# /builders/$builder/builds/$buildnum/steps -class StepsResource(HtmlResource): - addSlash = True - - def __init__(self, build_status): - HtmlResource.__init__(self) - self.build_status = build_status - - def content(self, req, ctx): - return "subpages show data for each step" - - def getChild(self, path, req): - for s in self.build_status.getSteps(): - if s.getName() == path: - return StatusResourceBuildStep(self.build_status, s) - return HtmlResource.getChild(self, path, req) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html deleted file mode 100644 index f7b799a2..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/about.html +++ /dev/null @@ -1,32 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>About this Buildbot</h1> - -<div class="column"> - -<h2>Version Information</h2> -<ul> -{% set item_class=cycler('alt', '') %} - - <li class="{{ item_class.next() }}">Buildbot: {{ buildbot }}</li> - <li class="{{ item_class.next() }}">Twisted: {{ twisted }}</li> - <li class="{{ item_class.next() }}">Jinja: {{ jinja }}</li> - <li class="{{ item_class.next() }}">Python: {{ python }}</li> - <li class="{{ item_class.next() }}">Buildmaster platform: {{ platform }}</li> - -</ul> - -<h2>Source code</h2> - -<p>Buildbot is a free software project, released under the terms of the -<a href="http://www.gnu.org/licenses/gpl.html">GNU GPL</a>.</p> - -<p>Please visit the <a href="http://buildbot.net/">Buildbot Home Page</a> for -more information, including documentation, bug reports, and source -downloads.</p> - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html deleted file mode 100644 index bae600f7..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authfail.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>Authentication Failed</h1> - -<p>The username or password you entered were not correct. - Please go back and try again. -</p> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html deleted file mode 100644 index e2bfcd99..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/authzfail.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>Authorization Failed</h1> - -<p>You are not allowed to perform this action. -</p> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html deleted file mode 100644 index ec5b80b6..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/box_macros.html +++ /dev/null @@ -1,37 +0,0 @@ -{% macro box(text=[], comment=None) -%} - -{%- if comment -%}<!-- {{ comment }} -->{%- endif -%} - <td class="{{ kwargs.class or kwargs.class_ or "" }}" - {%- for prop in ("align", "colspan", "rowspan", "border", "valign", "halign") -%} - {%- if prop in kwargs %} {{ prop }}="{{ kwargs[prop] }}"{% endif -%} - {%- endfor -%}> - - {%- if text is string -%} - {{ text }} - {%- else -%} - {{- text|join("<br/>") -}} - {%- endif -%} - </td> -{% endmacro %} - -{# this is currently just the text part of the boxes #} - -{% macro build_box(reason, url, number) -%} - <a title="Reason: {{ reason|e }}" href="{{ url }}">Build {{ number }}</a> -{%- endmacro %} - -{% macro step_box(text, logs, urls, stepinfo) -%} - {%- if text is string -%} - {{ text }} - {%- else -%} - {{- text|join("<br/>") -}} - {%- endif -%} - <br/> - {%- for l in logs %} - <a {% if l.url %}href="{{ l.url }}"{% endif %}>{{ l.name|e }}</a><br/> - {%- endfor -%} - - {%- for u in urls %} - [<a href="{{ u.link }}" class="BuildStep external">{{ u.name|e }}</a>]<br/> - {%- endfor -%} -{%- endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html deleted file mode 100644 index 0f508880..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build.html +++ /dev/null @@ -1,238 +0,0 @@ -{% extends "layout.html" %} -{% import 'forms.html' as forms %} -{% from "change_macros.html" import change with context %} - -{% block content %} - -<h1> -Builder <a href="{{ path_to_builder }}">{{ b.getBuilder().getName() }}</a> -Build #{{ b.getNumber() }} -</h1> - -<div class="column"> - -{% if not b.isFinished() %} - <h2>Build In Progress:</h2> - - {% if when_time %} - <p>ETA: {{ when_time }} [{{ when }}]</p> - {% endif %} - - {{ current_step }} - - {% if authz.advertiseAction('stopBuild', request) %} - <h2>Stop Build</h2> - {{ forms.stop_build(build_url+"/stop", authz, on_all=False, short=False, label='This Build') }} - {% endif %} -{% else %} - <h2>Results:</h2> - - <p class="{{ result_css }} result"> - {{ b.getText()|join(' ')|capitalize }} - </p> - - {% if b.getTestResults() %} - <h3><a href="{{ tests_link }}"/></h3> - {% endif %} -{% endif %} - -<h2> -{% if sourcestamps|count == 1 %} -SourceStamp: -{% else %} -SourceStamps: -{% endif %} -</h2> - -{% for ss in sourcestamps %} -<h3>{{ ss.codebase }}</h3> - <table class="info" width="100%"> - {% set ss_class = cycler('alt','') %} - - {% if ss.project %} - <tr class="{{ ss_class.next() }}"><td class="left">Project</td><td>{{ ss.project|projectlink }}</td></tr> - {% endif %} - - {% if ss.repository %} - <tr class="{{ ss_class.next() }}"><td class="left">Repository</td><td>{{ ss.repository|repolink }}</td></tr> - {% endif %} - - {% if ss.branch %} - <tr class="{{ ss_class.next() }}"><td class="left">Branch</td><td>{{ ss.branch|e }}</td></tr> - {% endif %} - - {% if ss.revision %} - <tr class="{{ ss_class.next() }}"><td class="left">Revision</td><td>{{ ss.revision|revlink(ss.repository) }}</td></tr> - {% endif %} - - {% if got_revisions[ss.codebase] %} - <tr class="{{ ss_class.next() }}"><td class="left">Got Revision</td><td>{{ got_revisions[ss.codebase]|revlink(ss.repository) }}</td></tr> - {% endif %} - - {% if ss.patch %} - <tr class="{{ ss_class.next() }}"><td class="left">Patch</td><td>YES</td></tr> - {% endif %} - - {% if ss.changes %} - <tr class="{{ ss_class.next() }}"><td class="left">Changes</td><td><a href="#changes-{{ ss.codebase }}">{{ ss.changes|count }} change{{ 's' if ss.changes|count > 1 else '' }}</a></td></tr> - {% endif %} - - {% if not ss.branch and not ss.revision and not ss.patch and not ss.changes %} - <tr class="{{ ss_class.next() }}"><td class="left" colspan="2">Build of most recent revision</td></tr> - {% endif %} - </table> -{% endfor %} - -{# - # TODO: turn this into a table, or some other sort of definition-list - # that doesn't take up quite so much vertical space - #} - -<h2>BuildSlave:</h2> - -{% if slave_url %} - <a href="{{ slave_url|e }}">{{ b.getSlavename()|e }}</a> -{% else %} - {{ b.getSlavename()|e }} -{% endif %} - -<h2>Reason:</h2> -<p> -{{ b.getReason()|e }} -</p> - -<h2>Steps and Logfiles:</h2> - -{# - # TODO: - # urls = self.original.getURLs() - # ex_url_class = "BuildStep external" - # for name, target in urls.items(): - # text.append('[<a href="%s" class="%s">%s</a>]' % - # (target, ex_url_class, html.escape(name))) - #} - -<ol> -{% for s in steps %} - <li> - <div class="{{ s.css_class }} result"> - <a href="{{ s.link }}">{{ s.name }}</a> - {{ s.text }} <span style="float:right">{{ '( ' + s.time_to_run + ' )' if s.time_to_run else '' }}</span> - </div> - - <ol> - {% set item_class = cycler('alt', '') %} - {% for l in s.logs %} - <li class="{{ item_class.next() }}"><a href="{{ l.link }}">{{ l.name }}</a></li> - {% else %} - <li class="{{ item_class.next() }}">- no logs -</li> - {% endfor %} - - {% for u in s.urls %} - <li class="{{ item_class.next() }}"><a href="{{ u.url }}">{{ u.logname }}</a></li> - {% endfor %} - </ol> - </li> -{% endfor %} -</ol> - -</div> -<div class="column"> - -<h2>Build Properties:</h2> - -<table class="info" width="100%"> -<tr><th>Name</th><th>Value</th><th>Source</th></tr> - -{% for p in properties %} -{% if p.source != "Force Build Form" %} - <tr class="{{ loop.cycle('alt', '') }}"> - <td class="left">{{ p.name|e }}</td> - {% if p.short_value %} - <td>{{ p.short_value|e }} .. [property value too long]</td> - {% else %} - {% if p.value is not mapping %} - <td>{{ p.value|e }}</td> - {% else %} - <td> - <table class="info" width="100%"> - {%- for key, value in p.value.items() recursive %} - <tr><td>{{ key|e }}</td><td>{{ value|e }}</td></tr> - {% endfor %} - </table> - </td> - {% endif %} - {% endif %} - <td>{{ p.source|e }}</td> - </tr> -{% endif %} -{% endfor %} -</table> -<h2>Forced Build Properties:</h2> -<table class="info" width="100%"> -<tr><th>Name</th><th>Label</th><th>Value</th></tr> - -{% for p in properties %} - {% if p.source == "Force Build Form" %} - <tr class="{{ loop.cycle('alt', '') }}"> - <td class="left">{{ p.name|e }}</td> - <td class="left"> - {% if p.label %} - {{ p.label }} - {% endif %} - </td> - {% if p.text %} - <td><textarea readonly cols="{{p.cols}}" rows="{{p.rows}}">{{ p.text|e }}</textarea></td> - {% else %} - <td>{{ p.value|e }}</td> - {% endif %} - </tr> - {% endif %} -{% endfor %} -</table> - -<h2>Responsible Users:</h2> - -{% if responsible_users %} - <ol> - {% for u in responsible_users %} - <li class="{{ loop.cycle('alt', '') }}">{{ u|user }}</li> - {% endfor %} - </ol> -{% else %} - <p>no responsible users</p> -{% endif %} - - -<h2>Timing:</h2> -<table class="info" width="100%"> - <tr class="alt"><td class="left">Start</td><td>{{ start }}</td></tr> -{% if end %} - <tr><td class="left">End</td><td>{{ end }}</td></tr> -{% endif %} - <tr {{ 'class="alt"' if end else '' }}><td class="left">Elapsed</td><td>{{ elapsed }}</td></tr> -</table> - -</div> - -<br style="clear:both"/> - -{% if has_changes %} - <div class="column"> - <h2>All Changes:</h2> - {% for ss in sourcestamps %} - {% if ss.changes %} - <h3 id="changes-{{ ss.codebase }}"> {{ ss.codebase }}:</h3> - <ol> - {% for c in ss.changes %} - <li><h3>Change #{{ c.number }}</h3> - {{ change(c.asDict()) }} - </li> - {% endfor %} - </ol> - {% endif %} - {% endfor %} - </div> -{% endif %} - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html deleted file mode 100644 index fc08b9dc..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/build_line.html +++ /dev/null @@ -1,45 +0,0 @@ -{% macro build_line(b, include_builder=False) %} - <small>({{ b.time }})</small> - Rev: {{ b.rev|shortrev(b.rev_repo) }} - <span class="{{ b.class }}">{{ b.results }}</span> - {% if include_builder %} - <a href="{{ b.builderurl }}">{{ b.builder_name }}</a> - {% endif %} - <a href="{{ b.buildurl }}">#{{ b.buildnum }}</a> - - {{ b.text|capitalize }} -{% endmacro %} - -{% macro build_tr(b, include_builder=False, loop=None) %} - <tr class="{{ loop.cycle('alt', '') if loop }}"> - <td>{{ b.time }}</td> - <td>{{ b.rev|shortrev(b.rev_repo) }}</td> - <td class="{{ b.class }}">{{ b.results }}</td> - {%- if include_builder %} - <td><a href="{{ b.builderurl }}">{{ b.builder_name }}</a></td> - {% endif %} - <td><a href="{{ b.buildurl }}">#{{ b.buildnum }}</a></td> - <td class="left">{{ b.text|capitalize }}</td> - </tr> -{% endmacro %} - -{% macro build_table(builds, include_builder=False) %} -{% if builds %} -<table class="info"> - <tr> - <th>Time</th> - <th>Revision</th> - <th>Result</th> - {%- if include_builder %} - <th>Builder</th> - {% endif %} - <th>Build #</th> - <th>Info</th> - </tr> - {% for b in builds %} - {{ build_tr(b, include_builder, loop) }} - {% endfor %} -</table> -{% else %} - No matching builds found -{% endif %} -{% endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html deleted file mode 100644 index f557d7c5..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builder.html +++ /dev/null @@ -1,184 +0,0 @@ -{% from 'build_line.html' import build_table %} -{% import 'forms.html' as forms %} - -{% extends "layout.html" %} - -{% block head %} -{{ super() }} -<script type='text/javascript'> -// <![CDATA[ -// - -// Mapping OE Core branch names to bitbake branch names -var bbvermap = { - 'jethro': '1.28', - 'krogoth': '1.30', - 'morty': '1.32', - 'pyro': '1.34', - 'rocko': '1.36', - 'sumo': '1.38', - 'master': 'master' -}; - -var eclipseBranchFormat = "branch_eclipse-poky-"; - -function isEclipseBranch(elementName) { - var pattern = eclipseBranchFormat + "*"; - return new RegExp(pattern).test(elementName); -} - -function updateFormBranchInputs(pokybranch) { - var elements = document.querySelectorAll('input[name^="branch_"]'); - - for (var i = 0, len = elements.length; i < len; i++) { - var newval = pokybranch; - if (elements[i].name == "branch_bitbake") { - newval = bbvermap[pokybranch]; - } else if (isEclipseBranch(elements[i].name)) { - eclipseRelease = elements[i].name.split(eclipseBranchFormat, 2)[1]; - // Match the Eclipse branch format - if (pokybranch != "master") { - newval = eclipseRelease + "/" + pokybranch; - } else { - newval = eclipseRelease + "-master"; - } - } else if (elements[i].name == "branch_refkit") { - // Refkit only tracks OE-Core master - newval = "master"; - } else if (elements[i].name == "branch_meta-qt3") { - // won't get a rocko, or newer, branch - if (['jethro', 'krogoth', 'morty', 'pyro'].indexOf(pokybranch) < 0) { - newval = "master" - } - } else if (elements[i].name == "branch_meta-gplv2") { - // only has pyro and master branches - if (pokybranch != "pyro") { - newval = "master" - } - } - elements[i].value = newval; - } -} - -// ]]> -</script> -{% endblock %} - -{% block content %} - -<h1>Builder {{ name }}</h1> - -<p>(<a href="{{ path_to_root }}waterfall?show={{ name }}">view in waterfall</a>)</p> - -{% if description %} - <div class="BuilderDescription">{{ description }}</div> -{% endif %} - -<div class="column"> - -{% if current %} - <h2>Current Builds:</h2> - <ul> - {% for b in current %} - <li><a href="{{ b.link }}">{{ b.num }}</a> - {% if b.when %} - ETA: {{ b.when_time }} [{{ b.when }}] - {% endif %} - - {{ b.current_step }} - - {% if authz.advertiseAction('stopBuild', request) %} - {{ forms.stop_build(b.stop_url, authz, on_all=False, short=True, label='Build') }} - {% endif %} - </li> - {% endfor %} - </ul> -{% else %} - <h2>No current builds</h2> -{% endif %} - -{% if pending %} - <h2>Pending Build Requests:</h2> - <ul> - {% for b in pending %} - <li><small>({{ b.when }}, waiting {{ b.delay }})</small> - - {% if authz.advertiseAction('cancelPendingBuild', request) %} - {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=True, id=b.id) }} - {% endif %} - - {% if b.num_changes < 4 %} - {% for c in b.changes %}{{ c.revision|shortrev(c.repo) }} - (<a href="{{ c.url }}">{{ c.who|email }}</a>){% if not loop.last %},{% endif %} - {% endfor %} - {% else %} - ({{ b.num_changes }} changes) - {% endif %} - - {% if 'owner' in b.properties %} - <b>Forced build</b> - by {{b.properties['owner'][0]}} - <small>{{b.properties['reason'][0]}}</small> - {% endif %} - </li> - {% endfor %} - </ul> - - {% if authz.advertiseAction('cancelPendingBuild', request) %} - {{ forms.cancel_pending_build(builder_url+"/cancelbuild", authz, short=False, id='all') }} - {% endif %} - -{% else %} - <h2>No Pending Build Requests</h2> -{% endif %} - -<h2>Recent Builds:</h2> - -{{ build_table(recent) }} - -<a href="?numbuilds={{numbuilds + 5}}">Show more</a> - -</div> -<div class="column"> - -<h2>Buildslaves:</h2> -<table class="info"> -{% if slaves %} -<tr> - <th>Name</th> - <th>Status</th> - <th>Admin</th> -</tr> -{% endif %} -{% for s in slaves %} - <tr class="{{ loop.cycle('alt', '') }}"> - <td><b><a href="{{ s.link|e }}">{{ s.name|e }}</a></b></td> - {% if s.connected %} - {% if s.paused %} - <td class="paused">paused</td> - {% else %} - <td class="idle">connected</td> - {% endif %} - {% else %} - <td class="offline">offline</td> - {% endif %} - <td>{{ s.admin|email if s.admin else ""}}</td> - </tr> -{% else %} - <td>no slaves attached</td> -{% endfor %} -</table> - -{% if authz.advertiseAction('pingBuilder', request) %} - <h2>Ping slaves</h2> - {{ forms.ping_builder(builder_url+"/ping", authz) }} -{% endif %} - -{% if authz.advertiseAction('forceBuild', request) and force_schedulers != {} %} - <h2>Force build</h2> - {{ forms.force_build(builder_url+"/force", authz, request, False, force_schedulers=force_schedulers,default_props=default_props) }} -{% endif %} - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html deleted file mode 100644 index 67cb0225..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/builders.html +++ /dev/null @@ -1,50 +0,0 @@ -{% extends 'layout.html' %} -{% import 'forms.html' as forms %} -{% from "box_macros.html" import box %} - -{% block content %} -<h1>Builders: {{ branches|join(', ')|e }}</h1> - -<table> -{% for b in builders %} - <tr> - <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td> - {% if b.build_url %} - <td class="LastBuild box {{ b.build_css_class }}"> - <a href="{{ b.build_url }}">{{ b.build_label }}</a> - <br/>{{ b.build_text }} - </td> - {% else %} - <td class="LastBuild box">no build</td> - {% endif %} - {{ box(**b.current_box) }} - </tr> -{% endfor %} -</table> - -{% if num_building > 0 %} - {% if authz.advertiseAction('stopAllBuilds', request) or authz.advertiseAction('stopBuild', request) %} - <h2>Stop Selected Builds</h2> - {{ forms.stop_build(path_to_root+"builders/_selected/stopselected", authz, on_selected=True, builders=builders, label='Selected Builds') }} - <h2>Stop All Builds</h2> - {{ forms.stop_build(path_to_root+"builders/_all/stopall", authz, on_all=True, label='All Builds') }} - {% endif %} -{% endif %} - -{% if authz.advertiseAction('cancelAllPendingBuilds', request) %} - <h2>Cancel Selected Pending Builds</h2> - {{ forms.cancel_build(path_to_root+"builders/_selected/cancelpendingselected", authz, on_selected=True, builders=builders, label='Selected Pending Builds') }} - <h2>Cancel All Pending Builds</h2> - {{ forms.cancel_build(path_to_root+"builders/_all/cancelpendingall", authz, on_all=True, label='All Pending Builds') }} -{% endif %} - -{% if num_online > 0 %} - {% if authz.advertiseAction('forceAllBuilds', request) or authz.advertiseAction('forceBuild', request) %} - <h2>Force Selected Builds</h2> - {{ forms.force_build(path_to_root+"builders/_selected/forceselected", authz, request, on_selected=True, builders=builders, force_schedulers=force_schedulers, default_props=default_props) }} - <h2>Force All Builds</h2> - {{ forms.force_build(path_to_root+"builders/_all/forceall", authz,request, on_all=True, force_schedulers=force_schedulers, default_props=default_props) }} - {% endif %} -{% endif %} - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html deleted file mode 100644 index d9f55038..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslave.html +++ /dev/null @@ -1,68 +0,0 @@ -{% from 'build_line.html' import build_table, build_line %} -{% import 'forms.html' as forms %} - -{% extends "layout.html" %} -{% block content %} -<h1>Buildslave: {{ slavename|e }}</h1> - -<div class="column"> - -{% if current %} - <h2>Currently building:</h2> - <ul> - {% for b in current %} - <li>{{ build_line(b, True) }} - <form method="post" action="{{ b.buildurl }}/stop" class="command stopbuild" style="display:inline"> - <input type="submit" value="Stop Build" /> - <input type="hidden" name="url" value="{{ this_url }}" /> - </form> - </li> - {% endfor %} - </ul> -{% else %} - <h2>No current builds</h2> -{% endif %} - -<h2>Recent builds</h2> -{{ build_table(recent, True) }} - -</div> -<div class="column"> -{% if access_uri %} - <a href="{{ access_uri|e }}">Click to Access Slave</a> -{% endif %} - -{% if admin %} - <h2>Administrator</h2> - <p>{{ admin|email }}</p> -{% endif %} - -{% if host %} - <h2>Slave information</h2> - Buildbot-Slave {{ slave_version }} - <pre>{{ host|e }}</pre> -{% endif %} - -<h2>Connection Status</h2> -<p> -{{ connect_count }} connection(s) in the last hour -{% if not slave.isConnected() %} -(not currently connected) -{% else %} -</p> - {% if authz.advertiseAction('gracefulShutdown', request) %} - <h2>Graceful Shutdown</h2> - {% if slave.getGraceful() %} - <p>Slave will shut down gracefully when it is idle.</p> - {% else %} - {{ forms.graceful_shutdown(shutdown_url, authz) }} - {% endif %} - {% endif %} - {% if authz.advertiseAction('pauseSlave', request) %} - <h2>Pause Slave</h2> - {{ forms.pause_slave(pause_url, authz, slave.isPaused()) }} - {% endif %} -{% endif %} -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html deleted file mode 100644 index 567e3747..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildslaves.html +++ /dev/null @@ -1,76 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>Buildslaves</h1> - -<div class="column"> - -<table class="info"> - -<tr> - <th>Name</th> - {%- if show_builder_column %} - <th>Builders</th> - {%- endif %} - <th>BuildBot</th> - <th>Admin</th> - <th>Last heard from</th> - <th>Connects/Hour</th> - <th>Status</th> -</tr> - -{% for s in slaves %} - <tr class="{{ loop.cycle('alt','') }}"> - <td><b><a href="{{ s.link }}">{{ s.name }}</a></b></td> - - {%- if show_builder_column %} - <td> - {%- if s.builders %} - {%- for b in s.builders %} - <a href="{{ b.link }}">{{ b.name }}</a> - {%- endfor %} - {%- else %} - <span class="Warning">no builders</span> - {%- endif -%} - </td> - {%- endif %} - - - <td>{{ (s.version or '-')|e }}</td> - - {%- if s.admin -%} - <td>{{ s.admin|email }}</td> - {%- else -%} - <td>-</td> - {%- endif -%} - - <td> - {%- if s.last_heard_from_age -%} - {{ s.last_heard_from_age }} <small>({{ s.last_heard_from_time }})</small> - {%- endif -%} - </td> - <td> - {{ s.connectCount }} - </td> - - {% if s.connected %} - {% if s.running_builds %} - <td class="building">Running {{ s.running_builds }} build(s)</td> - {% elif s.paused %} - <td class="paused">Paused</td> - {% else %} - <td class="idle">Idle</td> - {% endif %} - - {% else %} - <td class="offline">Not connected</td> - {% endif %} - - </tr> -{% endfor %} -</table> - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html deleted file mode 100644 index df33878a..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstatus.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "layout.html" %} -{% from "box_macros.html" import box %} - -{% block header %} -{% endblock %} - -{% block barecontent %} -<table> - {% for r in rows %} - <tr>{{ box(**r) }}</tr> - {% endfor %} - - <tr>{{ box(**build) }}</tr> -</table> -{% endblock %} - -{% block footer %} -{% endblock %} - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html deleted file mode 100644 index c2c75140..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/buildstep.html +++ /dev/null @@ -1,73 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1> - Builder <a href="{{ builder_link }}">{{ b.getBuilder().getName() }}</a> - build <a href="{{ build_link }}">#{{ b.getNumber() }}</a> - step <a href="">{{ s.getName() }}</a> -</h1> - -<div class="column"> - -{% if s.isFinished() %} - <h2>Finished</h2> - <p class="{{ result_css }} result"> - {%- set text = s.getText() -%} - {%- if text is string %}{{ text|e }} - {%- else %}{{ text|join(" ")|e }}{% endif -%} - </p> -{% else %} - <h2>Not Finished</h2> - <p>ETA {{ s.getETA()|e }} seconds</p> -{% endif %} - -{% set exp = s.getExpectations() %} -{% if exp %} - <h2>Expectations</h2> - <ul> - {% for e in exp %} - <li>{{ e[0]|e }}: current={{ e[1] }}, target={{ e[2] }}</li> - {% endfor %} - </ul> -{% endif %} - -<h2>Timing</h2> -{% if start %} - <table class="info"> - <tr class="alt"><td class="left">Start</td><td>{{ start }}</td></tr> - <tr><td class="left">End</td><td>{{ end or "Not finished" }}</td></tr> - <tr class="alt"><td class="left">Elapsed</td><td>{{ elapsed }}</td></tr> - </table> -{% else %} - <b>Not started</b> -{% endif %} - -<h2>Logs</h2> -<ul> -{% for l in logs %} - <li class="{{ loop.cycle('alt', '') }}"> - {% if l.has_contents %} - <a href="{{ l.link|e }}">{{ l.name|e }}</a> - {% else %} - {{ l.name|e }} - {% endif %} - </li> -{% else %} - <li class="alt">- No logs -</li> -{% endfor %} -</ul> - -{% if statistics %} -<h2>Statistics</h2> -<table class="info"> - <tr><th>Name</th><th>Value</th></tr> - {% for stat in statistics %} - <tr class="{{ loop.cycle('alt', '') }}"><td>{{ stat.name|e }}</td><td>{{ stat.value|e }}</td></tr> - {% endfor %} -</table> -{% endif %} - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html deleted file mode 100644 index f12161da..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends "layout.html" %} -{% from "change_macros.html" import change with context %} -{% import 'forms.html' as forms %} - -{% block content %} - -<h1>{{ pageTitle }}</h1> - -<div class="column"> - -{{ change(c) }} - -{% if authz.advertiseAction('stopChange', request) %} - <h3>Cancel Builds For Change:</h3> - {{ forms.stop_change_builds("/builders/_all/stopchangeall", c.number, authz) }} -{% endif %} - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html deleted file mode 100644 index 2ca01d9f..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_macros.html +++ /dev/null @@ -1,76 +0,0 @@ -{% macro change(c) %} - -<table class="info"> - {% set row_class=cycler('alt','') %} - <tr class="{{ row_class.next() }}"> - <td class="left">Category</td> - <td><b>{{ c.category }}</b></td> - </tr> - <tr class="{{ row_class.next() }}"> - <td class="left">Changed by</td> - <td><b>{{ c.who|email }}</b></td> - </tr> - <tr class="{{ row_class.next() }}"> - <td class="left">Changed at</td> - <td><b>{{ c.at }}</b></td> - </tr> - - {% if c.repository %} - <tr class="{{ row_class.next() }}"> - <td class="left">Repository</td> - <td><b>{{ c.repository|repolink }}</b></td> - </tr> - {% endif %} {% if c.project %} - <tr class="{{ row_class.next() }}"> - <td class="left">Project</td> - <td><b>{{ c.project|projectlink }}</b></td> - </tr> - {% endif %} {% if c.branch %} - <tr class="{{ row_class.next() }}"> - <td class="left">Branch</td> - <td><b>{{ c.branch|e }}</b></td> - </tr> - {% endif %} {% if c.rev %} - <tr class="{{ row_class.next() }}"> - <td class="left">Revision</td> - <td>{%- if c.revlink -%}<a href="{{ c.revlink }}">{{ c.rev|e }}</a> - {%- else -%}{{ c.rev|revlink(c.repository) }} {%- endif -%}</td> - </tr> - {% endif %} -</table> - -{% if c.comments %} -<h3>Comments</h3> -<pre class="comments">{{ c.comments|changecomment(c.project) }}</pre> -{% endif %} - -<h3 class="files">Changed files</h3> -<ul> - {% for f in c.files -%} - <li class="{{ loop.cycle('alt', '') }}">{%- if f.url %}<a - href="{{ f.url }}"><b>{{ f.name|e }}</b></a></li> - {%- else %} - <b>{{ f.name|e }}</b> - {%- endif -%} - </li> - {% else %} - <li>no files</li> - {% endfor %} -</ul> - -{% if c.properties %} -<h3>Properties</h3> -<table class="info"> - {% for p in c.properties %} - <tr class="{{ loop.cycle('alt') }}"> - <td class="left">{{ p[0]|capitalize|e }}</td> - <td>{{ p[1]|e }}</td> - </tr> - {% endfor %} -</table> -{% endif %} -{%- endmacro %} - -{% macro box_contents(who, url, pageTitle, revision, project) -%} -<a href="{{ url }}" title="{{ pageTitle|e }}">{{ who|user }}</a> -{%- endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html deleted file mode 100644 index 24674dd5..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/change_sources.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>Changesources</h1> - -<div class="column"> - -{% if sources %} - <ol> - {% for s in sources -%} - <li class="{{ loop.cycle('alt', '') }}">{{ s.describe() }}</li> - {% endfor -%} - </ol> -{% else %} - none (push only) -{% endif %} - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html deleted file mode 100644 index a51c946e..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/console.html +++ /dev/null @@ -1,276 +0,0 @@ -{% extends "layout.html" %} - -{% block head %} -{{ super() }} -<script type='text/javascript'> -// <![CDATA[ -// - -// -// Functions used to display the build status bubble on box click. -// - -// show the build status box. This is called when the user clicks on a block. -function showBuildBox(url, event) { - // Find the current curson position. - var cursorPosTop = (window.event ? window.event.clientY : event.pageY) - var cursorPosLeft = (window.event ? window.event.clientX : event.pageX) - - // Offset the position by 5, to make the window appears under the cursor. - cursorPosTop = cursorPosTop + document.body.scrollTop -5 ; - cursorPosLeft = cursorPosLeft + document.body.scrollLeft - 5; - - // Move the div (hidden) under the cursor. - var divBox = document.getElementById('divBox'); - divBox.style.top = parseInt(cursorPosTop) + 'px'; - divBox.style.left = parseInt(cursorPosLeft) + 'px'; - - // Reload the hidden frame with the build page we want to show. - // The onload even on this frame will update the div and make it visible. - document.getElementById("frameBox").src = url - - // We don't want to reload the page. - return false; -} - -// OnLoad handler for the iframe containing the build to show. -function updateDiv(event) { - // Get the frame innerHTML. - var iframeContent = document.getElementById("frameBox").contentWindow.document.body.innerHTML; - - // If there is any content, update the div, and make it visible. - if (iframeContent) { - var divBox = document.getElementById('divBox'); - divBox.innerHTML = iframeContent ; - divBox.style.display = "block"; - } -} - -// Util functions to know if an element is contained inside another element. -// We use this to know when we mouse out our build status div. -function containsDOM (container, containee) { - var isParent = false; - do { - if ((isParent = container == containee)) - break; - containee = containee.parentNode; - } while (containee != null); - - return isParent; -} - -// OnMouseOut handler. Returns true if the mouse moved out of the element. -// It is false if the mouse is still in the element, but in a blank part of it, -// like in an empty table cell. -function checkMouseLeave(element, event) { - if (element.contains && event.toElement) { - return !element.contains(event.toElement); - } - else if (event.relatedTarget) { - return !containsDOM(element, event.relatedTarget); - } -} - -// ]]> -</script> -{% endblock %} - -{% block content %} - -<h1>Console View</h1> - -<div align="center"> - <table width="95%" class="Grid" border="0" cellspacing="0"> - <tr> - <td width="33%" align="left" class="left_align"> -{% if categories|length > 1 %} - <br><b>Categories:</b> {% for c in categories %}{{ c.name|e }} {% endfor %} -{% endif %} -{% if codebase %} - <br><b>Codebase:</b> {{ codebase|e }} -{% endif %} -{% if repository %} - <br><b>Repository:</b> {{ repository|e }} -{% endif %} -{% if project %} - <br><b>Project:</b> {{ project|e }} -{% endif %} -{% if branch != ANYBRANCH %} - <br><b>Branch:</b> {{ branch|e }} -{% endif %} - </td> - <td width="33%" align="center" class="center_align"> - <div align="center"> - <table class="info"> - <tr> - <td>Legend: </td> - <td class='legend success' title='All tests passed'>Passed</td> - <td class='legend failure' title='There is a new failure. Take a look!'>Failed</td> - <td class='legend warnings' title='Build has warnings'>Warnings</td> - <td class='legend failure-again' title='It was failing before, and it is still failing. Make sure you did not introduce new regressions'>Failed Again</td> - <td class='legend running' title='The tests are still running'>Running</td> - <td class='legend exception' title='Something went wrong with the test, there is no result'>Exception</td> - <td class='legend offline' title='The builder is offline, as there are no slaves connected to it'>Offline</td> - <td class='legend notstarted' title='No result yet.'>No data</td> - </tr> - </table> - </div> - </td> - <td width="33%" align="right" class="right_align"> - <script type="text/javascript"> -// <![CDATA[ - function reload_page() { - name_value = document.getElementById('namebox').value - if (document.location.href.lastIndexOf('?') == -1) - document.location.href = document.location.href+ '?name=' + name_value; - else - document.location.href = document.location.href+ '&name=' + name_value; - } -// ]]> - </script> - <form onsubmit='reload_page()'> - <input id='namebox' name='name' type='text' style='color:#999;' - onblur='this.value = this.value || this.defaultValue; this.style.color = "#999";' - onfocus='this.value=""; this.style.color = "#000";' - value='Personalized for...'/> - <input type='submit' value='Go'/> - </form> - </td> - </tr> - </table> -</div> - -<br/> - -{% set alt_class = cycler('', 'Alt') %} - -<div align="center"> -<table width="96%"> - -{% if categories|length > 1 %} - <tr> - <td width="1%"> - </td> - <td width="1%"> - </td> - {% for c in categories %} - <td class='DevStatus {{ alt_class.next() }} {{ "first" if loop.first else '' }} {{ "last" if loop.last else '' }}' width='{{ c.size }}%'> - {{ c.name|e }} - </td> - {% endfor %} - </tr> - <tr class='DevStatusSpacing'> - </tr> -{% endif %} - -{% if slaves %} - <tr> - <td width="1%"> - </td> - <td width="1%"> - </td> - {% for c in categories %} - <td class='DevSlave {{ alt_class.next() }}'> - <table width="100%"> - <tr> - {% for s in slaves[c.name] %} - <td class='DevSlaveBox'> - <a href='{{ s.url }}' title='{{ s.pageTitle }}' class='DevSlaveBox {{ s.color }}' target="_blank"> - </a> - </td> - {% endfor %} - </tr> - </table> - </td> - {% endfor %} - </tr> -{% endif %} - -{% for r in revisions %} - {% set alt = alt_class.next() %} - {% set firstrev = "first" if loop.first else '' %} - - <tr> - <td class='DevRev {{ alt }}' width="1%"> - {{ r.id|shortrev(r.repository) }} - </td> - <td class='DevName {{ alt }}' width="1%"> - {{ r.who|user }} - </td> - - {% for c in categories %} - {% set last = "last" if loop.last else "" %} - <td class='DevStatus {{ alt }} {{ last if not firstrev else '' }}'> - <table width="100%"> - <tr> - {% for b in r.builds[c.name] %} - <td class='DevStatusBox'> - <a href='#' onclick='showBuildBox("{{ b.url }}", event); return false;' - title='{{ b.pageTitle|e }}' class='DevStatusBox {{ b.color }} {{ b.tag }}' - target="_blank"></a> - </td> - {% endfor %} - </tr> - </table> - </td> - {% endfor %} - </tr> - - <tr> - <td colspan="{{ r.span }}" class='DevComment {{ alt }} {% if not r.details %}DevBottom{% endif %}'> - {{ r.comments|changecomment(r.project or None)|replace('\n', '<br/>')|replace(' ',' ') }} - </td> - </tr> - - {% if r.details %} - <tr> - <td colspan="{{ r.span }}" class='DevDetails {{ alt }} DevBottom'> - <ul style='margin: 0px; padding: 0 0 0 1.5em;'> - {% for d in r.details %} - <li>{{ d.buildername }}: {{ d.status }} - - {%- for l in d.logs -%} - <a href="{{ l.url }}">{{ l.name }}</a> - {%- endfor -%} - </li> - {% endfor %} - </ul> - </td> - </tr> - {% endif %} - - <tr class='DevStatusSpacing'> - <td> - </td> - </tr> - -{% else %} - <tr><td>No revisions available</td></tr> -{% endfor %} - -</table> -</div> - - -<div id="divBox" onmouseout="if (checkMouseLeave(this, event)) this.style.display = 'None'" class="BuildWaterfall"> -</div> - - -<iframe id="frameBox" style="display: none;"></iframe> - -<script type="text/javascript"> -// replace 'onload="updateDiv(event);" with this, as iframe doesn't have onload event in xhtml -window.onload = function() { - document.getElementById('frameBox').onload = function(event) { - updateDiv(event); - }; -}; -</script> - -{% endblock %} - - -{% block footer %} - -{{ super() }} -{# <p>Debug info: {{ debuginfo }}</p> #} -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html deleted file mode 100644 index 662355de..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/directory.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>Directory listing for {{ path }}</h1> - -{% set row_class = cycler('alt', '') %} - -<table> - -<tr class="{{ row_class.next() }}"> -<th style="min-width:18em">Name</th> -<th style="min-width:8em">Size</th> -<th style="min-width:10em">Type</th> -<th style="min-width:10em">Encoding</th> -</tr> - -{% for d in directories %} - <tr class="directory {{ row_class.next() }}"> - <td><a href="{{ d.href }}"><b>{{ d.text }}</b></a></td> - <td><b>{{ d.size }}</b></td> - <td><b>{{ d.type }}</b></td> - <td><b>{{ d.encoding }}</b></td> - </tr> -{% endfor %} - -{% for f in files %} - <tr class="file {{ row_class.next() }}"> - <td><a href="{{ f.href }}">{{ f.text }}</a></td> - <td>{{ f.size }}</td> - <td>{{ f.type }}</td> - <td>{{ f.encoding }}</td> - </tr> -{% endfor %} -</table> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html deleted file mode 100644 index 91f4e591..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/empty.html +++ /dev/null @@ -1,5 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} -{{ content }} -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml deleted file mode 100644 index c423e7b0..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_atom10.xml +++ /dev/null @@ -1,40 +0,0 @@ -{% from 'feed_description.html' import item_desc %} - -<?xml version="1.0" encoding="utf-8"?> -<feed xmlns="http://www.w3.org/2005/Atom"> - <id>{{ title_url }}</id> - <title>{{ pageTitle|e }}</title> - {% if project_url -%} - <link rel="self" href="{{ title_url }}/atom"/> - <link rel="alternate" href="{{ title_url }}"/> - {% endif %} - {%- if description -%} - <subtitle>{{ description }}</subtitle> - {% endif %} - {%- if rfc3339_pubdate -%} - <updated>{{ rfc3339_pubdate }}</updated> - {% endif -%} - <author> - <name>BuildBot</name> - </author> - - {% for b in builds -%} - <entry> - <title>{{ b.pageTitle }}</title> - <link href="{{ b.link }}"/> - <content type="xhtml"> - <div xmlns="http://www.w3.org/1999/xhtml"> - {{ item_desc(b, title_url, title)|indent(6) }} - <pre xml:space="preserve">{{ b.log_lines|join('\n')|e }}</pre> - </div> - </content> - {% if b.rfc3339_pubdate -%} - <updated>{{ b.rfc3339_pubdate }}</updated> - <id>{{ b.guid }}</id> - {% endif -%} - <author>Buildbot</author> - </entry> - - {% endfor -%} - -</feed> diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html deleted file mode 100644 index 7f387c67..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_description.html +++ /dev/null @@ -1,18 +0,0 @@ -{% from 'feed_sources.html' import srcs_desc %} - -{% macro item_desc(b, title_url, title) -%} - <p> - Date: {{ b.date }}<br/> - Project home: <a href="{{ title_url }}">{{ title|e }}</a><br/> - Builder summary: <a href="{{ b.summary_link }}">{{ b.name }}</a><br/> - Build details: <a href="{{ b.link }}">Build {{ b.number }}</a><br/> - Author list: <b>{{ b.responsible_users|join(', ') }}</b><br/> - Failed step(s): <b>{{ b.failed_steps|join(', ') }}</b><br/> - </p> - {% for src in b.sources %} - {{ srcs_desc(src) }} - {% endfor %} - <p> - <i>Last lines of the build log:</i> - </p> -{%- endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml deleted file mode 100644 index 9f30112a..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_rss20.xml +++ /dev/null @@ -1,39 +0,0 @@ -{% from 'feed_description.html' import item_desc %} - -<?xml version="1.0" encoding="utf-8"?> -<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> - <channel> - <title>{{ pageTitle|e }}</title> - <link>{{ title_url }}</link> - <atom:link href="{{ title_url }}rss" rel="self" type="application/rss+xml"/> - {% if language -%} - <language>{{ language }}</language> - {% endif %} - {%- if description -%} - <description>{{ description }}</description> - {% endif %} - {%- if rfc822_pubdate -%} - <pubDate>{{ rfc822_pubdate }}</pubDate> - {% endif %} - - {% for b in builds -%} - <item> - <title>{{ b.pageTitle }}</title> - <link>{{ b.link }}</link> - <description> - <![CDATA[ - {{ item_desc(b, title_url, title)|indent(8) }} - <pre>{{ b.log_lines|join('\n')|e }}</pre> - ]]> - </description> - {% if b.rfc822_pubdate -%} - <pubDate>{{ b.rfc822_pubdate }}</pubDate> - <guid isPermaLink="false">{{ b.guid }}</guid> - {%- endif %} - - </item> - - {% endfor %} - - </channel> -</rss> diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html deleted file mode 100644 index 4ec3bc8f..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/feed_sources.html +++ /dev/null @@ -1,16 +0,0 @@ -{% macro srcs_desc(src) -%} - <div> - {%- if src.codebase -%} - <b>Codebase: {{ src.codebase }}</b><br/> - {% endif %} - <p> - Repository: {{ src.repository }}<br/> - {%- if src.branch -%} - Branch: {{ src.branch }}<br/> - {% endif %} - {%- if src.revision -%} - Revision: {{ src.revision }}<br/> - {% endif %} - </p> - </div> -{%- endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html deleted file mode 100644 index 30c664c7..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/footer.html +++ /dev/null @@ -1,23 +0,0 @@ -<hr /> -<div class="footer"> - -<a href="{{ welcomeurl }}">Welcome Page</a> -<br /> - -<a href="http://buildbot.net/">Buildbot</a>-{{ version }} - -{% if title %} - working for - {% if title_url %} - <a href="{{ title_url }}">{{ title }}</a> - {% else %} - {{ title }} - {% endif %} - project -{% endif %} - -<br /> - -Page built: {{ time }} ({{ tz }}) -</div> - diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html deleted file mode 100644 index 133c465a..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/forms.html +++ /dev/null @@ -1,288 +0,0 @@ - -{% macro cancel_pending_build(cancel_url, authz, short=False, id='all') %} - <form method="post" name="cancel" action="{{ cancel_url }}" class='command cancelbuild' - {{ 'style="display:inline"' if short else '' }}> - {% if not short %} - {% if id == 'all' %} - <p>To cancel all builds, push the 'Cancel' button</p> - <p>To cancel individual builds, click the 'Cancel' buttons above.</p> - {% else %} - <p>To cancel this build, push the 'Cancel' button</p> - {% endif %} - {% endif %} - <input type="hidden" name="id" value="{{ id }}" /> - <input type="submit" value="Cancel" /> - </form> -{% endmacro %} - -{% macro stop_change_builds(stopchange_url, changenum, authz) %} - {% if not changenum %} - <form method="post" action="{{ stopchange_url }}" class='command stopchange'> - {% if changenum %} - <p>To cancel all builds for this change, push the 'Cancel' button</p> - {% else %} - <p>To cancel builds for this builder for a given change, fill out the - following field and push the 'Cancel' button</p> - {% endif %} - - {% if changenum %} - <input type="hidden" name="change" value="{{ changenum }}" /> - {% else %} - <div class="row"> - <span class="label">Change #:</span> - <input type="text" name="change"/> - </div> - {% endif %} - <input type="submit" value="Cancel" /> - </form> - {% endif %} -{% endmacro %} - -{% macro stop_build(stop_url, authz, on_all=False, on_selected=False, builders=[], short=False, label="Build") %} - {% if not short %} - <form method="post" name="stop_build" action="{{ stop_url }}" class='command stopbuild' - {{ 'style="display:inline"' if short else '' }}> - {% if not short %} - {% if on_all %} - <p>To stop all builds, fill out the following field and - push the <i>Stop {{ label }}</i> button</p> - {% elif on_selected %} - <p>To stop selected builds, select the builders, fill out the - following field and push the <i>Stop {{ label }}</i> button</p> - <table> - {% for b in builders %} - <tr> - <td align="center"><input type="checkbox" name="selected" value="{{ b.name }}"></td> - <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td> - </tr> - {% endfor %} - </table> - - {% else %} - <p>To stop this build, fill out the following field and - push the <i>Stop {{ label }}</i> button</p> - {% endif %} - {% endif %} - - {% if not short %} - <div class="row"> - <span class="label">Reason:</span> - <input type="text" name="comments"/> - </div> - {% endif %} - - <input type="submit" value="Stop {{ label }}" /> - </form> - {% endif %} -{% endmacro %} - -{% macro cancel_build(cancel_url, authz, on_all=False, on_selected=False, builders=[], short=False, label="Build") %} - {% if not short %} - <form method="post" name="cancel_build" action="{{ cancel_url }}" class='command cancelbuild' - {{ 'style="display:inline"' if short else '' }}> - {% if not short %} - {% if on_all %} - <p>To cancel all pending builds, fill out the following field and - push the <i>Cancel {{ label }}</i> button</p> - {% elif on_selected %} - <p>To cancel selected pending builds, select the builders, fill out the - following field and push the <i>Cancel {{ label }}</i> button</p> - <table> - {% for b in builders %} - <tr> - <td align="center"><input type="checkbox" name="selected" value="{{ b.name }}"></td> - <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td> - </tr> - {% endfor %} - </table> - - {% else %} - <p>To cancel this pending build, fill out the following field and - push the <i>Cancel {{ label }}</i> button</p> - {% endif %} - {% endif %} - - {% if not short %} - <div class="row"> - <span class="label">Reason:</span> - <input type="text" name="comments"/> - </div> - {% endif %} - - <input type="submit" value="Cancel {{ label }}" /> - </form> - {% endif %} -{% endmacro %} - -{% macro force_build_scheduler_parameter(f, authz, request, sch, default_props) %} - {% if f and not f.hide and (f.fullName != "username" or not authz.authenticated(request)) %} - <div class="row{% for subtype in f.type %} force-{{subtype}}{%endfor%}"{% if f.name %} id="force-{{sch.name}}-{{f.fullName}}"{% endif %}> - {% if 'text' in f.type or 'int' in f.type %} - <span class="label">{{f.label}}</span> - <input type='text' size='{{f.size}}' name='{{f.fullName}}' value='{{default_props[sch.name+"."+f.fullName]}}' /> - {% elif 'bool' in f.type%} - <input type='checkbox' name='checkbox' value='{{f.fullName}}' {{default_props[sch.name+"."+f.fullName]}} /> - <span class="label">{{f.label}}</span> - {% elif 'textarea' in f.type %} - <span class="label">{{f.label}}</span> - <textarea name='{{f.fullName}}' rows={{f.rows}} cols={{f.cols}}>{{default_props[sch.name+"."+f.fullName]}}</textarea> - {% elif 'list' in f.type %} - <span class="label">{{f.label}}</span> - <span class="select"> - <select name='{{f.fullName}}' {{ f.multiple and "multiple" or ""}}> - {% for c in default_props[sch.name+"."+f.fullName+".choices"] %} - <option {{(c in default_props[sch.name+"."+f.fullName]) and "selected" or ""}}>{{c}}</option> - {% endfor %} - </select> - </span> - {% elif 'nested' in f.type %} - {% if f.label %}<span class="label">{{f.label}}</span>{% endif %} - {% for subfield in f.fields %} - {{ force_build_scheduler_parameter(subfield, authz, request, sch, default_props) }} - {% endfor %} - {% endif %} - </div> - {% endif %} -{% endmacro %} - -{% macro force_build_one_scheduler(force_url, authz, request, on_all, on_selected, builders, sch, default_props) %} - <form method="post" name="force_build" action="{{ force_url }}" class="command_forcebuild"> - - <h3>{{ sch.name|e }}</h3> - {% if on_all %} - <p>To force a build on <strong>all Builders</strong>, fill out the following fields - and push the 'Force Build' button</p> - {% elif on_selected %} - <p>To force a build on <strong>certain Builders</strong>, select the - builders, fill out the following fields and push the - 'Force Build' button</p> - - <table> - {% for b in builders %} - {% if b.name in sch.builderNames %} - <tr> - <td align="center"><input type="checkbox" name="selected" value="{{ b.name }}"></td> - <td class="box"><a href="{{ b.link }}">{{ b.name|e }}</a></td> - </tr> - {% endif %} - {% endfor %} - </table> - - {% else %} - <p>To force a build, fill out the following fields and - push the 'Force Build' button</p> - {% endif %} - <input type='hidden' name='forcescheduler' value='{{sch.name}}' /> - <p> - <hr /> - {% if "nightly" in sch.builderNames %} - Set up branch values for Poky branch: <select id ="select_release" - name="build_release" onchange="updateFormBranchInputs(this.value)"> - <option value="master" selected>master</option> - <option value="rocko">rocko</option> - <option value="pyro">pyro</option> - <option value="morty">morty</option> - <option value="krogoth">krogoth</option> - </select> - <hr/> - {% endif %} - - {% for f in sch.all_fields %} - {{ force_build_scheduler_parameter(f, authz, request, sch, default_props) }} - {% endfor %} - - <input type="submit" value="Force Build" /> - </form> -{% endmacro %} -{% macro force_build(force_url, authz, request, on_all=False, on_selected=False, builders=[], force_schedulers={},default_props={}) %} - {% for name, sch in force_schedulers.items() | sort %} - {{ force_build_one_scheduler(force_url, authz, request, on_all, on_selected, builders, sch, default_props=default_props) }} - {% endfor %} - -{% endmacro %} - -{% macro graceful_shutdown(shutdown_url, authz) %} - <form method="post" action="{{ shutdown_url }}" class='command graceful_shutdown'> - - <p>To cause this slave to shut down gracefully when it is idle, - push the 'Graceful Shutdown' button</p> - <input type="submit" value="Graceful Shutdown" /> - </form> -{% endmacro %} - -{% macro pause_slave(pause_url, authz, paused) %} - <form method="post" action="{{ pause_url }}" class='command pause_slave'> - - {% if paused %} - <p>To cause this slave to start running new builds again, - push the 'Unpause Slave' button</p> - {% else %} - <p>To cause this slave to stop running new builds, - push the 'Pause Slave' button</p> - {% endif %} - - {% if paused %} - <input type="submit" value="Unpause Slave" /> - {% else %} - <input type="submit" value="Pause Slave" /> - {% endif %} - </form> -{% endmacro %} - -{% macro clean_shutdown(shutdown_url, authz) %} - <form method="post" action="{{ shutdown_url }}" class='command clean_shutdown'> - <p>To cause this master to shut down cleanly, push the 'Clean Shutdown' button.</p> - <p>No other builds will be started on this master, and the master will - stop once all current builds are finished.</p> - - <input type="submit" value="Clean Shutdown" /> - </form> -{% endmacro %} - -{% macro cancel_clean_shutdown(cancel_shutdown_url, authz) %} - <form method="post" action="{{ cancel_shutdown_url }}" class='command cancel_clean_shutdown'> - <p>To cancel a previously initiated shutdown, push the 'Cancel Shutdown' button.</p> - - <input type="submit" value="Cancel Shutdown" /> - </form> -{% endmacro %} - -{% macro ping_builder(ping_url, authz) %} - <form method="post" action="{{ ping_url }}" class='command ping_builder'> - <p>To ping the buildslave(s), push the 'Ping' button</p> - <input type="submit" value="Ping Builder" /> - </form> -{% endmacro %} - -{% macro rebuild_build(rebuild_url, authz, ss) %} - <form method="post" action="{{ rebuild_url }}" class="command rebuild"> - - {% if on_all %} - <p>To force a build on <strong>all Builders</strong>, fill out the following fields - and push the 'Force Build' button</p> - {% else %} - <p>To force a build, fill out the following fields and - push the 'Force Build' button</p> - {% endif %} - <div class="row"> - <span class="label">Reason for re-running build:</span> - <input type='text' name='comments' /> - </div> - <div class="row"> - Rebuild using: - <select name="useSourcestamp"> - <option value='exact' selected>Exact same revisions</option> - <option value='updated'>Same sourcestamps (ignoring 'got revision')</option> - </select> - </div> - <input type="submit" value="Rebuild" /> - </form> -{% endmacro %} - -{% macro show_users(users_url, authz) %} - <form method="post" action="{{ users_url }}" class='command show_users'> - <p>To show users, press the 'Show Users' button</p> - - <input type="submit" value="Show Users" /> - </form> -{% endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html deleted file mode 100644 index ed44ea10..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid.html +++ /dev/null @@ -1,31 +0,0 @@ -{% extends "layout.html" %} -{% import 'grid_macros.html' as grid with context %} - -{% block content %} - -<h1>Grid View</h1> - -<table class="Grid" border="0" cellspacing="0"> - -<tr> - <td class="title"><a href="{{ title_url }}">{{ title }}</a> - {{ grid.category_title() }} - </td> - - {% for i in range %} - {{ grid.stamp_td(stamps[i], build_triggers[i]) }} - {% endfor %} -</tr> - -{% for builder in builders %} - <tr> - {{ grid.builder_td(builder) }} - {% for build in builder.builds %} - {{ grid.build_td(build) }} - {% endfor %} - </tr> -{% endfor %} - -</table> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html deleted file mode 100644 index 42a1b451..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_macros.html +++ /dev/null @@ -1,65 +0,0 @@ -{% macro category_title() -%} - {% if categories %} - <br> - {% trans categories=categories %} - <b>Category:</b></br> - {% pluralize categories %} - <b>Categories:</b><br/> - {% endtrans %} - {% for c in categories %} - {{ c|e }}<br/> - {% endfor %} - {% endif %} - - {% if branch != ANYBRANCH %} - <br><b>Branch:</b> {{ branch|e or "trunk" }} - {% endif %} -{%- endmacro %} - - -{% macro stamp_td(sourcestamps, trigger) -%} - <td valign="bottom" class="sourcestamp"> - {% for ss in sourcestamps %} - {%- if ss.codebase %}{{ ss.codebase|e }}: {% endif %} - {%- if ss.revision -%} - <br/><b>Commit: </b>{{ ss.revision|shortrev(ss.repository) }} - {%- else %}<br/><b>Commit: </b>latest{% endif %} - {%- if ss.branch %} in {{ ss.branch|e }}{% endif %} - {%- if ss.hasPatch %} [patch]{% endif -%} - (<a href="http://errors.yoctoproject.org/Errors/Latest/Autobuilder/?filter={{ss.revision}}&type=commit">errors</a>, - <a href="https://wiki.yoctoproject.org/wiki/BuildLog#{{trigger.builder}}_{{trigger.id}}_-_{{ss.branch}}_{{ss.revision}}">log</a>) - <br/> - {%- endfor %} - </td> -{%- endmacro %} - -{% macro builder_td(b) -%} - <td valign="middle" style="text-align: center" class="builder {{ b.state }}"> - <a href="{{ b.url }}">{{ b.name }}</a> - {%- if b.state != 'idle' or b.n_pending > 0 -%} - <br/>({{ b.state }} - {%- if b.n_pending > 0 -%} - , plus {{ b.n_pending }} - {%- endif -%} - ) - {%- endif -%} - {%- if b.time %}<br/><b>Time: </b> {{ b.time }} {% endif %} - </td> -{%- endmacro %} - -{% macro build_td(build) -%} -{% if build %} - <td valign="top" class="build {{ build.class }}" style="text-align: left" style="white-space: nowrap" valign="bottom" > - {%- if build.release_name %}<br/><b>RELEASE NAME:</b> {{ build.release_name }}{% endif %} - {%- if build.branchshortname %}<br/><b>Branch:</b> {{ build.branchshortname }} {% endif %} - {%- if build.repository %}<br/><b>Repo: </b> - {%- if build.cgiturl %} <a href="{{ build.cgiturl }}"> {% endif %} - {{ build.repository }} - {%- if build.cgiturl %} </a> {% endif %} - {% endif %} - <br/><b>Build:</b> <a href="{{ build.url }}">{{ build.text|join('<br/>') }}</a> - </td> -{% else %} - <td class="build"> </td> -{% endif %} -{%- endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html deleted file mode 100644 index 9b6cadad..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/grid_transposed.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends "layout.html" %} -{% import 'grid_macros.html' as grid with context %} - -{% block content %} - -<h1>Transposed Grid View</h1> - -<table class="Grid" border="0" cellspacing="0"> - -<tr> - <td class="title"><a href="{{ title_url }}">{{ title }}</a> - {{ grid.category_title() }} - </td> - {% for builder in builders %} - {{ grid.builder_td(builder) }} - {% endfor %} -</tr> - -{% for i in range %} - <tr> - {{ grid.stamp_td(stamps[i], build_triggers[i]) }} - {% for b in builder_builds %} - {{ grid.build_td(b[i]) }} - {% endfor %} - </tr> -{% endfor %} - -</table> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html deleted file mode 100644 index 63c155b9..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/jsonhelp.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends "layout.html" %} -{% block content %} - -<p>{{ text }}</p> -<h2>More Help:</h2> - -{% if level != 1 %} -<p><a href="../help">Parent's Help</a></p> -{% endif %} - -{% if children %} -<p>Child Nodes</p> -<ul> -{% for child in children %} - <li><a href="{{ child|e }}">{{ child|e }}</a> - (<a href="{{ child|e }}/help">{{ child|e }}/help</a>) - </li> -{% endfor %} -</ul> -{% endif %} - -<h2>Flags:</h2> -{{ flags }} - -<h2>Examples:</h2> -{{ examples }} - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html deleted file mode 100644 index 01dfb80c..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/layout.html +++ /dev/null @@ -1,90 +0,0 @@ -{%- block doctype -%} -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" -"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -{% endblock %} -<html xmlns="http://www.w3.org/1999/xhtml"> - <head> - {% block head %} - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - {% if metatags %} - {{ metatags }} - {% endif %} - {% if refresh %} - <meta http-equiv="refresh" content="{{ refresh|e }}"/> - {% endif %} - <title>{{ pageTitle|e }}</title> - <link rel="stylesheet" href="{{ stylesheet }}" type="text/css" /> - <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ path_to_root }}rss"> - <link rel="shortcut icon" href="{{ path_to_root }}favicon.ico"> - {% endblock %} - </head> - <body class="interface"> - {% block header -%} - <div class="header"> - <a href="{{ path_to_root or '.' }}">Home</a> - {% if authz.advertiseAction('view', request) %} - - <a href="{{ path_to_root }}waterfall">Waterfall</a> - <a href="{{ path_to_root }}grid">Grid</a> - <a href="{{ path_to_root }}tgrid">T-Grid</a> - <a href="{{ path_to_root }}console">Console</a> - <a href="{{ path_to_root }}builders">Builders</a> - <a href="{{ path_to_root }}one_line_per_build">Recent Builds</a> - <a href="{{ path_to_root }}buildslaves">Buildslaves</a> - <a href="{{ path_to_root }}changes">Changesources</a> - {% if authz.advertiseAction('showUsersPage', request) %} - <a href="{{ path_to_root }}users">Users</a> - {% endif %} - - <a href="{{ path_to_root }}json/help">JSON API</a> - - <a href="{{ path_to_root }}about">About</a> - {% endif %} - <div class="auth"> - {% if authz.authenticated(request) %} - {{ authz.getUsernameHTML(request) }} - |<a href="{{ path_to_root }}logout">Logout</a> - {% elif authz.useHttpHeader and authz.httpLoginUrl %} - <a href="{{ authz.httpLoginUrl }}">Login</a> - {% elif authz.auth %} - <form method="post" name="login" action="{{ path_to_root }}login"> - <input type="text" name="username" size=10 /> - <input type="password" name="passwd" size=10 /> - <input type="submit" value="login" /> - </form> - {% endif %} - </div> - </div> - {% endblock %} - - {%- block barecontent -%} - <hr/> - - {% if alert_msg != "" %} - <div class="alert"> - {{ alert_msg }} - </div> - {% endif %} - - <div class="content"> - {%- block content -%} - {%- endblock -%} - </div> - {%- endblock -%} - - {%- block footer -%} - <div class="footer" style="clear:both"> - <hr/> - <a href="http://buildbot.net/">BuildBot</a> ({{version}}) - {% if title -%} - working for the - {%- if title_url -%} - <a href="{{ title_url }}">{{ title }}</a> - {%- else -%} - {{ title }} - {%- endif -%} - project. - {%- endif -%} - <br/> - Page built: <b>{{ time }}</b> ({{ tz }}) - </div> - {% endblock -%} - </body> -</html> diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html deleted file mode 100644 index 116bbd6a..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/logs.html +++ /dev/null @@ -1,23 +0,0 @@ -{%- macro page_header(pageTitle, path_to_root, texturl) -%} -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - <html> - <head><title>{{ pageTitle }}</title> - <link rel="stylesheet" href="{{ path_to_root }}default.css" type="text/css" /> - </head> - <body class='log'> - <a href="{{ texturl }}">(view as text)</a><br/> - <pre> -{%- endmacro -%} - -{%- macro chunks(entries) -%} -{%- for entry in entries -%} - <span class="{{ entry.type }}">{{ entry.text|e }}</span> -{%- endfor -%} -{%- endmacro -%} - -{%- macro page_footer() -%} -</pre> -</body> -</html> -{%- endmacro -%} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html deleted file mode 100644 index d2484465..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuild.html +++ /dev/null @@ -1,36 +0,0 @@ -{% extends "layout.html" %} -{% from 'build_line.html' import build_table %} -{% import 'forms.html' as forms %} - -{% block content %} -<h1>Last {{ num_builds }} finished builds: {{ branches|join(', ')|e }}</h1> - -{% if builders %} - <p>of builders: {{ builders|join(", ")|e }}</p> -{% endif %} - -<div class="column"> - -{{ build_table(builds, True) }} - -</div> -<div class="column"> - -{% if num_building > 0 %} - {% if authz.advertiseAction('stopBuild', request) %} - <h2>Stop All Builds</h2> - {{ forms.stop_build("builders/_all/stopall", authz, on_all=True, label='All Builds') }} - {% endif %} -{% endif %} - -{% if num_online > 0 %} - {% if authz.advertiseAction('forceAllBuilds', request) %} - <h2>Force All Builds</h2> - {{ forms.force_build("builders/_all/forceall", authz, request, True, force_schedulers=force_schedulers, default_props=default_props) }} - {% endif %} -{% endif %} - - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html deleted file mode 100644 index 051501f2..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/onelineperbuildonebuilder.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "layout.html" %} -{% from 'build_line.html' import build_line %} - -{% block content %} - -<h1>Last {{ num_builds }} builds of builder {{ builder_name|e }}: - {{ branches|join(', ')|e }} -</h1> - -<ul> -{% for b in builds %} - <li>{{ build_line(b) }}</li> -{% else %} - <li>No matching builds found</li> -{% endfor %} -</ul> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html deleted file mode 100644 index 87a87a02..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/revmacros.html +++ /dev/null @@ -1,35 +0,0 @@ -{# both macro pairs must have the same signature #} - -{% macro id_replace(rev, url) -%} - <span class="revision" title="Revision {{ rev }}"><a href="{{ url }}"> - {%- if rev|length > 40 %}{{ rev[:40] }}... - {%- else %}{{ rev }} - {%- endif -%} - </a></span> -{%- endmacro %} - -{% macro shorten_replace(short, rev, url) %} - <div class="revision"> - <div class="short" title="Revision {{ rev }}"> - <a href="{{ url }}">{{ short }}...</a> - </div> - <div class="full"> - <a href="{{ url }}">{{ rev }}</a> - </div> - </div> -{% endmacro %} - -{% macro id(rev, url) -%} - <span class="revision" title="Revision {{ rev }}"> - {%- if rev|length > 40 %}{{ rev[:40] }}... - {%- else %}{{ rev }} - {%- endif -%} - </span> -{%- endmacro %} - -{% macro shorten(short, rev, url) %} - <div class="revision"> - <div class="short" title="Revision {{ rev }}">{{ short }}...</div> - <div class="full">{{ rev }}</div> - </div> -{% endmacro %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html deleted file mode 100644 index 561973e4..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/root.html +++ /dev/null @@ -1,61 +0,0 @@ -{% extends 'layout.html' %} -{% import 'forms.html' as forms %} - -{% block content %} - -<h1>Welcome to the Buildbot -{%- if title -%} - for the - {%- if title_url -%} - <a href="{{ title_url }}">{{ title }}</a> - {%- else -%} - {{ title }} - {%- endif -%} - project -{%- endif -%} -! -</h1> - -<div class="column"> - -<ul> - {% set item_class=cycler('alt', '') %} - - <li class="{{ item_class.next() }}">The <a href="waterfall">Waterfall Display</a> will give you a - time-oriented summary of recent buildbot activity. <a href="waterfall/help">Waterfall Help.</a></li> - - <li class="{{ item_class.next() }}">The <a href="grid">Grid Display</a> will give you a - developer-oriented summary of recent buildbot activity.</li> - - <li class="{{ item_class.next() }}">The <a href="tgrid">Transposed Grid Display</a> presents - the same information as the grid, but lists the revisions down the side.</li> - - <li class="{{ item_class.next() }}">The <a href="console">Console</a> presents - a user-oriented status page.</li> - - <li class="{{ item_class.next() }}">The <a href="builders">Builders</a> and their most recent builds are - here.</li> - - <li class="{{ item_class.next() }}"><a href="one_line_per_build">Recent Builds</a> are summarized here, one - per line.</li> - - <li class="{{ item_class.next() }}"><a href="buildslaves">Buildslave</a> information</li> - <li class="{{ item_class.next() }}"><a href="changes">Changesource</a> information.</li> - - <li class="{{ item_class.next() }}"><a href="about">About</a> this Buildbot</li> -</ul> - -{%- if authz.advertiseAction('cleanShutdown', request) -%} -{%- if shutting_down -%} -Master is shutting down<br/> -{{ forms.cancel_clean_shutdown(cancel_shutdown_url, authz) }} -{%- else -%} -{{ forms.clean_shutdown(shutdown_url, authz) }} -{%- endif -%} -{%- endif -%} - -<p><i>This and other pages can be overridden and customized.</i></p> - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html deleted file mode 100644 index 70dac7ae..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/testresult.html +++ /dev/null @@ -1,34 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1> - Builder <a href="{{ builder_link }}">{{ b.getBuilder().getName() }}</a> - build <a href="{{ build_link }}">#{{ b.getNumber() }}</a> - test <a href="">{{ '.'.join(tr.getName()) }}</a> -</h1> - -<div class="column"> - - <h2>Result</h2> - <p class="{{ result_css }} result"> - {{ result_word }} - {%- set text = tr.getText() -%} - {%- if text is string %}{{ text|e }} - {%- else %}{{ text|join(" ")|e }}{% endif -%} - </p> - -<h2>Logs</h2> -<ul> -{% for l in logs %} - <h3>Log: {{ l.name|e }}</h3> - <samp><pre>{{ l.log|e }}</pre></samp> - </br> -{% else %} - <li class="alt">- No logs -</li> -{% endfor %} -</ul> - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html deleted file mode 100644 index eb136175..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/user.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>User: {{ user_identifier|e }}</h1> - -<div class="column"> - -<table class="info"> - -<tr> - <th>Attribute Type</th> - <th>Attribute Value</th> -</tr> - -{% for attr in user %} - <tr class="{{ loop.cycle('alt','') }}"> - - <td>{{ attr|e }}</td> - <td>{{ user[attr]|e }}</td> - - </tr> -{% endfor %} - -</table> - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html deleted file mode 100644 index 5cb2dafc..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/users.html +++ /dev/null @@ -1,27 +0,0 @@ -{% extends "layout.html" %} - -{% block content %} - -<h1>Users</h1> - -<table class="info"> - -<tr> - <th>Uid</th> - <th>Identifier</th> -</tr> - -{% for user in users %} - <tr class="{{ loop.cycle('alt','') }}"> - - <td><b><a href="{{ user.user_link }}">{{ user.uid }}</a></b></td> - <td>{{ user.identifier|e }}</td> - - </tr> -{% endfor %} - -</table> - -</div> - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html deleted file mode 100644 index e380406e..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfall.html +++ /dev/null @@ -1,66 +0,0 @@ -{% extends "layout.html" %} -{% from "box_macros.html" import box %} - -{% block content %} - -<div> - <h1 style="display: inline;">Waterfall</h1> - <a style="float: right;" href="{{ help_url }}">waterfall help</a> -</div> - -<table border="0" cellspacing="0"> - -<tr class="LastBuild"> - <td align="right" colspan="2" class="Project"> - last build - </td> - -{% for b in builders %} - <td align="center" class="{{ b.top_class }}"> - <a href="{{ b.url }}">{{ b.name }}</a><br/> - {{ " ".join(b.top) }} - </td> -{% endfor %} -</tr> - -<tr class="Activity"> -<td align="right" colspan="2">current activity</td> - -{% for b in builders %} - <td align="center" class="{{ b.status_class }}"> - {{ "<br/>".join(b.status) }} - </td> -{% endfor %} -</tr> - -<tr> -<td align="center" class="Time">{{ tz }}</td> -<td align="center" class="Change"><a href="{{ changes_url }}">changes</a></td> - -{% for b in builders %} - <td align="center" class="Builder"><a href="{{ b.url }}">{{ b.name }}</a></td> -{% endfor %} -</tr> - -{# waterfall contents goes here #} -{% for i in range(gridlen) -%} - <tr> - {% for strip in grid -%} - {%- if strip[i] -%}{{ box(**strip[i]) }} - {%- elif no_bubble -%}{{ box() }} - {%- endif -%} - {%- endfor -%} - </tr> -{% endfor %} - -</table> - -{% if nextpage %} - <a href="{{ nextpage }}">next page</a> -{% endif %} - -{% if no_reload_page %} - <a href="{{ no_reload_page }}">Stop Reloading</a> -{% endif %} - -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html deleted file mode 100644 index c0e5ec6e..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/templates/waterfallhelp.html +++ /dev/null @@ -1,140 +0,0 @@ -{% extends "layout.html" %} -{% block content %} - -<form action="../waterfall" method="get"> - -<h1>The Waterfall Display</h1> - -<p>The Waterfall display can be controlled by adding query arguments to the -URL. For example, if your Waterfall is accessed via the URL -<tt>http://buildbot.example.org:8080</tt>, then you could add a -<tt>branch=</tt> argument (described below) by going to -<tt>http://buildbot.example.org:8080?branch=beta4</tt> instead. Remember that -query arguments are separated from each other with ampersands, but they are -separated from the main URL with a question mark, so to add a -<tt>branch=</tt> and two <tt>builder=</tt> arguments, you would use -<tt>http://buildbot.example.org:8080?branch=beta4&builder=unix&builder=macos</tt>.</p> - -<h2>Limiting the Displayed Interval</h2> - -<p>The <tt>last_time=</tt> argument is a unix timestamp (seconds since the -start of 1970) that will be used as an upper bound on the interval of events -displayed: nothing will be shown that is more recent than the given time. -When no argument is provided, all events up to and including the most recent -steps are included.</p> - -<p>The <tt>first_time=</tt> argument provides the lower bound. No events will -be displayed that occurred <b>before</b> this timestamp. Instead of providing -<tt>first_time=</tt>, you can provide <tt>show_time=</tt>: in this case, -<tt>first_time</tt> will be set equal to <tt>last_time</tt> minus -<tt>show_time</tt>. <tt>show_time</tt> overrides <tt>first_time</tt>.</p> - -<p>The display normally shows the latest 200 events that occurred in the -given interval, where each timestamp on the left hand edge counts as a single -event. You can add a <tt>num_events=</tt> argument to override this this.</p> - -<h2>Showing non-Build events</h2> - -<p>By passing <tt>show_events=true</tt>, you can add the "buildslave -attached", "buildslave detached", and "builder reconfigured" events that -appear in-between the actual builds.</p> - -<p> -<input type="checkbox" name="show_events" value="true" -{% if show_events_checked %} checked="checked" {% endif %}/> -Show non-Build events -</p> - -<h2>Showing only Certain Branches</h2> - -<p>If you provide one or more <tt>branch=</tt> arguments, the display will be -limited to builds that used one of the given branches. If no <tt>branch=</tt> -arguments are given, builds from all branches will be displayed.</p> - -Erase the text from these "Show Branch:" boxes to remove that branch filter. - -{% if branches %} -<table> - {% for b in branches %} - <tr> - <td>Show Branch: - <input type="text" name="branch" value="{{ b|e }}"/> - </td> - </tr> - {% endfor %} -</table> -{% endif %} - -<h2>Limiting the Builders that are Displayed</h2> - -<p>By adding one or more <tt>builder=</tt> arguments, the display will be -limited to showing builds that ran on the given builders. This serves to -limit the display to the specific named columns. If no <tt>builder=</tt> -arguments are provided, all Builders will be displayed.</p> - -<p>To view a Waterfall page with only a subset of Builders displayed, select -the Builders you are interested in here.</p> - -<table> -{% for bn in all_builders %} - <tr><td><input type="checkbox" name="builder" value="{{ bn }}" - {% if bn in show_builders %}checked="checked"{% endif %} /> - </td><td>{{bn}}</td></tr> -{% endfor %} -</table> - -<h2>Limiting the Builds that are Displayed</h2> - -<p>By adding one or more <tt>committer=</tt> arguments, the display will be -limited to showing builds that were started by the given committer. If no -<tt>committer=</tt> arguments are provided, all builds will be displayed.</p> - -<p>To view a Waterfall page with only a subset of Builds displayed, select -the committers your are interested in here.</p> - -Erase the text from these "Show Committer:" boxes to remove that filter. - -{% if committers %} - <table> - {% for cn in committers %} - <tr> - <td> - Show Committer: <input type="text" name="committer" value="{{ cn }}"> - </td> - </tr> - {% endfor %} - </table> -{% endif %} - -<h2>Showing only the Builders with failures</h2> - -<p>By adding the <tt>failures_only=true</tt> argument, the display will be limited -to showing builders that are currently failing. A builder is considered -failing if the last finished build was not successful, a step in the current -build(s) failed, or if the builder is offline.</p> - -<p> - <input type="checkbox" name="failures_only" value="true" - {% if failures_only %}checked="checked"{% endif %}/> - Show failures only -</p> - -<h2>Auto-reloading the Page</h2> - -<p>Adding a <tt>reload=</tt> argument will cause the page to automatically -reload itself after that many seconds.</p> - -<table> -{% for value, name in times %} - <tr><td><input type="radio" name="reload" value="{{ value|e }}" - {% if value == current_reload_time %}checked="checked"{% endif %}/> - </td><td>{{ name|e }}</td></tr> -{% endfor %} -</table> - - -<h2>Reload Waterfall Page</h2> - -<input type="submit" value="View Waterfall" /> -</form> -{% endblock %} diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py deleted file mode 100644 index 52622982..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/tests.py +++ /dev/null @@ -1,84 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -import urllib -from buildbot.status.web.base import HtmlResource, path_to_builder, \ - path_to_build, css_classes -from buildbot.status.builder import Results - -# /builders/$builder/builds/$buildnum/steps/$stepname -class StatusResourceBuildTest(HtmlResource): - pageTitle = "Test Result" - addSlash = True - - def __init__(self, build_status, test_result): - HtmlResource.__init__(self) - self.status = build_status - self.test_result = test_result - - def content(self, req, cxt): - tr = self.test_result - b = self.status - - cxt['b'] = self.status - logs = cxt['logs'] = [] - for lname, log in tr.getLogs().items(): - if isinstance(log, str): - log = log.decode('utf-8') - logs.append({'name': lname, - 'log': log, - 'link': req.childLink("logs/%s" % urllib.quote(lname)) }) - - cxt['text'] = tr.text - cxt['result_word'] = Results[tr.getResults()] - cxt.update(dict(builder_link = path_to_builder(req, b.getBuilder()), - build_link = path_to_build(req, b), - result_css = css_classes[tr.getResults()], - b = b, - tr = tr)) - - template = req.site.buildbot_service.templates.get_template("testresult.html") - return template.render(**cxt) - - def getChild(self, path, req): - # if path == "logs": - # return LogsResource(self.step_status) #TODO we need another class - return HtmlResource.getChild(self, path, req) - - - -# /builders/$builder/builds/$buildnum/steps -class TestsResource(HtmlResource): - addSlash = True - nameDelim = '.' # Test result have names like a.b.c - - def __init__(self, build_status): - HtmlResource.__init__(self) - self.build_status = build_status - - def content(self, req, ctx): - # TODO list the tests - return "subpages show data for each test" - - def getChild(self, path, req): - tpath = None - if path: - tpath = tuple(path.split(self.nameDelim)) - if tpath: - tr = self.build_status.getTestResults().get(tpath) - if tr: - return StatusResourceBuildTest(self.build_status, tr) - return HtmlResource.getChild(self, path, req) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py deleted file mode 100644 index 953ae68f..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/users.py +++ /dev/null @@ -1,90 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -import urllib -from twisted.internet import defer -from twisted.web.util import redirectTo -from buildbot.status.web.base import HtmlResource, path_to_authzfail, \ - path_to_root, ActionResource - -class UsersActionResource(ActionResource): - - def __init__(self): - self.action = "showUsersPage" - - @defer.inlineCallbacks - def performAction(self, req): - res = yield self.getAuthz(req).actionAllowed('showUsersPage', req) - if not res: - defer.returnValue(path_to_authzfail(req)) - return - # show the table - defer.returnValue(path_to_root(req) + "users") - -# /users/$uid -class OneUserResource(HtmlResource): - addSlash = False - def __init__(self, uid): - HtmlResource.__init__(self) - self.uid = int(uid) - - def getPageTitle (self, req): - return "Buildbot User: %s" % self.uid - - def content(self, request, ctx): - status = self.getStatus(request) - - d = status.master.db.users.getUser(self.uid) - def cb(usdict): - ctx['user_identifier'] = usdict['identifier'] - user = ctx['user'] = {} - for attr in usdict: - if attr not in ['uid', 'identifier', 'bb_password']: - user[attr] = usdict[attr] - - template = request.site.buildbot_service.templates.get_template("user.html") - data = template.render(**ctx) - return data - d.addCallback(cb) - return d - -# /users -class UsersResource(HtmlResource): - pageTitle = "Users" - addSlash = True - - def __init__(self): - HtmlResource.__init__(self) - - def getChild(self, path, req): - return OneUserResource(path) - - @defer.inlineCallbacks - def content(self, req, ctx): - res = yield self.getAuthz(req).actionAllowed('showUsersPage', req) - if not res: - defer.returnValue(redirectTo(path_to_authzfail(req), req)) - return - - s = self.getStatus(req) - - usdicts = yield s.master.db.users.getUsers() - users = ctx['users'] = usdicts - - for user in users: - user['user_link'] = req.childLink(urllib.quote(str(user['uid']), '')) - template = req.site.buildbot_service.templates.get_template( - "users.html") - defer.returnValue(template.render(**ctx)) diff --git a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py b/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py deleted file mode 100644 index 681c5768..00000000 --- a/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/status/web/waterfall.py +++ /dev/null @@ -1,813 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - - -from zope.interface import implements -from twisted.python import log, components -from twisted.internet import defer -import urllib - -import time, locale -import operator - -from buildbot import interfaces, util -from buildbot.status import builder, buildstep, build -from buildbot.changes import changes - -from buildbot.status.web.base import Box, HtmlResource, IBox, ICurrentBox, \ - ITopBox, build_get_class, path_to_build, path_to_step, path_to_root, \ - map_branches - - -def earlier(old, new): - # minimum of two things, but "None" counts as +infinity - if old: - if new < old: - return new - return old - return new - -def later(old, new): - # maximum of two things, but "None" counts as -infinity - if old: - if new > old: - return new - return old - return new - - -class CurrentBox(components.Adapter): - # this provides the "current activity" box, just above the builder name - implements(ICurrentBox) - - def formatETA(self, prefix, eta): - if eta is None: - return [] - if eta < 60: - return ["< 1 min"] - eta_parts = ["~"] - eta_secs = eta - if eta_secs > 3600: - eta_parts.append("%d hrs" % (eta_secs / 3600)) - eta_secs %= 3600 - if eta_secs > 60: - eta_parts.append("%d mins" % (eta_secs / 60)) - eta_secs %= 60 - abstime = time.strftime("%H:%M", time.localtime(util.now()+eta)) - return [prefix, " ".join(eta_parts), "at %s" % abstime] - - def getBox(self, status, brcounts): - # getState() returns offline, idle, or building - state, builds = self.original.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 = self.original.getName() - for s in status.getSchedulers(): - if builderName in s.listBuilderNames(): - upcoming.extend(s.getPendingBuildTimes()) - if state == "idle" and upcoming: - state = "waiting" - - if state == "building": - text = ["building"] - if builds: - for b in builds: - eta = b.getETA() - text.extend(self.formatETA("ETA in", eta)) - elif state == "offline": - text = ["offline"] - elif state == "idle": - text = ["idle"] - elif state == "waiting": - text = ["waiting"] - else: - # just in case I add a state and forget to update this - text = [state] - - # 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) - brcount = brcounts[builderName] - if brcount: - text.append("%d pending" % brcount) - for t in sorted(upcoming): - if t is not None: - eta = t - util.now() - text.extend(self.formatETA("next in", eta)) - return Box(text, class_="Activity " + state) - -components.registerAdapter(CurrentBox, builder.BuilderStatus, ICurrentBox) - - -class BuildTopBox(components.Adapter): - # this provides a per-builder box at the very top of the display, - # showing the results of the most recent build - implements(IBox) - - def getBox(self, req): - assert interfaces.IBuilderStatus(self.original) - branches = [b for b in req.args.get("branch", []) if b] - builder = self.original - builds = list(builder.generateFinishedBuilds(map_branches(branches), - num_builds=1)) - if not builds: - return Box(["none"], class_="LastBuild") - b = builds[0] - url = path_to_build(req, b) - text = b.getText() - tests_failed = b.getSummaryStatistic('tests-failed', operator.add, 0) - if tests_failed: text.extend(["Failed tests: %d" % tests_failed]) - # TODO: maybe add logs? - class_ = build_get_class(b) - return Box(text, urlbase=url, class_="LastBuild %s" % class_) -components.registerAdapter(BuildTopBox, builder.BuilderStatus, ITopBox) - -class BuildBox(components.Adapter): - # this provides the yellow "starting line" box for each build - implements(IBox) - - def getBox(self, req): - b = self.original - number = b.getNumber() - url = path_to_build(req, b) - reason = b.getReason() - template = req.site.buildbot_service.templates.get_template("box_macros.html") - text = template.module.build_box(reason=reason,url=url,number=number) - class_ = "start" - if b.isFinished() and not b.getSteps(): - # the steps have been pruned, so there won't be any indication - # of whether it succeeded or failed. - class_ = build_get_class(b) - return Box([text], class_="BuildStep " + class_) -components.registerAdapter(BuildBox, build.BuildStatus, IBox) - -class StepBox(components.Adapter): - implements(IBox) - - def getBox(self, req): - urlbase = path_to_step(req, self.original) - text = self.original.getText() - if text is None: - log.msg("getText() gave None", urlbase) - text = [] - text = text[:] - logs = self.original.getLogs() - - cxt = dict(text=text, logs=[], urls=[], stepinfo=self) - - for num in range(len(logs)): - name = logs[num].getName() - if logs[num].hasContents(): - url = urlbase + "/logs/%s" % urllib.quote(name) - else: - url = None - cxt['logs'].append(dict(name=name, url=url)) - - for name, target in self.original.getURLs().items(): - cxt['urls'].append(dict(link=target,name=name)) - - template = req.site.buildbot_service.templates.get_template("box_macros.html") - text = template.module.step_box(**cxt) - - class_ = "BuildStep " + build_get_class(self.original) - return Box(text, class_=class_) -components.registerAdapter(StepBox, buildstep.BuildStepStatus, IBox) - - -class EventBox(components.Adapter): - implements(IBox) - - def getBox(self, req): - text = self.original.getText() - class_ = "Event" - return Box(text, class_=class_) -components.registerAdapter(EventBox, builder.Event, IBox) - - -class Spacer: - implements(interfaces.IStatusEvent) - - def __init__(self, start, finish): - self.started = start - self.finished = finish - - def getTimes(self): - return (self.started, self.finished) - def getText(self): - return [] - -class SpacerBox(components.Adapter): - implements(IBox) - - def getBox(self, req): - #b = Box(["spacer"], "white") - b = Box([]) - b.spacer = True - return b -components.registerAdapter(SpacerBox, Spacer, IBox) - -def insertGaps(g, showEvents, lastEventTime, idleGap=2): - debug = False - - e = g.next() - starts, finishes = e.getTimes() - if debug: log.msg("E0", starts, finishes) - if finishes == 0: - finishes = starts - if debug: log.msg("E1 finishes=%s, gap=%s, lET=%s" % \ - (finishes, idleGap, lastEventTime)) - if finishes is not None and finishes + idleGap < lastEventTime: - if debug: log.msg(" spacer0") - yield Spacer(finishes, lastEventTime) - - followingEventStarts = starts - if debug: log.msg(" fES0", starts) - yield e - - while 1: - e = g.next() - if not showEvents and isinstance(e, builder.Event): - continue - starts, finishes = e.getTimes() - if debug: log.msg("E2", starts, finishes) - if finishes == 0: - finishes = starts - if finishes is not None and finishes + idleGap < followingEventStarts: - # there is a gap between the end of this event and the beginning - # of the next one. Insert an idle event so the waterfall display - # shows a gap here. - if debug: - log.msg(" finishes=%s, gap=%s, fES=%s" % \ - (finishes, idleGap, followingEventStarts)) - yield Spacer(finishes, followingEventStarts) - yield e - followingEventStarts = starts - if debug: log.msg(" fES1", starts) - - -class WaterfallHelp(HtmlResource): - pageTitle = "Waterfall Help" - - def __init__(self, categories=None): - HtmlResource.__init__(self) - self.categories = categories - - def content(self, request, cxt): - status = self.getStatus(request) - - cxt['show_events_checked'] = request.args.get("show_events", ["false"])[0].lower() == "true" - cxt['branches'] = [b for b in request.args.get("branch", []) if b] - cxt['failures_only'] = request.args.get("failures_only", ["false"])[0].lower() == "true" - cxt['committers'] = [c for c in request.args.get("committer", []) if c] - - # this has a set of toggle-buttons to let the user choose the - # builders - show_builders = request.args.get("show", []) - show_builders.extend(request.args.get("builder", [])) - cxt['show_builders'] = show_builders - cxt['all_builders'] = status.getBuilderNames(categories=self.categories) - - # a couple of radio-button selectors for refresh time will appear - # just after that text - times = [("none", "None"), - ("60", "60 seconds"), - ("300", "5 minutes"), - ("600", "10 minutes"), - ] - current_reload_time = request.args.get("reload", ["none"]) - if current_reload_time: - current_reload_time = current_reload_time[0] - if current_reload_time not in [t[0] for t in times]: - times.insert(0, (current_reload_time, current_reload_time) ) - - cxt['times'] = times - cxt['current_reload_time'] = current_reload_time - - template = request.site.buildbot_service.templates.get_template("waterfallhelp.html") - return template.render(**cxt) - - -class ChangeEventSource(object): - "A wrapper around a list of changes to supply the IEventSource interface" - def __init__(self, changes): - self.changes = changes - # we want them in newest-to-oldest order - self.changes.reverse() - - def eventGenerator(self, branches, categories, committers, minTime): - for change in self.changes: - if branches and change.branch not in branches: - continue - if categories and change.category not in categories: - continue - if committers and change.author not in committers: - continue - if minTime and change.when < minTime: - continue - yield change - -class WaterfallStatusResource(HtmlResource): - """This builds the main status page, with the waterfall display, and - all child pages.""" - - def __init__(self, categories=None, num_events=200, num_events_max=None): - HtmlResource.__init__(self) - self.categories = categories - self.num_events=num_events - self.num_events_max=num_events_max - self.putChild("help", WaterfallHelp(categories)) - - def getPageTitle(self, request): - status = self.getStatus(request) - p = status.getTitle() - if p: - return "BuildBot: %s" % p - else: - return "BuildBot" - - def getChangeManager(self, request): - # TODO: this wants to go away, access it through IStatus - return request.site.buildbot_service.getChangeSvc() - - 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 isSuccess(self, builderStatus): - # Helper function to return True if the builder is not failing. - # The function will return false if the current state is "offline", - # the last build was not successful, or if a step from the current - # build(s) failed. - - # Make sure the builder is online. - if builderStatus.getState()[0] == 'offline': - return False - - # Look at the last finished build to see if it was success or not. - lastBuild = builderStatus.getLastFinishedBuild() - if lastBuild and lastBuild.getResults() != builder.SUCCESS: - return False - - # Check all the current builds to see if one step is already - # failing. - currentBuilds = builderStatus.getCurrentBuilds() - if currentBuilds: - for build in currentBuilds: - for step in build.getSteps(): - if step.getResults()[0] == builder.FAILURE: - return False - - # The last finished build was successful, and all the current builds - # don't have any failed steps. - return True - - def content(self, request, ctx): - status = self.getStatus(request) - master = request.site.buildbot_service.master - - # before calling content_with_db_data, make a bunch of database - # queries. This is a sick hack, but beats rewriting the entire - # waterfall around asynchronous calls - - results = {} - - # recent changes - changes_d = master.db.changes.getRecentChanges(40) - def to_changes(chdicts): - return defer.gatherResults([ - changes.Change.fromChdict(master, chdict) - for chdict in chdicts ]) - changes_d.addCallback(to_changes) - def keep_changes(changes): - results['changes'] = changes - changes_d.addCallback(keep_changes) - - # build request counts for each builder - allBuilderNames = status.getBuilderNames(categories=self.categories) - brstatus_ds = [] - brcounts = {} - def keep_count(statuses, builderName): - brcounts[builderName] = len(statuses) - for builderName in allBuilderNames: - builder_status = status.getBuilder(builderName) - d = builder_status.getPendingBuildRequestStatuses() - d.addCallback(keep_count, builderName) - brstatus_ds.append(d) - - # wait for it all to finish - d = defer.gatherResults([ changes_d ] + brstatus_ds) - def call_content(_): - return self.content_with_db_data(results['changes'], - brcounts, request, ctx) - d.addCallback(call_content) - return d - - def content_with_db_data(self, changes, brcounts, request, ctx): - status = self.getStatus(request) - ctx['refresh'] = self.get_reload_time(request) - - # we start with all Builders available to this Waterfall: this is - # limited by the config-file -time categories= argument, and defaults - # to all defined Builders. - allBuilderNames = status.getBuilderNames(categories=self.categories) - builders = [status.getBuilder(name) for name in allBuilderNames] - - # but if the URL has one or more builder= arguments (or the old show= - # argument, which is still accepted for backwards compatibility), we - # use that set of builders instead. We still don't show anything - # outside the config-file time set limited by categories=. - showBuilders = request.args.get("show", []) - showBuilders.extend(request.args.get("builder", [])) - if showBuilders: - builders = [b for b in builders if b.name in showBuilders] - - # now, if the URL has one or category= arguments, use them as a - # filter: only show those builders which belong to one of the given - # categories. - showCategories = request.args.get("category", []) - if showCategories: - builders = [b for b in builders if b.category in showCategories] - - # If the URL has the failures_only=true argument, we remove all the - # builders that are not currently red or won't be turning red at the end - # of their current run. - failuresOnly = request.args.get("failures_only", ["false"])[0] - if failuresOnly.lower() == "true": - builders = [b for b in builders if not self.isSuccess(b)] - - (changeNames, builderNames, timestamps, eventGrid, sourceEvents) = \ - self.buildGrid(request, builders, changes) - - # start the table: top-header material - locale_enc = locale.getdefaultlocale()[1] - if locale_enc is not None: - locale_tz = unicode(time.tzname[time.localtime()[-1]], locale_enc) - else: - locale_tz = unicode(time.tzname[time.localtime()[-1]]) - ctx['tz'] = locale_tz - ctx['changes_url'] = request.childLink("../changes") - - bn = ctx['builders'] = [] - - for name in builderNames: - builder = status.getBuilder(name) - top_box = ITopBox(builder).getBox(request) - current_box = ICurrentBox(builder).getBox(status, brcounts) - bn.append({'name': name, - 'url': request.childLink("../builders/%s" % urllib.quote(name, safe='')), - 'top': top_box.text, - 'top_class': top_box.class_, - 'status': current_box.text, - 'status_class': current_box.class_, - }) - - ctx.update(self.phase2(request, changeNames + builderNames, timestamps, eventGrid, - sourceEvents)) - - def with_args(req, remove_args=[], new_args=[], new_path=None): - # sigh, nevow makes this sort of manipulation easier - newargs = req.args.copy() - for argname in remove_args: - newargs[argname] = [] - if "branch" in newargs: - newargs["branch"] = [b for b in newargs["branch"] if b] - for k,v in new_args: - if k in newargs: - newargs[k].append(v) - else: - newargs[k] = [v] - newquery = "&".join(["%s=%s" % (urllib.quote(k), urllib.quote(v)) - for k in newargs - for v in newargs[k] - ]) - if new_path: - new_url = new_path - elif req.prepath: - new_url = req.prepath[-1] - else: - new_url = '' - if newquery: - new_url += "?" + newquery - return new_url - - if timestamps: - bottom = timestamps[-1] - ctx['nextpage'] = with_args(request, ["last_time"], - [("last_time", str(int(bottom)))]) - - - helpurl = path_to_root(request) + "waterfall/help" - ctx['help_url'] = with_args(request, new_path=helpurl) - - if self.get_reload_time(request) is not None: - ctx['no_reload_page'] = with_args(request, remove_args=["reload"]) - - template = request.site.buildbot_service.templates.get_template("waterfall.html") - data = template.render(**ctx) - return data - - def buildGrid(self, request, builders, changes): - debug = False - # TODO: see if we can use a cached copy - - showEvents = False - if request.args.get("show_events", ["false"])[0].lower() == "true": - showEvents = True - filterCategories = request.args.get('category', []) - filterBranches = [b for b in request.args.get("branch", []) if b] - filterBranches = map_branches(filterBranches) - filterCommitters = [c for c in request.args.get("committer", []) if c] - maxTime = int(request.args.get("last_time", [util.now()])[0]) - if "show_time" in request.args: - minTime = maxTime - int(request.args["show_time"][0]) - elif "first_time" in request.args: - minTime = int(request.args["first_time"][0]) - elif filterBranches or filterCommitters: - minTime = util.now() - 24 * 60 * 60 - else: - minTime = 0 - spanLength = 10 # ten-second chunks - req_events=int(request.args.get("num_events", [self.num_events])[0]) - if self.num_events_max and req_events > self.num_events_max: - maxPageLen = self.num_events_max - else: - maxPageLen = req_events - - # first step is to walk backwards in time, asking each column - # (commit, all builders) if they have any events there. Build up the - # array of events, and stop when we have a reasonable number. - - commit_source = ChangeEventSource(changes) - - lastEventTime = util.now() - sources = [commit_source] + builders - changeNames = ["changes"] - builderNames = map(lambda builder: builder.getName(), builders) - sourceNames = changeNames + builderNames - sourceEvents = [] - sourceGenerators = [] - - def get_event_from(g): - try: - while True: - e = g.next() - # e might be buildstep.BuildStepStatus, - # builder.BuildStatus, builder.Event, - # waterfall.Spacer(builder.Event), or changes.Change . - # The showEvents=False flag means we should hide - # builder.Event . - if not showEvents and isinstance(e, builder.Event): - continue - - if isinstance(e, buildstep.BuildStepStatus): - # unfinished steps are always shown - if e.isFinished() and e.isHidden(): - continue - - break - event = interfaces.IStatusEvent(e) - if debug: - log.msg("gen %s gave1 %s" % (g, event.getText())) - except StopIteration: - event = None - return event - - for s in sources: - gen = insertGaps(s.eventGenerator(filterBranches, - filterCategories, - filterCommitters, - minTime), - showEvents, - lastEventTime) - sourceGenerators.append(gen) - # get the first event - sourceEvents.append(get_event_from(gen)) - eventGrid = [] - timestamps = [] - - lastEventTime = 0 - for e in sourceEvents: - if e and e.getTimes()[0] > lastEventTime: - lastEventTime = e.getTimes()[0] - if lastEventTime == 0: - lastEventTime = util.now() - - spanStart = lastEventTime - spanLength - debugGather = 0 - - while 1: - if debugGather: log.msg("checking (%s,]" % spanStart) - # the tableau of potential events is in sourceEvents[]. The - # window crawls backwards, and we examine one source at a time. - # If the source's top-most event is in the window, is it pushed - # onto the events[] array and the tableau is refilled. This - # continues until the tableau event is not in the window (or is - # missing). - - spanEvents = [] # for all sources, in this span. row of eventGrid - firstTimestamp = None # timestamp of first event in the span - lastTimestamp = None # last pre-span event, for next span - - for c in range(len(sourceGenerators)): - events = [] # for this source, in this span. cell of eventGrid - event = sourceEvents[c] - while event and spanStart < event.getTimes()[0]: - # to look at windows that don't end with the present, - # condition the .append on event.time <= spanFinish - if not IBox(event, None): - log.msg("BAD EVENT", event, event.getText()) - assert 0 - if debug: - log.msg("pushing", event.getText(), event) - events.append(event) - starts, finishes = event.getTimes() - firstTimestamp = earlier(firstTimestamp, starts) - event = get_event_from(sourceGenerators[c]) - if debug: - log.msg("finished span") - - if event: - # this is the last pre-span event for this source - lastTimestamp = later(lastTimestamp, - event.getTimes()[0]) - if debugGather: - log.msg(" got %s from %s" % (events, sourceNames[c])) - sourceEvents[c] = event # refill the tableau - spanEvents.append(events) - - # only show events older than maxTime. This makes it possible to - # visit a page that shows what it would be like to scroll off the - # bottom of this one. - if firstTimestamp is not None and firstTimestamp <= maxTime: - eventGrid.append(spanEvents) - timestamps.append(firstTimestamp) - - if lastTimestamp: - spanStart = lastTimestamp - spanLength - else: - # no more events - break - if minTime is not None and lastTimestamp < minTime: - break - - if len(timestamps) > maxPageLen: - break - - - # now loop - - # loop is finished. now we have eventGrid[] and timestamps[] - if debugGather: log.msg("finished loop") - assert(len(timestamps) == len(eventGrid)) - return (changeNames, builderNames, timestamps, eventGrid, sourceEvents) - - def phase2(self, request, sourceNames, timestamps, eventGrid, - sourceEvents): - - if not timestamps: - return dict(grid=[], gridlen=0) - - # first pass: figure out the height of the chunks, populate grid - grid = [] - for i in range(1+len(sourceNames)): - grid.append([]) - # grid is a list of columns, one for the timestamps, and one per - # event source. Each column is exactly the same height. Each element - # of the list is a single <td> box. - lastDate = time.strftime("%d %b %Y", - time.localtime(util.now())) - for r in range(0, len(timestamps)): - chunkstrip = eventGrid[r] - # chunkstrip is a horizontal strip of event blocks. Each block - # is a vertical list of events, all for the same source. - assert(len(chunkstrip) == len(sourceNames)) - maxRows = reduce(lambda x,y: max(x,y), - map(lambda x: len(x), chunkstrip)) - for i in range(maxRows): - if i != maxRows-1: - grid[0].append(None) - else: - # timestamp goes at the bottom of the chunk - stuff = [] - # add the date at the beginning (if it is not the same as - # today's date), and each time it changes - todayday = time.strftime("%a", - time.localtime(timestamps[r])) - today = time.strftime("%d %b %Y", - time.localtime(timestamps[r])) - if today != lastDate: - stuff.append(todayday) - stuff.append(today) - lastDate = today - stuff.append( - time.strftime("%H:%M:%S", - time.localtime(timestamps[r]))) - grid[0].append(Box(text=stuff, class_="Time", - valign="bottom", align="center")) - - # at this point the timestamp column has been populated with - # maxRows boxes, most None but the last one has the time string - for c in range(0, len(chunkstrip)): - block = chunkstrip[c] - assert(block != None) # should be [] instead - for i in range(maxRows - len(block)): - # fill top of chunk with blank space - grid[c+1].append(None) - for i in range(len(block)): - # so the events are bottom-justified - b = IBox(block[i]).getBox(request) - b.parms['valign'] = "top" - b.parms['align'] = "center" - grid[c+1].append(b) - # now all the other columns have maxRows new boxes too - # populate the last row, if empty - gridlen = len(grid[0]) - for i in range(len(grid)): - strip = grid[i] - assert(len(strip) == gridlen) - if strip[-1] == None: - if sourceEvents[i-1]: - filler = IBox(sourceEvents[i-1]).getBox(request) - else: - # this can happen if you delete part of the build history - filler = Box(text=["?"], align="center") - strip[-1] = filler - strip[-1].parms['rowspan'] = 1 - # second pass: bubble the events upwards to un-occupied locations - # Every square of the grid that has a None in it needs to have - # something else take its place. - noBubble = request.args.get("nobubble",['0']) - noBubble = int(noBubble[0]) - if not noBubble: - for col in range(len(grid)): - strip = grid[col] - if col == 1: # changes are handled differently - for i in range(2, len(strip)+1): - # only merge empty boxes. Don't bubble commit boxes. - if strip[-i] == None: - next = strip[-i+1] - assert(next) - if next: - #if not next.event: - if next.spacer: - # bubble the empty box up - strip[-i] = next - strip[-i].parms['rowspan'] += 1 - strip[-i+1] = None - else: - # we are above a commit box. Leave it - # be, and turn the current box into an - # empty one - strip[-i] = Box([], rowspan=1, - comment="commit bubble") - strip[-i].spacer = True - else: - # we are above another empty box, which - # somehow wasn't already converted. - # Shouldn't happen - pass - else: - for i in range(2, len(strip)+1): - # strip[-i] will go from next-to-last back to first - if strip[-i] == None: - # bubble previous item up - assert(strip[-i+1] != None) - strip[-i] = strip[-i+1] - strip[-i].parms['rowspan'] += 1 - strip[-i+1] = None - else: - strip[-i].parms['rowspan'] = 1 - - # convert to dicts - for i in range(gridlen): - for strip in grid: - if strip[i]: - strip[i] = strip[i].td() - - return dict(grid=grid, gridlen=gridlen, no_bubble=noBubble, time=lastDate) - |