1  from __future__ import generators 
  2   
  3  import sys, time, os.path 
  4  import urllib 
  5   
  6  from twisted.web import html, resource 
  7   
  8  from buildbot import util 
  9  from buildbot import version 
 10  from buildbot.status.web.base import HtmlResource 
 11   
 12   
 13  from buildbot.status.web.base import build_get_class 
 14   
 15   
 16  if hasattr(sys, "frozen"): 
 17       
 18      here = os.path.dirname(sys.executable) 
 19      grid_css = os.path.abspath(os.path.join(here, "grid.css")) 
 20  else: 
 21       
 22      up = os.path.dirname 
 23      grid_css = os.path.abspath(os.path.join(up(__file__), "grid.css")) 
 24   
 26   
 35   
 39   
 40       
 41       
 43          if "reload" in request.args: 
 44              try: 
 45                  reload_time = int(request.args["reload"][0]) 
 46                  return max(reload_time, 15) 
 47              except ValueError: 
 48                  pass 
 49          return None 
  50   
 51 -    def head(self, request): 
  52          head = '' 
 53          reload_time = self.get_reload_time(request) 
 54          if reload_time is not None: 
 55              head += '<meta http-equiv="refresh" content="%d">\n' % reload_time 
 56          return head 
  57   
 58   
 59   
 60   
 61   
 62   
 63   
 64   
 65   
 66   
 67   
 68   
 69   
 70   
 91   
125   
127          text = stamp.getText() 
128          return '<td valign="bottom" class="sourcestamp">%s</td>\n' % \ 
129              "<br />".join(text) 
 130   
132          """Given two source stamps, we want to assign them to the same row if 
133          they are the same version of code, even if they differ in minor detail. 
134   
135          This function returns an appropriate comparison key for that. 
136          """ 
137          return (ss.branch, ss.revision, ss.patch) 
 138   
 173   
175       
176      status = None 
177      control = None 
178      changemaster = None 
179   
180 -    def __init__(self, allowForce=True, css=None): 
 185   
186   
187 -    def body(self, request): 
 188          """This method builds the regular grid display. 
189          That is, build stamps across the top, build hosts down the left side 
190          """ 
191   
192           
193          numBuilds = int(request.args.get("width", [5])[0]) 
194          categories = request.args.get("category", []) 
195          branch = request.args.get("branch", [ANYBRANCH])[0] 
196          if branch == 'trunk': branch = None 
197   
198           
199          status = self.getStatus(request) 
200          stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch) 
201   
202          projectURL = status.getProjectURL() 
203          projectName = status.getProjectName() 
204   
205          data = '<table class="Grid" border="0" cellspacing="0">\n' 
206          data += '<tr>\n' 
207          data += '<td class="title"><a href="%s">%s</a>' % (projectURL, projectName) 
208          if categories: 
209              html_categories = map(html.escape, categories) 
210              if len(categories) > 1: 
211                  data += '\n<br /><b>Categories:</b><br/>%s' % ('<br/>'.join(html_categories)) 
212              else: 
213                  data += '\n<br /><b>Category:</b> %s' % html_categories[0] 
214          if branch != ANYBRANCH: 
215              data += '\n<br /><b>Branch:</b> %s' % (html.escape(branch or 'trunk')) 
216          data += '</td>\n' 
217          for stamp in stamps: 
218              data += self.stamp_td(stamp) 
219          data += '</tr>\n' 
220   
221          sortedBuilderNames = status.getBuilderNames()[:] 
222          sortedBuilderNames.sort() 
223          for bn in sortedBuilderNames: 
224              builds = [None] * len(stamps) 
225   
226              builder = status.getBuilder(bn) 
227              if categories and builder.category not in categories: 
228                  continue 
229   
230              build = builder.getBuild(-1) 
231              while build and None in builds: 
232                  ss = build.getSourceStamp(absolute=True) 
233                  key= self.getSourceStampKey(ss) 
234                  for i in range(len(stamps)): 
235                      if key == self.getSourceStampKey(stamps[i]) and builds[i] is None: 
236                          builds[i] = build 
237                  build = build.getPreviousBuild() 
238   
239              data += '<tr>\n' 
240              data += self.builder_td(request, builder) 
241              for build in builds: 
242                  data += self.build_td(request, build) 
243              data += '</tr>\n' 
244   
245          data += '</table>\n' 
246   
247          data += self.footer(status, request) 
248          return data 
  249   
251       
252      status = None 
253      control = None 
254      changemaster = None 
255   
256 -    def __init__(self, allowForce=True, css=None): 
 261   
262   
263 -    def body(self, request): 
 264          """This method builds the transposed grid display. 
265          That is, build hosts across the top, ebuild stamps down the left side 
266          """ 
267   
268           
269          numBuilds = int(request.args.get("length", [5])[0]) 
270          categories = request.args.get("category", []) 
271          branch = request.args.get("branch", [ANYBRANCH])[0] 
272          if branch == 'trunk': branch = None 
273   
274           
275          status = self.getStatus(request) 
276          stamps = self.getRecentSourcestamps(status, numBuilds, categories, branch) 
277   
278          projectURL = status.getProjectURL() 
279          projectName = status.getProjectName() 
280   
281          data = '<table class="Grid" border="0" cellspacing="0">\n' 
282          data += '<tr>\n' 
283          data += '<td class="title"><a href="%s">%s</a>' % (projectURL, projectName) 
284          if categories: 
285              html_categories = map(html.escape, categories) 
286              if len(categories) > 1: 
287                  data += '\n<br /><b>Categories:</b><br/>%s' % ('<br/>'.join(html_categories)) 
288              else: 
289                  data += '\n<br /><b>Category:</b> %s' % html_categories[0] 
290          if branch != ANYBRANCH: 
291              data += '\n<br /><b>Branch:</b> %s' % (html.escape(branch or 'trunk')) 
292          data += '</td>\n' 
293   
294          sortedBuilderNames = status.getBuilderNames()[:] 
295          sortedBuilderNames.sort() 
296   
297          builder_builds = [] 
298   
299          for bn in sortedBuilderNames: 
300              builds = [None] * len(stamps) 
301   
302              builder = status.getBuilder(bn) 
303              if categories and builder.category not in categories: 
304                  continue 
305   
306              build = builder.getBuild(-1) 
307              while build and None in builds: 
308                  ss = build.getSourceStamp(absolute=True) 
309                  key = self.getSourceStampKey(ss) 
310                  for i in range(len(stamps)): 
311                      if key == self.getSourceStampKey(stamps[i]) and builds[i] is None: 
312                          builds[i] = build 
313                  build = build.getPreviousBuild() 
314   
315              data += self.builder_td(request, builder) 
316              builder_builds.append(builds) 
317   
318          data += '</tr>\n' 
319   
320          for i in range(len(stamps)): 
321              data += '<tr>\n' 
322              data += self.stamp_td(stamps[i]) 
323              for builds in builder_builds: 
324                  data += self.build_td(request, builds[i]) 
325              data += '</tr>\n' 
326   
327          data += '</table>\n' 
328   
329          data += self.footer(status, request) 
330          return data 
  331