Added SVN logging observer.

It isn't triggered by anything yet. When the observer is called, it uses
Blinker to send out a signal for every [T12345] marker it sees in the
first line of each commit log. Those signals aren't connected to anything
yet.

NOTE: this requires the 'svn' Python module , which is a wrapper for the
'svn' commandline client. This client needs to be installed on our docker
when we deploy.
This commit is contained in:
2016-08-31 14:31:45 +02:00
parent 15f0f5889a
commit 0c9b31c4b4
5 changed files with 228 additions and 1 deletions

View File

@@ -0,0 +1,17 @@
"""Extra functionality for attrs."""
import logging
import attr
def log(name):
"""Returns a logger attr.ib
:param name: name to pass to logging.getLogger()
:rtype: attr.ib
"""
return attr.ib(default=logging.getLogger(name),
repr=False,
hash=False,
cmp=False)

View File

@@ -0,0 +1,53 @@
"""Subversion interface."""
from __future__ import absolute_import
import re
import attr
import blinker
import svn.remote
from . import attrs_extra
task_logged = blinker.NamedSignal('task_logged')
task_marker_re = re.compile(r'\[(?P<task_id>T\d+)\]')
FETCH_AND_OBSERVE_CHUNK_SIZE = 10
def obtain(server_location):
"""Returns a Connection object for the given server location."""
return svn.remote.RemoteClient(server_location)
@attr.s
class CommitLogObserver(object):
svn_client = attr.ib(validator=attr.validators.instance_of(svn.remote.RemoteClient))
last_seen_revision = attr.ib(default=0, validator=attr.validators.instance_of(int))
_log = attrs_extra.log('%s.CommitLogObserver' % __name__)
def fetch_and_observe(self):
"""Obtains task IDs from SVN logs."""
self._log.debug('%s: fetch_and_observe()', self)
svn_log = self.svn_client.log_default(
revision_from=self.last_seen_revision + 1,
revision_to=self.last_seen_revision + FETCH_AND_OBSERVE_CHUNK_SIZE)
for log_entry in svn_log:
self._log.debug('- %r', log_entry)
# assumption: revisions are always logged in strictly increasing order.
self.last_seen_revision = log_entry.revision
# Parse the commit log to see if there are any task markers.
lines = log_entry.msg.split('\n', 1)
first_line = lines[0]
for match in task_marker_re.finditer(first_line):
task_id = match.group('task_id')
task_logged.send(self,
task_id=task_id,
log_entry=log_entry)