{Notes to self, programming, technology, linux, windows, git} U {Papers, reviews, games, coffee, tabletennis, ramblings} = {things worth saving}

Saturday, May 02, 2009

Python: svn pre-commit hook

I put together a python svn pre-commit hook that does 2 things.

* Checks commit message syntax {, orphan} {baseline, tag, integrate}. If syntax does not comply with standards, commit is rejected.
* If syntax contains an activity-id, a ticket repository is checked to locate that specific id. Commit fails if id is not found. If repository connection fails (which shouldn't ever happen), commit is let through regardless.


__doc__ = """
iw_check_commit_messages.py
Utility for doing svn stuff.
"""

import os, string, sys, re, pg
from iw_connect import get_activity_ids #import connect method from iw_connect

SVNLOOK = 'C:\\Program Files\\svn-win32-1.4.5\\bin\\svnlook.exe' #location of SVNlook.exe
authors = {"mk" : "Martin Kjeldsen", "sas" : "Soren Ahm Sorensen", "jo": "Jens Olsen" } #list of fullname authors

syntax_ok = '^(ID|id):(\d+|orphan|baseline|activity|integrate)$' #regexp "tasks"
specifies_activity = '^(ID|id):(\d+)'

def do_lookup(repo,txn, cmd):
cmd = '"%s" %s -t %s %s' % (SVNLOOK, cmd, txn, repo)
result = os.popen(cmd, 'r').readline().rstrip('\n')
return result

def run_reg_exp_task(text, exp, mode):
expression = re.compile(exp)
if mode == "eval":
return expression.search(text) != None
elif mode == "getval":
return expression.search(text)

def parse_commit(repo, txn):
"""
This method parses the log assosiated with transaction txn and takes appropriate action
"""
author = do_lookup(repo,txn, "author") #Determine author
author_fullname = "".join([ v for k,v in authors.items() if k==author]) #if authors fullname isn't in authors dictionary, author is empty.
log_msg = do_lookup(repo,txn, "log") #determine log message

if(run_reg_exp_task(log_msg, syntax_ok, "eval")): #eval TASK: is syntax okay?
if not run_reg_exp_task(log_msg, specifies_activity, "eval"): #eval TASK: does it specify an activity?
sys.exit(0) #exit normally if syntax is okay and we're not dealing with activity id's.
else:
#activity_id = get_activity_id(log_msg) #check database for ID. extract it using a regular exp after it's been approven by the first.
activity_id = run_reg_exp_task(log_msg, specifies_activity, "getval").groups()[1] #get the id from the regexp result
ticket_repository = get_activity_ids() #get ticket repository
if ticket_repository == None: #NONE if connection fails. just commit it. Nothing else we can do. It already passed first test.
sys.exit(0)
elif activity_id in ticket_repository: #is log message activity id present?
sys.exit(0)
else: #reject revision
sys.stderr.write("Dear %s, your revision was rejected. You're trying to commit to an activity that doesn't exist (ID:%s). \n" % (author_fullname, activity_id))
sys.exit(1)
else:
sys.stderr.write("Dear %s, your revision was rejected. Syntax: \nLine 1: {ID|id}:{|orphan|baseline|tag|integrate}\nLine 2+:{Optional: Additional information about activity}" % (author_fullname))
sys.exit(1) #reject revision

if __name__ == "__main__":
print __doc__
if len(sys.argv) <>




__doc__ = """
iw_connect.py
Utility for connecting to a postgresdb using pygresql interface
"""

import os, string, sys, pg

iw_database = 'removed'
iw_host = 'removed'
iw_user = 'removed'
iw_passwd = 'removed'

iw_query = "removed"

def connect():
con = pg.connect(dbname=iw_database, host=iw_host, user=iw_user, passwd=iw_passwd)
return con

def get_activity_ids():
try:
con = connect() #connect to db: details specified in iw_connect.py
query = con.query(iw_query) #Run query to get id's to check in. refactor
ids = [str(v[0]) for v in query.getresult()] #convert result to set of strings
return ids
except pg.InternalError: #if connection fails, just commit it. Nothing else we can do. It already passed first test.
return None

No comments:

Followers