Mercurial > bitten > bitten-test
changeset 114:ecc062d4fd55
Paths to files and directories in the build log output are rendered as links to the repository browser.
author | cmlenz |
---|---|
date | Sun, 07 Aug 2005 09:03:16 +0000 |
parents | 142d95b9e8b0 |
children | 16d69eb6e047 |
files | bitten/trac_ext/templates/build.cs bitten/trac_ext/web_ui.py |
diffstat | 2 files changed, 62 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/bitten/trac_ext/templates/build.cs +++ b/bitten/trac_ext/templates/build.cs @@ -99,7 +99,9 @@ if:len(rev[platform.id]) ?><td class="<?cs var:rev[platform.id].cls ?>"><a href="<?cs var:rev[platform.id].href ?>" title="View build results"><?cs - var:rev[platform.id].slave.name ?></a><br /><?cs + var:rev[platform.id].slave.name ?></a> (<?cs + var:rev[platform.id].slave.os ?> <?cs + var:rev[platform.id].slave.os.version ?>)<br /><?cs if:rev[platform.id].status == 'in progress' ?>started <?cs var:rev[platform.id].started_delta ?> ago<?cs else ?>took <?cs
--- a/bitten/trac_ext/web_ui.py +++ b/bitten/trac_ext/web_ui.py @@ -34,12 +34,26 @@ from bitten.model import BuildConfig, TargetPlatform, Build, BuildStep, BuildLog +class ILogFormatter(Interface): + """Extension point interface for components that format build log + messages.""" + + def get_formatter(req, build, step, type): + """Return a function that gets called for every log message. + + The function must take two positional arguments, `level` and `message`, + and return the formatted message. + """ + + class BuildModule(Component): """Implements the Bitten web interface.""" implements(INavigationContributor, IRequestHandler, ITimelineEventProvider, ITemplateProvider) + log_formatters = ExtensionPoint(ILogFormatter) + _status_label = {Build.IN_PROGRESS: 'in progress', Build.SUCCESS: 'completed', Build.FAILURE: 'failed'} @@ -331,7 +345,7 @@ for build in Build.select(self.env, config=config.name, rev=rev): if build.status == Build.PENDING: continue - req.hdf['%s.%s' % (prefix, build.platform)] = self._build_to_hdf(build) + req.hdf['%s.%s' % (prefix, build.platform)] = self._build_to_hdf(req, build) if idx > 4: break except TracError, e: @@ -384,7 +398,7 @@ Build.IN_PROGRESS: 'In Progress'} req.hdf['title'] = 'Build %s - %s' % (build_id, status2title[build.status]) - req.hdf['build'] = self._build_to_hdf(build, include_output=True) + req.hdf['build'] = self._build_to_hdf(req, build, include_output=True) req.hdf['build.mode'] = 'view_build' config = BuildConfig.fetch(self.env, build.config) @@ -393,7 +407,7 @@ 'href': self.env.href.build(config.name) } - def _build_to_hdf(self, build, include_output=False): + def _build_to_hdf(self, req, build, include_output=False): hdf = {'id': build.id, 'name': build.slave, 'rev': build.rev, 'status': self._status_label[build.status], 'cls': self._status_label[build.status].replace(' ', '-'), @@ -425,9 +439,48 @@ if include_output: for log in BuildLog.select(self.env, build=build.id, step=step.name, db=db): - steps[-1]['log'] = [{'level': level, - 'message': message} - for level, message in log.messages] + formatters = [] + items = [] + for formatter in self.log_formatters: + formatters.append(formatter.get_formatter(req, build, + step, + log.type)) + for level, message in log.messages: + for format in formatters: + message = format(level, message) + items.append({'level': level, 'message': message}) + steps[-1]['log'] = items hdf['steps'] = steps return hdf + + +class SourceFileLinkFormatter(Component): + """Finds references to files and directories in the repository in the build + log and renders them as links to the repository browser.""" + + implements(ILogFormatter) + + def get_formatter(self, req, build, step, type): + config = BuildConfig.fetch(self.env, build.config) + repos = self.env.get_repository(req.authname) + nodes = [] + def _walk(node): + for child in node.get_entries(): + path = child.path[len(config.path) + 1:] + pattern = re.compile("([\s'\"])(%s)([\s'\"])" % re.escape(path)) + nodes.append((child.path, pattern)) + if child.isdir: + _walk(child) + _walk(repos.get_node(config.path, build.rev)) + nodes.sort(lambda x, y: -cmp(len(x[0]), len(y[0]))) + + def _formatter(level, message): + for path, pattern in nodes: + def _replace(m): + return '%s<a href="%s">%s</a>%s' % (m.group(1), + self.env.href.browser(path, rev=build.rev), + m.group(2), m.group(3)) + message = pattern.sub(_replace, message) + return message + return _formatter