SVN woes

I recently found out that our repository holding the code of multiple projects for the past 8+ years wasn’t being backed up properly. What’s worse, the reason it isn’t being backed up properly isn’t because we have no backup in place, no, it is because the repo is corrupt. HOORAY!

This revelation has led me on a long, strange trip, and I have tried many things so far in an attempt to save some of our history (though it is not looking good). One of the interesting things I read was an idea to use svnsync:

Another approach I forgot to recommend before is to setup a user in the original repository that has read permission only to your branch, and then use that user to create a mirror of the repository using svnsync. svnsync will honor the permissions in your access file, and will simply omit the stuff that user can’t read, leaving you with a repository that has a bunch of empty revisions but contains all the changes made to your branch only.

I found a great post on using svnsync and had a go. While this is a pretty slick trick, it unfortunately did not work. You, long ago when the repo was corrupted, I was tasked with “fixing” the repo. My “fix” allowed us to keep on using the repo, but it effectively made the repo worthless since my “fix” was to remove the corrupt db rev file – not a good idea…

Anyway, now we are stuck with a repo that is full of work and no way to export it easily with history. Luckily 3 years in code is like dog years, so much of the code from before the corruption occurred is not really used. My latest trick to attempt is dumping a range after the corruption, then use svndumpfilter to try and save history for relevant projects. This post gives a nice outline of the steps involved to perform a task like this.

Unforunately, some stuff is just going to have to get added to the new repo and we are going to lose history, but we can keep the current repo running in a read-only state for that. In the end, it turns out this is all for the better – we made the mistake of putting binaries into the repo, and it is out of control at over 14GB. Time to prune that sucker…

TortoiseSVN global ignores

I know all the cool kids are using git and their .gitignore files, but in crufty enterprisey-land we still use SVN. I hated always having to ignore bin/obj, etc. for new projects, so a while back I found out how to set global ignores. I wanted to share this info with some co-workers, so I thought it would make a good blog post. That way I’ll be able to refer back to it when I format my HD and forget how exactly I set the global ignores “last time”.

It is really quite simple:

  1. Open TortoiseSVN settings by right-clicking > TortoiseSVN > Settings
  2. In the initial General dialog, in the lower Subversion section is a textbox labelled Global ignore pattern. Add your values here

tsvn-general

I use VS/C#, so I added bin obj *.user *.suo, YMMV.

SVN Tree Conflicts

One thing that has always baffled me and my co-workers is SVN tree conflicts. I thought it would be a good idea to keep track of different scenarios that result in tree conflicts as an exercise in demystifying them.

  • Delete a file but don’t check in the delete. Another user performs the same delete and checks it in. Perform an update = tree conflict

Automating TortoiseSVN

So the whole reason I started this stupid blog was so I’d have a place to fall back on with all the interesting crap I found on the interwebz. Yeah, that worked out well…

So why the hell am I not just adding every cool thing I find?!? Because it is way easier to bookmark it. Hell, I use this pre-alpha version of Oxite and I gotta type in my HTML markup by hand. How archaic is that! [Edit: not any more!]

Well, here is a great link to TortoiseSVN automation. I have been working towards completely automating our release procedure, and we always had the Tortoise dialog that we had to click “OK” for every time. We all know how completely annoying that can be, right? Well, no more!

Example

What good is this post without some sort of example, right? Well here you go.

We used to do something like so:

"C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe" /command:update /path:%FOLDER%

That has the annoying dialog. So now we just do the following:

"C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe" /command:update /closeonend:2 /path:%FOLDER%

That handy little /closeonend saves my click-finger! Voila! The post goes into detail on the parameter, so have a look.

SVN post-commit trigger

We use a post-commit trigger at work to notify the team of all commits made to the repository. I needed to make some modifications, so I thought I’d update my sorely neglected blog with the details. You know, for the kids…

Original post-commit file

This isn’t the exact file we use, but the majority of it was taken from this post. Dan has a great file that you can pretty much drag ‘n drop and have some seriously cool emails flying around. As Dan notes, you’ll need SendMail, but it is practically an out-of-the-box solution.

Recent tweaks

I get email. A LOT of email. It is a bit hard to manage, so I got rules up the wazoo! I originally had all the commit emails simply going into my “Commits” subfolder. However, we have some different apps, and a few different web sites going on, so having all the notifications dumped into a single folder wasn’t working either. Dan’s script adds some useful information to the subject line, but it wasn’t quite what I was looking for. I was trying to use keywords from the body of the email, but that wasn’t 100% either. So, I had to make some tweaks to get what I wanted.

I wanted to add the repo folder that was updated to the subject line. This way, I could write my rules to look for keywords based on the folder names of our projects in the repo. This would be fool-proof. Batch files have always been a little odd to me, and some of the deep, dark recesses of DOS are left unexplored. I did some searching and came up with this StackOverflow question about getting details of what was committed via svnlook. Using the dir-changed along with the suggested for loop worked quite well. Now all I had to do was get a part of the dir-changed.

More searching turned up this and this, which are both essentially the same. They pointed me down the right path and I got it going.

Not quite perfect

I am totally anal. I have personally labeled myself a “Code Nazi”. I can’t stand extra spaces, or extra line breaks, or anything that is seemingly unnecessary. It seems that svnlook author must add some extra spaces to the end of the author name, because there were 3 extra spaces at the end of every name. Up until now, I decided to just let this go. I mean, really, it wasn’t like it made the subject line illegible or anything. But, I love Mike Holmes, and like he says, make it right! So more searching turned up this great page on DOS string manipulation. I used it to replace the spaces in the author name and now the subject line is perfect!

The script

After all this talking, I could at least share the code, right? As I said earlier, it is heavily borrowed from Dan’s great code, with some minor updates made for my taste. Here you go:

@ECHO OFF
REM *************************************************************
REM * this sets the arguments supplied by Subversion            *
REM *************************************************************
SET REPOS=%1
SET REV=%2

REM *************************************************************
REM * define the path to the working copy of your code          *
REM *                                                           *
REM * the default working_copy folder would be:                 *
REM * file:///%REPOS%                                           *
REM *************************************************************
SET WORKING_COPY=file:///c:/web/svnroot
SET DIR=%REPOS%/hooks

REM *************************************************************
REM * get author's name                                         *
REM *************************************************************
for /f %%a in ( 'c:\svn\svnlook.exe author %REPOS% -r %REV%' ) do ( SET AUTHOR=%%a )

REM *************************************************************
REM * define e-mail parameters                                  *
REM *************************************************************
SET SITENAME=emw2k8dev
SET SMTP_SERVER=192.168.0.112
SET [email protected]
SET [email protected]-moor.com
for /F "eol=; tokens=1 delims=/" %%a in ( 'c:\svn\svnlook.exe dirs-changed %REPOS% -r %REV%' ) do ( SET SITENAME=%%a )
SET SUBJECT=SVN Update - %AUTHOR: =% - %SITENAME% - rev %REV% - \\emw2k8dev\%REPOS:C:\=%

REM *************************************************************
REM * generate the header to use for the e-mail message         *
REM *************************************************************
ECHO The following changes were made to the code: > %DIR%/email.txt
ECHO. >> %DIR%/email.txt

REM *************************************************************
REM * dump the log of changes to the e-mail message             *
REM *************************************************************
c:\svn\svn log %WORKING_COPY% -v -r "%REV%" >> %DIR%/email.txt
ECHO. >> %DIR%/email.txt

REM *************************************************************
REM * dump the diff changes to the e-mail message               *
REM *                                                           *
REM * WARNING: Generates tons of output                         *
REM *                                                           *
REM * NOTE: this is optional, you can remove this information   *
REM *       if you do not want a verbose message of changes     *
REM *************************************************************
c:\svn\svn diff %WORKING_COPY% -c "%REV%" --no-diff-deleted >> %DIR%/email.txt
ECHO. >> %DIR%/email.txt

REM *************************************************************
REM * send the e-mail message to the user                       *
REM *************************************************************
c:\web\svnroot\sendEmail.exe -s %SMTP_SERVER% -t %EMAIL_TO% -f %EMAIL_FROM% -u "%SUBJECT%" -o message-file=%DIR%/email.txt -l %DIR%/SendEmail.log

So it is by no means perfect or anything, but it may come in handy to someone else.