Categories
Posts

Setting up SVNSync and SVN-Notify

Long story short, I wanted to get commit emails for a Subversion repo. I don’t have any admin rights to the repo so I figured the easiest way was to just setup a local repo, keep up to date with the live repo with svnsync and then configure svn-notify on my local repo. The local repo is only used for svn-notify, I’m not using it to checkout copies of the code or anything else.

A good resource to getting started with svnsync is http://svn.apache.org/repos/asf/subversion/trunk/notes/svnsync.txt. Go take a look at that first, should make the rest of this easy to follow.

I assume that you already have subversion/svnsync and svn-notify installed and ready to go. I’m not going to cover installing those.

Here are the steps I followed to put this all together, first svnsync:

  1. Create local svn repo: svnadmin create /home/svn/repo-name
  2. Edit /home/svn/repo-name/hooks/pre-revprop-change so that it looks like:

    [sourcecode]
    #!/bin/sh
    USER="$3"

    if [ "$USER" = "svnsync" ]; then exit 0; fi

    echo "Only the svnsync user can change revprops" >&2
    exit 1
    [/sourcecode]

    This limits changes to the local repo to only the ‘svnsync’ user.

  3. Make it executable: chmod +x /home/svn/repo-name/hooks/pre-revprop-change
  4. Initialize the sync between repos: svnsync init – username svnsync file:///home/svn/repo-name http://svn.example.com/repo-name
  5. Run the first sync: svnsync sync file:///home/svn/repo-name
  6. Schedule a cron job to run the sync periodically, say once every hour (on a nice odd number like 17 after the hour): 17 * * * * /usr/local/bin/svnsync – non-interactive sync file:///home/svn/repo-name

With svnsync in place adding svn-notify for our locally synced repo is pretty easy. Edit /home/svn/repo-name/hooks/post-commit to look like:

[sourcecode]
#!/bin/sh

REPOS="$1"
REV="$2"

delayed_notify( ) {
sleep 10

/usr/local/bin/svnnotify –repos-path "$1" –revision "$2"
–to commit-list@example.com
–from commit-list@example.com
–with-diff
–subject-cx
–subject-prefix ‘REPO-NAME ‘
–handler HTML::ColorDiff
}

delayed_notify $1 $2 > /dev/null 2>&1 &
[/sourcecode]

Then make that hook executable: chmod +x /home/svn/repo-name/hooks/post-commit

There are two downsides to this approach. First, the commit emails don’t go out right away after a commit, svnsync has to be run first. In my example above that means it could be an hour after the commit before the email goes out. I don’t consider this a big deal and the gap can be reduced by syncing more often. The second problem bugs me, the user listed for all of the commits is the svnsync user, instead of the actual user that committed the change to the master repo. Since all of the commits are replayed as the svnsync user there doesn’t appear to be an easy way to fix this. If you know of one let me know.

And there we go, now you can get commit emails for a repo that you don’t have any admin rights to. Not glamorous or ideal, but better than nothing.

Update: A big thank you Peter Westwood (a.k.a westi) for suggesting a technique to delay svn-notify long enough for svnsync to finish replaying the rev-prop changes. I tried it out and it solved the problem where all commit emails showed the ‘svnsync’ user for every commit.

12 replies on “Setting up SVNSync and SVN-Notify”

The trick to get the correct usernames and dates is going to be to run your script later.

svnsync works by doing a commit and then playing with the revprops to set username, date etc which is why it needs the pre-revprop-change hook.

You want svn-notify to run after it has done all this.

You probably need something which runs n-seconds after the commit triggered from post-revprop-change and does the notify that way.

Barry may have some hints as the WP.org trac runs against an svnsync’d copy of the code.

So your thought is that SVN-Notify is running late enough to pick up the commit, but not late enough to pick prop changes, interesting. I wonder if there is something in svnsync that I could use to call SVN-Notify directly, after svnsync has completed replaying all of the changes.

I’ll have to explore this further, I’d really like to get all of the accurate information in the commit emails when using this setup.

This will do it.

This will fork and sleep before doing the notify so that you catch the revprop changes as well.

You need to tune the sleep time based on how big the revprop changes take. 10 seconds is probably far too long.


#!/bin/sh

delayed_notify() {
sleep 10
/usr/bin/svnnotify --repos-path "$1" --revision "$2"
--to commit-list@example.com
--from commit-list@example.com
--with-diff
--subject-cx
--subject-prefix 'REPO-NAME '
--handler HTML::ColorDiff
}

delayed_notify $1 $2 >& /dev/null &

Nice!
I had to make just one small fix, I changed the last line to:

delayed_notify $1 $2 >&2 /dev/null &

Without that I’d get an error, post-commit: 28: Syntax error: Bad fd number
I guess it doesn’t assume STDERR.

Not a big deal, but I usually do the ordering on this differently: > /dev/null 2>&1
so that it reads out loud like, redirect STDOUT to /dev/null and redirect STDERR to STDOUT

Thanks again, I just confirmed that this works. I now get the correct username in the commit emails. I’ll update the post with your example.

Cool.

I guess the output redirect difference may be just a shell configuration thing.

I just googled what to use as I can never remember 😉

Hi!

Did you sort the issue regarding that all commits where done by the user running svnsync?

I’m trying to move my subversion from an online service to our own local network and all commits are done by the user running the svnsync. And to make it even harder all the usernames have changed from the old repository to the new one.

Do you know of any way to change the usernames with svn hooks? On the external online service we use our complete mail address as usernames but the local one only use the domain username. So I need to strip away “@domain.com” in the username that does the commit……

Any ideas?

Peter Westwood’s suggestion worked for awhile, but for some reason has stopped working for me. This could be due to changes on the main repo, I’m not sure.

I’m not aware of specific method for changing usernames with svn hooks, but I wouldn’t be surprised if someone has done that before.

If you enable the ability to edit rev-props using a hook in the repo (which I think you have to do for svnsync anyway) then you can easily change the username associated with a log message.

You can do this as a one time script which runs through each revision on write a hook to do it for each revision as it is synced (as long as you can hook in after svnsync has set the username)

You may need a longer delay before the notifier runs so as to ensure you are not catching the svnsync username.

You could make it check the username and loop if the username for the revision is still svnsync.

Great article !
Is there any way to get the full repository path in the notification email?
Currently I get “trunk/project/……” while it would be great to have the full path as we have the subversion service through http with apache and would be able to navigate directly to the file. Something like:
“http://svn.mydomain.com/projectName/trunk/project….”

Thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *