Windows IIS trac-post-commit-hook on local subversion repository

Thursday, 23 July 2009


This post looks at a recent problem I had with getting the trac-post-commit-hook script to run on my local subversion repository.

I will try and add another post in the next couple of weeks talking about how to set up python/trac/subversion along with the hook, for now I will just discuss the solution to this problem.

Note this is for a windows server running IIS 6.

To start with we have a server with two drives C:\ and E:\. C:\ has the python installation with trac and E:\ has the local version of the subversion repository and with the local trac installation.

On my local computer I have mapped C:\ and E:\ as X:\ and Y:\ respectively. Now the big issue if you try and commit using the trac-post-commit-hook it will fail as the only argument it takes is the location of the trac environment where it reads the location of the subversion repository as being on E:\, which obviously fails when being called from my local machine.

If you have a look at the cmd file you will notice three arguments. To get this working you need to do the following:

SET TRAC_ENV= (Set this to the location of trac on the mapped drive e.g. Y:\projects\trac\mycoolproject)

SET PYTHON_PATH= (To get this to work, go to your server and copy everything out of the PATH system variable and paste it here, then replace all of the C:\ and E:\ with your X:\ and Y:\, this will allow the application to find the necessary DLLs)

SET TRAC_PATH= (Set this to the location of trac within Python on the X:\)

Now before you go off and make the next round of changes, go on to the server that has Python installed e.g. C:\ and try and run the trac-post-commit-hook.py from there. Python is sensitive about whitespace so it's a good idea to check that the script can be executed without errors otherwise you may be left scratching you head later.

Now on to the next part. We need to modify our local trac.ini file and then change a couple of the trac scripts.

As always, use this at your own risk and back everything up before hand!!!

First open you trac.ini file and add a new variable 'remote_repository_dir' underneath the 'repository_dir' variable. Remote repository dir will point to the mapped drive on your local machine. It should now look something like this:


repository_dir = E:/Projects/svn/InfoProj
remote_repository_dir = Y:/Projects/svn/InfoProj


Next we will modify the api.py file to check for the new variable if it can't find the repository at the *repository_dir* location. Around :71 you should have something like this:


repository_dir = Option('trac', 'repository_dir', '',
"""Path to local repository. This can also be a relative path
(''since 0.11'').""")


Underneath this line add:


remote_repository_dir = Option('trac', 'remote_repository_dir', '',
"""Path to remote repository.""")


Next near :156 you will have this:


rtype, rdir = self.repository_type, self.repository_dir
if not os.path.isabs(rdir):
rdir = os.path.join(self.env.path, rdir)


Change that to this:


rtype, rdir = self.repository_type, self.repository_dir
if not os.path.isdir(rdir):
rdir = self.remote_repository_dir
if not os.path.isabs(rdir):
rdir = os.path.join(self.env.path, rdir)


Finally you will need to remove the alert in the cache.py file (note this is not the best way to do this, you should be able to include the remote variable as part of the check, but for now it works).

In cache.py near :97 it should look like this:


if repository_dir:
# directory part of the repo name can vary on case insensitive fs
if os.path.normcase(repository_dir) != os.path.normcase(self.name):
self.log.info("'repository_dir' has changed from %r to %r"
% (repository_dir, self.name))
raise TracError(_("The 'repository_dir' has changed, a "
"'trac-admin resync' operation is needed."))
elif repository_dir is None: #
self.log.info('Storing initial "repository_dir": %s' % self.name)
cursor.execute("INSERT INTO system (name,value) VALUES (%s,%s)",
(CACHE_REPOSITORY_DIR, self.name,))
else: # 'repository_dir' cleared by a resync
self.log.info('Resetting "repository_dir": %s' % self.name)
cursor.execute("UPDATE system SET value=%s WHERE name=%s",
(self.name, CACHE_REPOSITORY_DIR))


We are going to remove the first part of the if statement so it now should look like this:


if repository_dir is None: #
self.log.info('Storing initial "repository_dir": %s' % self.name)
cursor.execute("INSERT INTO system (name,value) VALUES (%s,%s)",
(CACHE_REPOSITORY_DIR, self.name,))
else: # 'repository_dir' cleared by a resync
self.log.info('Resetting "repository_dir": %s' % self.name)
cursor.execute("UPDATE system SET value=%s WHERE name=%s",
(self.name, CACHE_REPOSITORY_DIR))


Warning! Doing this will mean that it no longer gives you an error if your directory has changed and you need a resync.

Once this is done it should all work like clock work.
blog comments powered by Disqus