Symfony World blog is not maintained anymore. Check new sys.exit() programming blog.

SVN repository auto update

Scene from "Brazil" by Terry Gilliam (1985)

I found an article (in Polish) describing a subversion hook that will automatically update a server working copy. This seems perfect - after commiting a new revision, all changes are available online (entire development team can test the most up to date version, your boss may see the newest results, etc).

Anyway, I don't see any reason to use C here, so I've made my own version updating the repository using shell command:

svn up /home/website/domains/dev.website.com/website
  --no-auth-cache --username user --password pass
The --no-auth-cache option is important here - authorization data is not going to be remembered here. Other two options define the authorization data.

troubleshooting

You may have problems with file permissions, if the user which holds the repository is different than the user which hold the working copy (this was in my case). The problem I got was permission denied for .../.svn/lock file, which is a temporary file, existing only when the revision is being checked/committed. Oops... There is no one good solution for this - it depends on the server configuration. It can be adding one user to the group of another, changing the owner of the entire working copy files (no matter in which /home subdirectory it is, as long as web server can handle requests, etc).

force to log message SVN python

Scene from "It Happened One Night" by Frank Capra (1934)

Another blog post about Subversion. Few days ago someone asked me if I know how to block commiting a subversion revision that has no log message defined. I didn't, but I thought it's a good idea, because it could help to track bugs, changes, etc. There's no such configuration, but it can be achieved using SVN hooks.

tried to do this in PHP...

There are many resources in the web giving examples to do this using a windows batch file - but I'm a linux user. At first, I wanted to do this in PHP. Although my final solution is not PHP, maybe someone will find following code snippets useful.

So I started searching through many pages on the web to find PHP shell scripts that could block committing a revision with no log message. The first step is, of course, to create an executable pre-commit file in the hooks directory of the repository. Then make the shell use the PHP parser to execute our script. Next, define path to svnlook binary and execute it:

#!/usr/local/bin/php -q
<?php
 
$SVNLOOK = '/usr/bin/svnlook';
exec("$SVNLOOK log -t {$argv[2]} {$argv[1]}", $output, $result);
We have the output and the result of the command available. So we may just check if the message (which revision a user is just trying to commit) is empty (I guess there is no other way than to use svnlook). If the log message is empty, the revision shall be stopped - and this happens, when exit status code is different than 0 (of course, a message explaining the cause is appreciated):
if (empty($result))
{
  fwrite(STDERR, "Commit blocked, need to pass the log message.");
  exit(1);
}
else
  exit(0);
This all should work, but 99,9% of all servers will have the exec function disabled by default (in both CLI and web server PHP configuration; along with other system functions):
disable_functions = exec,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,dl,popen,show_source
Even if you manage to remove those functions from the configuration, you lower the server security, which may risk dangerous script injection. So I forgot about using PHP...

...and finally moved to python

Finally, I managed to succeed using python:

#!/usr/bin/python
 
import sys, os, string
 
SVNLOOK='/usr/bin/svnlook'
 
def main(repos, txn):
  log_cmd = '%s log -t "%s" "%s"' % (SVNLOOK, txn, repos)
  log_msg = os.popen(log_cmd, 'r').readline().rstrip('n')
  if len(log_msg) < 10:
    sys.stderr.write ("\n> Revision comment must be defined\n")
    sys.exit(1)
  else:
    sys.exit(0)
 
if __name__ == '__main__':
  if len(sys.argv) < 3:
    sys.stderr.write("\n> Usage: %s REPOS TXN\n" % (sys.argv[0]))
  else:
    main(sys.argv[1], sys.argv[2])

svnsync tutorial

Scene from magnificent "One Flew Over the Cuckoo's Nest" By Miloš Forman

I was forced to use this tool when I wanted to move my old project repository into a new server (until then, its SVN repository was hosted on a free SVN hosting). The hosting provider forced me to pay for the svnadmin dump, so I searched for an alternative solution and svnsync did the job.

In comparison to svnadmin dump/load, svnsync is migrating subversion repository with no svnadmin access. The migration can be done when you have a working copy (checkout) of the source repository and a clean (svnadmin create) version of the target repository. The repository synchronization is just reading all revisions one by one and copying them into the target repository, unchanged.

First, take a look at this article. Here you can find that a hook needs to be created in the target repository: hooks/pre-revprop-change (removing .tmpl and granting executable permissions for the script). What is not mentioned in the article above is that you should probably put

#!/bin/sh 
exit 0;
as the hooks/pre-revprop-change script content, to avoid the error, as written in another article.

Now, initialize the synchronization (example call below):

svnsync init [target repository] [source repository]
svnsync init file:///home/user/svn/test-repo svn://free-hosting/that-forced-me-to-pay/for-the-svn-dump

and copy all revisions, while being in the working copy of the source repository (example call below again):

svnsync --non-interactive sync [target repository]
svnsync --non-interactive sync file:///home/user/svn/test-repo

Be patient and wait until it's finished. Afterwards, remove the useless hooks/pre-revprop-change script - and you're done!