Synchronize subversion repositories with inotify-tools

How can I keep two subversion repositories synchronized on the fly?
As a known issues that system administrators may face, there’re serval ways to achieve that:

  • svnsync – As part of the official toolset, it would be a good solution. Anyway I will not use it.
  • SVK – Did not check it yet, but may have chance to try it.
  • inotify-tools and rsync – That’s what will be explained in this post.


With the help of inotifywait, we’re able to know the events happened on specific files or directories, so basically we just need to raise a command to do the sync work. Normally you can do that by setting up rsync service on the remote side, and run the command below in hooks/post-commit:

rsync -az /path/to/repos/reponame subversion@admon.org:/path/mirror/repos &

If you try to use inotifywait to do that, it will be a little tricky. Basically for each commit, we prefer to catching only one event and knowing the event right after the commit. So what can we do now?

Step 1 – Set up the post-commit hook to trigger a event

joseph@test !1064 $ tail -2 hooks/post-commit
#Used by inotifywait to trigger an event.
touch ${REPOS}/README.txt

Step 2 – Set up the authentication for copy files to destination side
You can use scp or ftp for file coping, here we use rsync as an example.

The authentication can be either password based, or public key based. We’ll not show more details here since it’s another topic.

Step 3 – Create a script to run as daemon
Here’s a script working well for me:

!1071 $ cat nice-sync
#!/bin/sh
#
# Created by Joseph.Chen <https://www.admon.org/>
# Watch ${REPOS}/README.txt, and rsync the repository accordingly.

working_dir="/path/to/repos/"
watched_file='opsource/README.txt'
sync_log="/tmp/subversion-sync.log"

msg_logger() {
    echo $@ >> $sync_log
}

rsync_repository() {
    therepo=$1
    rsync -rqlS ${therepo} admon@remote.dev:/path/mirror/repos &
    msg_logger ${therepo} started syncing at `date +%c`. May finish soon.
}

if [ "$(whoami)" != "admon" ]; then
    echo This script intends to run in normal user mode as admon.
    exit
fi

cd $working_dir || exit

# Inital rsync is needed
for rep in $(echo $watched_file |sed 's/\/README.txt//g')
do
    rsync_repository $rep
done

inotifywait -mrq --format "%w" -e attrib ${watched_file} |while read line
do
    fwrepo=$(echo $line |awk -F/ '{print $1}')
    msg_logger Detected commits happened on ${fwrepo} at `date +%c`
    rsync_repository $fwrepo
done

The command inotifywait serves as a daemon, and keeping reading the attrib events generated by README.txt, and then run a command for each received event.

If you faced further issues, don’t forget to submit a query here at our support forum.

Share Button

5 thoughts on “Synchronize subversion repositories with inotify-tools

  1. Hi Joseph;

    your solution is good for the environment I’m running under. Can you tell me if I can make the $watched_file the entire repo directory of the master server? I.e:

    I have multiple repos:
    master:/svnroot/repo1 and repo2 repo3 etc…

    I want to rsync the whole lot of them when a change is detected to:
    slave:/svnroot/repo1, repo2 repo3 etc..

    Please help.

    Thanks
    Ali.

  2. syncing on multiple repos is supported well by this script, you just need to change:
    watched_file=’opsource/README.txt’
    to
    watched_file=’repo1/README.txt repo2/README.txt repo3/README.txt …’
    and updated all the hooks/post-commit accordingly.

    Watch the whole directory is not proper, as for a single commit, their might be lots of temp files created in transaction directory, which may trigger a lot of unexpected events —– while actually all we need is just one event after the commitment finishes.

Leave a comment

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