svn

Migrate a folder from one Subversion server to another

I needed to migrate a folder from one Subversion server to another. So, I attempted to follow this page to use dump with svndumpfilter. This combo led me to a lot of issues. The dump command exports all the commits for a repository while svndumpfilter attempts to filter the folder I am interested to keep. Unfortunately, the filter tool is very buggy and unable to filter correctly. Here are the scenarios that did not work for me:

If a commit contains a move action with source location outside of the folder I want to include, the filter fails. I had to include that location when filter. If a commit contains an add action, the parent folder has to exist when loading. I could resolve this by creating the parent folder manually. If a commit contains a delete action and the target folder/file doesn’t exist, the load fails. I could try to create the folder/file manually in an attempt to not fail the delete action. This trick didn’t work when the commit includes a delete of parent folder before attempt to delete the file in it.

When I about to give up, I came across svndumpfilter3 and was happy to find it dump/load without an error. :) Here are the commands I used:

svnadmin dump [path to source repository] | ./svndumpfilter3 --untangle=[path to source repository] [target folder to include] > dump_file.dmp

svnadmin load [path to target repository] --parent-dir [path to target parent dir] < dump_file.dmp

SVN::Notify

After setting up an instance of SVN using the instructions I found here. I wanted to setup email notification for every commit on a SVN server. I was able to setup SVN::Notify using the tutorial on this page. When attempting to run perl -MCPAN -e 'install SVN::Notify', the install command complained that MakeMaker version is not new enough. So, I went to this CPAN page and download the module and install it before resume installing SVN::Notify. The install command complained again about a missing directory. I repeated the command and the installation completed successfully. :)

The instruction statement on “replace the existing call to commit-email.pl” wasn’t very clear to me. It didn’t say which file I should edit. I eventually figured out that I should make a copy of [SVN_REPOSITORY]/hooks/post-commit.tmpl file and name the new file [SVN_REPOSITORY]/hooks/post-commit. In the file, I commented out the following line:

mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf

Next, I added the following line:

/usr/bin/svnnotify --repos-path "$1" --revision "$2" --to me@mydomain.com --user-domain mydomain

Please note that I replaced me@mydomain.com and mydomain with correct values for my environment. I also ran the following command to make it executable.

chmos +x post-commit

After completed all these, I was able to receive the email notification every time an user commit to the repository. :)

Using Subversion externals for files

I needed to use Subversion externals property to define a reference to a file. Based on this blog, here are my notes:

Let’s say that you want to have Subversion to use the following file from another directory: https://mysvnserver.com/svn/shared/lib/thelib.jar

And have the file download into the following file in your project: myproject/lib/thelib.jar You should have lib directory already exist.

Within your myproject folder, create a text file. This is necessary if you plan to have multiple references.

$ cat > svn_externals_config.txt
lib/thelib.jar https://mysvnserver.com/svn/shared/lib/thelib.jar

Use Ctrl-D to exit the data entry mode. Alternatively, you can use your favourite text editor to create the text file.

If you want to reference a folder instead, you can have the following definition:

lib/aThirdPartyLibFolder https://mysvnserver.com/svn/shared/lib/aThirdPartyLibFolder

Make sure that the local lib folder doesn’t have aThirdPartyLibFolder or you may get the following error: svn: warning: Working copy 'aThirdPartyLibFolder' locked.

Now you can set the svn:externals property by running the following lines:

svn propset svn:externals . -F svn_externals_config.txt
svn update

Once you are set, you can commit the externals definition by running the following command:

svn commit --depth empty . -m "Modify svn externals definition only."

Using svn merge

I wanted to merge one revision I made in the trunk into one of the branches. So, I used Subversion’s svn merge command to accomplish this. Thanks to Ray M. for explained the Subversion merge command to me. Here are my notes:

Before I start, I identified the following information:

  • The target revision number in trunk that I wanted to merge into the branch. In this case, I assigned a revision number of 100.
  • The full URL for the trunk. I found this information by running svn info and looked for Repository Root. In my environment, the trunk is simply [Repository Root]/trunk.

With the above information, I was ready to do a dry-run to make sure the command produced the outcome I wanted. Here is what I ran:

cd [local branch directory]
svn merge -r99:100 --dry-run [Repository Root]/trunk

I basically changed directory into the branch where I want merge the trunk revision to. Next, I ran the svn command with the merge sub-command. For the revision numbers, I specified the revision I wanted to merge from the trunk as the second number and the first number was simply the second revision minus one. This essentially said to merge changes that happen between revision 99 and 100, which was equivalent to all the changes committed in revision 100. The URL to trunk told the merge sub-command where to look for the specified source revision number.

Once I was happy with the dry-out output, I ran the command again without the --dry-run option. This effectively merge revision 100 from trunk into the branch. Right after that, I ran svn diff to check if the diff output was what I expected before I commit the changes.