| OLD | NEW |
| 1 # This file is part of Buildbot. Buildbot is free software: you can | 1 # This file is part of Buildbot. Buildbot is free software: you can |
| 2 # redistribute it and/or modify it under the terms of the GNU General Public | 2 # redistribute it and/or modify it under the terms of the GNU General Public |
| 3 # License as published by the Free Software Foundation, version 2. | 3 # License as published by the Free Software Foundation, version 2. |
| 4 # | 4 # |
| 5 # This program is distributed in the hope that it will be useful, but WITHOUT | 5 # This program is distributed in the hope that it will be useful, but WITHOUT |
| 6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | 7 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
| 8 # details. | 8 # details. |
| 9 # | 9 # |
| 10 # You should have received a copy of the GNU General Public License along with | 10 # You should have received a copy of the GNU General Public License along with |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 self.date = change.getTime() | 151 self.date = change.getTime() |
| 152 self.revlink = getattr(change, 'revlink', None) | 152 self.revlink = getattr(change, 'revlink', None) |
| 153 self.when = change.when | 153 self.when = change.when |
| 154 self.repository = change.repository | 154 self.repository = change.repository |
| 155 self.project = change.project | 155 self.project = change.project |
| 156 | 156 |
| 157 | 157 |
| 158 class DevBuild: | 158 class DevBuild: |
| 159 """Helper class that contains all the information we need for a build.""" | 159 """Helper class that contains all the information we need for a build.""" |
| 160 | 160 |
| 161 def __init__(self, revision, build, details, inProgressResults=None): | 161 def __init__(self, revision, build, details, inProgressResults=None, |
| 162 revisions=[]): |
| 162 self.revision = revision | 163 self.revision = revision |
| 163 self.results = build.getResults() | 164 self.results = build.getResults() |
| 164 self.number = build.getNumber() | 165 self.number = build.getNumber() |
| 165 self.isFinished = build.isFinished() | 166 self.isFinished = build.isFinished() |
| 166 self.text = build.getText() | 167 self.text = build.getText() |
| 167 self.eta = build.getETA() | 168 self.eta = build.getETA() |
| 168 self.details = details | 169 self.details = details |
| 169 self.when = build.getTimes()[0] | 170 self.when = build.getTimes()[0] |
| 170 self.source = build.getSourceStamp() | 171 self.source = build.getSourceStamp() |
| 171 self.inProgressResults = inProgressResults | 172 self.inProgressResults = inProgressResults |
| 173 for rev in revisions: |
| 174 if rev.revision == revision: |
| 175 self.when = rev.when |
| 176 break |
| 172 | 177 |
| 173 | 178 |
| 174 class ConsoleStatusResource(HtmlResource): | 179 class ConsoleStatusResource(HtmlResource): |
| 175 """Main console class. It displays a user-oriented status page. | 180 """Main console class. It displays a user-oriented status page. |
| 176 Every change is a line in the page, and it shows the result of the first | 181 Every change is a line in the page, and it shows the result of the first |
| 177 build with this change for each slave.""" | 182 build with this change for each slave.""" |
| 178 | 183 |
| 179 def __init__(self, orderByTime=False, repository=None, | 184 def __init__(self, orderByTime=False, repository=None, |
| 180 builder_filter_fn=lambda builderName: True): | 185 builder_filter_fn=lambda builderName: True): |
| 181 HtmlResource.__init__(self) | 186 HtmlResource.__init__(self) |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 logurl = request.childLink( | 314 logurl = request.childLink( |
| 310 "../builders/%s/builds/%s/steps/%s/logs/%s" % | 315 "../builders/%s/builds/%s/steps/%s/logs/%s" % |
| 311 (urllib.quote(builderName, safe=''), | 316 (urllib.quote(builderName, safe=''), |
| 312 build.getNumber(), | 317 build.getNumber(), |
| 313 urllib.quote(name, safe=''), | 318 urllib.quote(name, safe=''), |
| 314 urllib.quote(logname, safe=''))) | 319 urllib.quote(logname, safe=''))) |
| 315 logs.append(dict(url=logurl, name=logname)) | 320 logs.append(dict(url=logurl, name=logname)) |
| 316 return details | 321 return details |
| 317 | 322 |
| 318 def getBuildsForRevision(self, request, builder, builderName, lastRevision, | 323 def getBuildsForRevision(self, request, builder, builderName, lastRevision, |
| 319 numBuilds, debugInfo): | 324 numBuilds, debugInfo, revisions): |
| 320 """Return the list of all the builds for a given builder that we will | 325 """Return the list of all the builds for a given builder that we will |
| 321 need to be able to display the console page. We start by the most recent | 326 need to be able to display the console page. We start by the most recent |
| 322 build, and we go down until we find a build that was built prior to the | 327 build, and we go down until we find a build that was built prior to the |
| 323 last change we are interested in.""" | 328 last change we are interested in.""" |
| 324 | 329 |
| 325 revision = lastRevision | 330 revision = lastRevision |
| 326 | 331 |
| 327 builds = [] | 332 builds = [] |
| 328 build = self.getHeadBuild(builder) | 333 build = self.getHeadBuild(builder) |
| 329 number = 0 | 334 number = 0 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 350 except: | 355 except: |
| 351 pass | 356 pass |
| 352 | 357 |
| 353 # We ignore all builds that don't have last revisions. | 358 # We ignore all builds that don't have last revisions. |
| 354 # TODO(nsylvain): If the build is over, maybe it was a problem | 359 # TODO(nsylvain): If the build is over, maybe it was a problem |
| 355 # with the update source step. We need to find a way to tell the | 360 # with the update source step. We need to find a way to tell the |
| 356 # user that his change might have broken the source update. | 361 # user that his change might have broken the source update. |
| 357 if got_rev and got_rev != -1: | 362 if got_rev and got_rev != -1: |
| 358 details = self.getBuildDetails(request, builderName, build) | 363 details = self.getBuildDetails(request, builderName, build) |
| 359 devBuild = DevBuild(got_rev, build, details, | 364 devBuild = DevBuild(got_rev, build, details, |
| 360 getInProgressResults(build)) | 365 getInProgressResults(build), revisions) |
| 361 builds.append(devBuild) | 366 builds.append(devBuild) |
| 362 | 367 |
| 363 # Now break if we have enough builds. | 368 # Now break if we have enough builds. |
| 364 current_revision = self.getChangeForBuild( | 369 current_revision = self.getChangeForBuild( |
| 365 build, revision) | 370 build, revision) |
| 366 if self.comparator.isRevisionEarlier( | 371 if self.comparator.isRevisionEarlier( |
| 367 devBuild, current_revision): | 372 devBuild, current_revision): |
| 368 break | 373 break |
| 369 | 374 |
| 370 build = build.getPreviousBuild() | 375 build = build.getPreviousBuild() |
| 371 | 376 |
| 372 return builds | 377 return builds |
| 373 | 378 |
| 374 def getChangeForBuild(self, build, revision): | 379 def getChangeForBuild(self, build, revision): |
| 375 if not build or not build.getChanges(): # Forced build | 380 if not build or not build.getChanges(): # Forced build |
| 376 return DevBuild(revision, build, None) | 381 return DevBuild(revision, build, None) |
| 377 | 382 |
| 378 for change in build.getChanges(): | 383 for change in build.getChanges(): |
| 379 if change.revision == revision: | 384 if change.revision == revision: |
| 380 return change | 385 return change |
| 381 | 386 |
| 382 # No matching change, return the last change in build. | 387 # No matching change, return the last change in build. |
| 383 changes = list(build.getChanges()) | 388 changes = list(build.getChanges()) |
| 384 changes.sort(key=self.comparator.getSortingKey()) | 389 changes.sort(key=self.comparator.getSortingKey()) |
| 385 return changes[-1] | 390 return changes[-1] |
| 386 | 391 |
| 387 def getAllBuildsForRevision(self, status, request, lastRevision, numBuilds, | 392 def getAllBuildsForRevision(self, status, request, lastRevision, numBuilds, |
| 388 categories, builders, debugInfo): | 393 categories, builders, debugInfo, revisions): |
| 389 """Returns a dictionary of builds we need to inspect to be able to | 394 """Returns a dictionary of builds we need to inspect to be able to |
| 390 display the console page. The key is the builder name, and the value is | 395 display the console page. The key is the builder name, and the value is |
| 391 an array of build we care about. We also returns a dictionary of | 396 an array of build we care about. We also returns a dictionary of |
| 392 builders we care about. The key is it's category. | 397 builders we care about. The key is it's category. |
| 393 | 398 |
| 394 lastRevision is the last revision we want to display in the page. | 399 lastRevision is the last revision we want to display in the page. |
| 395 categories is a list of categories to display. It is coming from the | 400 categories is a list of categories to display. It is coming from the |
| 396 HTTP GET parameters. | 401 HTTP GET parameters. |
| 397 builders is a list of builders to display. It is coming from the HTTP | 402 builders is a list of builders to display. It is coming from the HTTP |
| 398 GET parameters. | 403 GET parameters. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 429 builderList[category] = [] | 434 builderList[category] = [] |
| 430 | 435 |
| 431 # Append this builder to the dictionary of builders. | 436 # Append this builder to the dictionary of builders. |
| 432 builderList[category].append(builderName) | 437 builderList[category].append(builderName) |
| 433 # Set the list of builds for this builder. | 438 # Set the list of builds for this builder. |
| 434 allBuilds[builderName] = self.getBuildsForRevision(request, | 439 allBuilds[builderName] = self.getBuildsForRevision(request, |
| 435 builder, | 440 builder, |
| 436 builderName, | 441 builderName, |
| 437 lastRevision, | 442 lastRevision, |
| 438 numBuilds, | 443 numBuilds, |
| 439 debugInfo) | 444 debugInfo, |
| 445 revisions) |
| 440 | 446 |
| 441 return (builderList, allBuilds) | 447 return (builderList, allBuilds) |
| 442 | 448 |
| 443 | 449 |
| 444 ## | 450 ## |
| 445 ## Display functions | 451 ## Display functions |
| 446 ## | 452 ## |
| 447 | 453 |
| 448 def displayCategories(self, builderList, debugInfo): | 454 def displayCategories(self, builderList, debugInfo): |
| 449 """Display the top category line.""" | 455 """Display the top category line.""" |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 793 if revisions: | 799 if revisions: |
| 794 lastRevision = revisions[len(revisions) - 1].revision | 800 lastRevision = revisions[len(revisions) - 1].revision |
| 795 debugInfo["last_revision"] = lastRevision | 801 debugInfo["last_revision"] = lastRevision |
| 796 | 802 |
| 797 (builderList, allBuilds) = self.getAllBuildsForRevision(status, | 803 (builderList, allBuilds) = self.getAllBuildsForRevision(status, |
| 798 request, | 804 request, |
| 799 lastRevision, | 805 lastRevision, |
| 800 numBuilds, | 806 numBuilds, |
| 801 categories, | 807 categories, |
| 802 builders, | 808 builders, |
| 803 debugInfo) | 809 debugInfo, |
| 810 revisions) |
| 804 | 811 |
| 805 debugInfo["added_blocks"] = 0 | 812 debugInfo["added_blocks"] = 0 |
| 806 debugInfo["from_cache"] = 0 | 813 debugInfo["from_cache"] = 0 |
| 807 | 814 |
| 808 if request.args.get("display_cache", None): | 815 if request.args.get("display_cache", None): |
| 809 data = "" | 816 data = "" |
| 810 data += "\nGlobal Cache\n" | 817 data += "\nGlobal Cache\n" |
| 811 data += self.cache.display() | 818 data += self.cache.display() |
| 812 return data | 819 return data |
| 813 | 820 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 | 874 |
| 868 def isValidRevision(self, revision): | 875 def isValidRevision(self, revision): |
| 869 try: | 876 try: |
| 870 int(revision) | 877 int(revision) |
| 871 return True | 878 return True |
| 872 except: | 879 except: |
| 873 return False | 880 return False |
| 874 | 881 |
| 875 def getSortingKey(self): | 882 def getSortingKey(self): |
| 876 return operator.attrgetter('revision') | 883 return operator.attrgetter('revision') |
| OLD | NEW |