comparison bitten/web_ui.py @ 883:dfbf2f857a50

Fixed handling of active configurations that points to deleted branches. Configurations and builds can now be checked and displayed even though the repository path cannot be found for last revision. It uses configuration 'last' (`max_rev`) to "close" the configuration. Closes #606. Thanks to falkb for extensive testing.
author osimons
date Fri, 10 Dec 2010 09:23:12 +0000
parents a68027e2245d
children
comparison
equal deleted inserted replaced
881:15cf0edad043 883:dfbf2f857a50
20 from genshi.builder import tag 20 from genshi.builder import tag
21 from trac.attachment import AttachmentModule, Attachment 21 from trac.attachment import AttachmentModule, Attachment
22 from trac.core import * 22 from trac.core import *
23 from trac.config import Option 23 from trac.config import Option
24 from trac.mimeview.api import Context 24 from trac.mimeview.api import Context
25 from trac.perm import PermissionError
25 from trac.resource import Resource 26 from trac.resource import Resource
26 from trac.timeline import ITimelineEventProvider 27 from trac.timeline import ITimelineEventProvider
27 from trac.util import escape, pretty_timedelta, format_datetime, shorten_line, \ 28 from trac.util import escape, pretty_timedelta, format_datetime, shorten_line, \
28 Markup, arity 29 Markup, arity
29 from trac.util.datefmt import to_timestamp, to_datetime, utc 30 from trac.util.datefmt import to_timestamp, to_datetime, utc
30 from trac.util.html import html 31 from trac.util.html import html
31 from trac.web import IRequestHandler, IRequestFilter, HTTPNotFound 32 from trac.web import IRequestHandler, IRequestFilter, HTTPNotFound
32 from trac.web.chrome import INavigationContributor, ITemplateProvider, \ 33 from trac.web.chrome import INavigationContributor, ITemplateProvider, \
33 add_link, add_stylesheet, add_ctxtnav, \ 34 add_link, add_stylesheet, add_ctxtnav, \
34 prevnext_nav, add_script 35 prevnext_nav, add_script, add_warning
35 from trac.versioncontrol import NoSuchChangeset 36 from trac.versioncontrol import NoSuchChangeset, NoSuchNode
36 from trac.wiki import wiki_to_html, wiki_to_oneliner 37 from trac.wiki import wiki_to_html, wiki_to_oneliner
37 from bitten.api import ILogFormatter, IReportChartGenerator, IReportSummarizer 38 from bitten.api import ILogFormatter, IReportChartGenerator, IReportSummarizer
38 from bitten.master import BuildMaster 39 from bitten.master import BuildMaster
39 from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, \ 40 from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, \
40 BuildLog, Report 41 BuildLog, Report
78 'machine': build.slave_info.get(Build.MACHINE), 79 'machine': build.slave_info.get(Build.MACHINE),
79 'processor': build.slave_info.get(Build.PROCESSOR) 80 'processor': build.slave_info.get(Build.PROCESSOR)
80 } 81 }
81 return data 82 return data
82 83
83 def _has_permission(repos, path, perm, raise_error=False): 84 def _has_permission(perm, repos, path, rev=None, raise_error=False):
84 if hasattr(repos, 'authz'): 85 if hasattr(repos, 'authz'):
85 if not repos.authz.has_permission(path): 86 if not repos.authz.has_permission(path):
86 if not raise_error: 87 if not raise_error:
87 return False 88 return False
88 repos.authz.assert_permission(path) 89 repos.authz.assert_permission(path)
89 else: 90 else:
90 node = repos.get_node(path) 91 node = repos.get_node(path, rev)
91 if not node.can_view(perm): 92 if not node.can_view(perm):
92 if not raise_error: 93 if not raise_error:
93 return False 94 return False
94 from trac.perm import PermissionError
95 raise PermissionError('BROWSER_VIEW', node.resource) 95 raise PermissionError('BROWSER_VIEW', node.resource)
96 return True 96 return True
97 97
98 class BittenChrome(Component): 98 class BittenChrome(Component):
99 """Provides the Bitten templates and static resources.""" 99 """Provides the Bitten templates and static resources."""
217 assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 217 assert repos, 'No "(default)" Repository: Add a repository or alias ' \
218 'named "(default)" to Trac.' 218 'named "(default)" to Trac.'
219 219
220 configs = [] 220 configs = []
221 for config in BuildConfig.select(self.env, include_inactive=show_all): 221 for config in BuildConfig.select(self.env, include_inactive=show_all):
222 if not _has_permission(repos, config.path, req.perm): 222 rev = config.max_rev or repos.youngest_rev
223 try:
224 if not _has_permission(req.perm, repos, config.path, rev=rev):
225 continue
226 except NoSuchNode:
227 add_warning(req, "Configuration '%s' points to non-existing "
228 "path '/%s' at revision '%s'. Configuration skipped." \
229 % (config.name, config.path, rev))
223 continue 230 continue
224 231
225 description = config.description 232 description = config.description
226 if description: 233 if description:
227 description = wiki_to_html(description, self.env, req) 234 description = wiki_to_html(description, self.env, req)
307 assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 314 assert repos, 'No "(default)" Repository: Add a repository or alias ' \
308 'named "(default)" to Trac.' 315 'named "(default)" to Trac.'
309 316
310 configs = [] 317 configs = []
311 for config in BuildConfig.select(self.env, include_inactive=False): 318 for config in BuildConfig.select(self.env, include_inactive=False):
312 if not _has_permission(repos, config.path, req.perm): 319 rev = config.max_rev or repos.youngest_rev
320 try:
321 if not _has_permission(req.perm, repos, config.path, rev=rev):
322 continue
323 except NoSuchNode:
324 add_warning(req, "Configuration '%s' points to non-existing "
325 "path '/%s' at revision '%s'. Configuration skipped." \
326 % (config.name, config.path, rev))
313 continue 327 continue
314 328
315 self.log.debug(config.name) 329 self.log.debug(config.name)
316 if not config.active: 330 if not config.active:
317 continue 331 continue
373 % config_name) 387 % config_name)
374 388
375 repos = self.env.get_repository(authname=req.authname) 389 repos = self.env.get_repository(authname=req.authname)
376 assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 390 assert repos, 'No "(default)" Repository: Add a repository or alias ' \
377 'named "(default)" to Trac.' 391 'named "(default)" to Trac.'
378 _has_permission(repos, config.path, req.perm, True) 392 rev = config.max_rev or repos.youngest_rev
393 try:
394 _has_permission(req.perm, repos, config.path, rev=rev,
395 raise_error=True)
396 except NoSuchNode:
397 raise TracError("Permission checking against repository path %s "
398 "at revision %s failed." % (config.path, rev))
379 399
380 data = {'title': 'Build Configuration "%s"' \ 400 data = {'title': 'Build Configuration "%s"' \
381 % config.label or config.name, 401 % config.label or config.name,
382 'page_mode': 'view_config'} 402 'page_mode': 'view_config'}
383 add_link(req, 'up', req.href.build(), 'Build Status') 403 add_link(req, 'up', req.href.build(), 'Build Status')
603 and build.status != build.PENDING) 623 and build.status != build.PENDING)
604 624
605 repos = self.env.get_repository(authname=req.authname) 625 repos = self.env.get_repository(authname=req.authname)
606 assert repos, 'No "(default)" Repository: Add a repository or alias ' \ 626 assert repos, 'No "(default)" Repository: Add a repository or alias ' \
607 'named "(default)" to Trac.' 627 'named "(default)" to Trac.'
608 _has_permission(repos, config.path, req.perm, True) 628 _has_permission(req.perm, repos, config.path, rev=build.rev, raise_error=True)
609 chgset = repos.get_changeset(build.rev) 629 chgset = repos.get_changeset(build.rev)
610 data['build']['chgset_author'] = chgset.author 630 data['build']['chgset_author'] = chgset.author
611 data['build']['display_rev'] = repos.normalize_rev(build.rev) 631 data['build']['display_rev'] = repos.normalize_rev(build.rev)
612 632
613 add_script(req, 'common/js/folding.js') 633 add_script(req, 'common/js/folding.js')
652 672
653 event_kinds = {Build.SUCCESS: 'successbuild', 673 event_kinds = {Build.SUCCESS: 'successbuild',
654 Build.FAILURE: 'failedbuild'} 674 Build.FAILURE: 'failedbuild'}
655 675
656 for id_, config, label, path, rev, platform, stopped, status in cursor: 676 for id_, config, label, path, rev, platform, stopped, status in cursor:
657 if not _has_permission(repos, path, req.perm): 677 if not _has_permission(req.perm, repos, path, rev=rev):
658 continue 678 continue
659 errors = [] 679 errors = []
660 if status == Build.FAILURE: 680 if status == Build.FAILURE:
661 for step in BuildStep.select(self.env, build=id_, 681 for step in BuildStep.select(self.env, build=id_,
662 status=BuildStep.FAILURE, 682 status=BuildStep.FAILURE,
Copyright (C) 2012-2017 Edgewall Software