This post is from the CollabNet VersionOne blog and has not been updated since the original publish date.
Mirroring Repositories with svnsync
To best discuss svnsync without getting confused, we should establish some common terminology before going any further:
- Master: The live read/write repository that will be mirrored via svnsync.
- Mirror: The read-only repository that is synchronized with the master via svnsync.
svnsync is a utility that became part of the standard Subversion offering when 1.4 was released and is described as a program that “provides all the functionality required for maintaining a read-only mirror of a Subversion repository.” While understanding the purpose of svnsync based on it’s documentation is simple, why would maintaining a mirror repository be important in the enterprise? With each Subversion implementation being different, there can be many reasons but there are a couple common reasons as to the importance of maintaining mirror repositories:
- Provide a backup repository: This can be beneficial for failover, soft-upgrade, etc.
- Provide a simple read-only repository: Some people want a simple way to provide read-only access to a repository. With svnsync, you can easily achieve this without maintaining authorization files and such. (For example: To maintain a community access point to a repository while using a different repository for the actual developer actions.)
These are just a couple examples but should give you an idea as to what value svnsync can provide. (For a more detailed explanation, please refer to the “Repository Maintenance” chapter of the “Version Control with Subversion” book.) While I could jump right in to script suggestions and examples, doing so would be a shame. To really understand why we are doing what we are, we should really understand how svnsync works. I will be brief in my explanation and then we will go into example scripts and suggestions you can apply in your Subversion implementation.
The way svnsync works is actually pretty simple: Take revisions from one repository and “replay” them to another. This means that the mirror repository plays by the same rules as the master repository. The user account performing the actions against the mirror repository must have write access to that mirror repository. The “secret sauce” that makes svnsync work is due to Subversion maintaining the necessary metadata to know what needs to be synchronized in special revision properties on revision 0 of the mirror repository. That is it. That is how svnsync works and although it is easy to understand, to make svnsync work as designed, there are a few “rules” you need to be aware of. The following is a list of rules and/or best practices for using svnsync:
- The synchronizing user needs read/write access to the complete mirror repository.
- The synchronizing user needs to be able to modify certain revision properties.
- The mirror repository needs to be read-only for all users except the synchronizing user.
- Before you can synchronize a mirror repository with the master, the mirror repository needs to be at revision 0.
Now that we know what svnsync is and how it works and why it might be useful, let’s learn how we can start synchronizing a mirror repository with our master repository using svnsync.
The only real prerequisite for implementing svnsync is to have a repository that you want to mirror already created prior to starting this process. Once that is complete, you can follow the steps outlined below:
Step 1: Create Mirror Repository
svnadmin create MIRROR_REPO_PATH
Step 2: Make Mirror Repository Only Writable by Synchronizing User
To make the mirror repository only writable by the synchronizing user, which in our example will be “svnsync”, we have a few options. One option is to use the authz functionality of Subversion with a default access rule like this:
[/] * = r svnsync = rw
The other option is to use the start-commit hook to check for the svnsync user. Here is an example, as a shell script:
#!/bin/sh USER="$2" if [ "$USER" = "syncuser" ]; then exit 0; fi echo "Only the syncuser user may commit new revisions as this is a read-only, mirror repository." >&2 exit 1
Step 3: Make Mirror Repository Revision Properties Modifiable by Synchronizing User
To do this, we need to create a pre-revprop-change hook with something similar to the following example, as a shell script:
#!/bin/sh USER="$3" if [ "$USER" = "syncuser" ]; then exit 0; fi echo "Only the syncuser user may change revision properties as this is a read-only, mirror repository." >&2 exit 1
Step 4: Register Mirror Repository for Synchronization
Perform the following svnsync command on any system:
svnsync initialize URL_TO_MIRROR_REPO URL_TO_MASTER_REPO --username=svnsync --password=svnsyncpassword
If everything is configured properly, you should see some output like this:
Copied properties for revision 0.
Now that you have registered your mirror repository for synchronization with the master repository, we should go ahead and perform the initial synchronization so that the mirror and the master repository are synchronized.
Step 5: Perform Initial Synchronization
To make sure everything is ready and to perform the initial synchronization, on any system, perform the following:
svnsync synchronize URL_TO_MIRROR_REPO --username=svnsync --password=svnsyncpassword
If everything synchronized property, you should see some output similar to this:
Committed revision 1. Copied properties for revision 1. Committed revision 2. Copied properties for revision 2. Committed revision 3. Copied properties for revision 3. …
Step 6: Automate Synchronization with post-commit Hook
Now with the initial synchronization out of the way, all that needs to happen now is to write a script to be ran either as a scheduled process or as a post-commit hook to synchronize your mirror repository with the master repository. I suggest the post-commit option as it gives you the best chance of having a mirror repository as up-to-date as possible. Here is an example hook that might be used on the master repository to synchronize a mirror repository as part of the post-commit hook. As a shell script:
# Example for synchronizing one repository from the post-commit hook #!/bin/sh SVNSYNC=/usr/local/bin/svnsync $SVNSYNC synchronize URL_TO_MIRROR_REPO --username=svnsync --password=svnsyncpassword & exit 0
That is it. Once you have followed the steps outlined above, you should have a mirror repository that is kept up to date automatically when someone modifies the master repository. This also concludes our introduction to svnsync and how to implement it.