SVN/Trac Integration
A long time ago I wrote an article titled CVS/Bugzilla Integration. Here is an updated version for subversion and trac.
Note that it doesn’t require access the trac python libs or database; it just uses HTTP. But it does require BeautifulSoup. Install it by adding it to your hooks post-commit script. (it takes the normal params of REPOS and REV).
#!/usr/bin/env python
import os, re, sys, urllib, urllib2
from BeautifulSoup import BeautifulSoup
TRAC_URL = 'http://my.trac.url'
TRAC_TICKET_REL_URL = '/xxx/ticket/'
TRAC_LOGIN_REL_URL = '/xxx/login/'
TRAC_USER = 'user'
TRAC_PASS = 'pass'
TRAC_REALM = 'myRealm'
#SVNLOOK = '/usr/bin/svnlook'
SVNLOOK = '/usr/local/bin/svnlook'
TRAC_TICKET_URL = TRAC_URL+TRAC_TICKET_REL_URL
TRAC_LOGIN_URL = TRAC_URL+TRAC_LOGIN_REL_URL
def get_commit_info(repos, rev):
c = os.popen( SVNLOOK+' info "%s" -r "%s"' % (repos, rev) )
user = c.readline().strip()
date = c.readline().strip()
ignore = c.readline().strip()
msg = c.read()
c.close()
return user, date, msg
def get_trac_tickets(msg):
p = re.compile(r'trac:d+')
tickets = p.findall(msg)
return [ t[5:] for t in tickets ]
def post_to_trac( ticket, msg ):
auth = urllib2.HTTPDigestAuthHandler()
auth.add_password(TRAC_REALM, TRAC_URL, TRAC_USER, TRAC_PASS)
opener = urllib2.build_opener(auth, urllib2.HTTPCookieProcessor())
req = urllib2.Request(TRAC_LOGIN_URL)
req.add_header("Referer", TRAC_TICKET_URL+ticket)
try:
res = opener.open(req)
html = res.read()
soup = BeautifulSoup(html)
form = soup.find('form', action=TRAC_TICKET_REL_URL+ticket+'#preview')
data = {}
for i in form.findAll('input'):
try:
if i['type']=='hidden' or i['type']=='text':
data[ i['name'] ] = i['value']
if i['type']=='checkbox' or i['type']=='radio':
if i.get('checked'):
data[ i['name'] ] = i['value']
except: pass
for s in form.findAll('select'):
for o in s.findAll('option'):
if o.get('selected'):
data[ s['name'] ] = o.get('value',o.string)
data['comment'] = msg
#data['preview'] = 'Preview'
#print 'n'.join([ str(x) for x in data.iteritems() ] )
req = urllib2.Request(TRAC_TICKET_URL+ticket, urllib.urlencode(data))
req.add_header("Referer", TRAC_TICKET_URL+ticket)
res = opener.open(req)
html = res.read()
#print html
except IOError, e:
pass
# if hasattr(e, 'code'):
# if e.code != 401:
# print 'We got another error'
# print e.code
# else:
# print e.headers
def main(*args):
if len(args)!=3:
print 'usage: python commit-trac.py "repos" "rev"'
return 1
repos = args[1]
rev = args[2]
user, date, msg = get_commit_info(repos, rev)
msg = 'svn commit to %s -r%s (%s):n%s' % (repos, rev, user, msg)
print msg
for ticket in get_trac_tickets(msg):
post_to_trac( ticket, msg )
return 0 # exit errorlessly
if __name__ == '__main__':
sys.exit(main(*sys.argv))







