SVN post-commit for Windows
As I mentioned early I've been working on a SVN post-commit script. We've got a SVN repository that will be modified by several remote developers and I really need to keep an eye on this repository and I need to closely monitor changes to this repository.
There are two major functions that I needed in my post-commit script:
- I needed to update the working copy on my server
- I needed to e-mail the changes to myself, so I know when developers are making changes
There are an abundant of examples showing off how to do this in various *nix flavors, but I couldn't find any good Windows-based solutions that didn't require Perl to be installed on the server. That led me to create the following post-commit.bat script.
@ECHO OFF REM ************************************************************* REM * this sets the arguments supplied by Subversion * REM ************************************************************* SET REPOS=%1 SET REV=%2 REM ************************************************************* REM * define directory paths * REM * you *must* add any paths for command line tools you plan * REM * since SVN does not include the Windows %PATH% environment * REM * variable for security reasons. * REM * * REM * DIR - the current hooks directory * REM * PATH - a user set path of where executables are located * REM * * REM ************************************************************* SET DIR=%REPOS%/hooks REM ************************************************************* REM * make sure to add the path to the SendEmail executable * REM ************************************************************* SET PATH=%PATH%;%DIR%;C:\Utils 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=c:\path\to\working\copy REM ************************************************************* REM * define e-mail parameters * REM ************************************************************* SET SITENAME=My Code Base SET SMTP_SERVER=smtp.yourdomain.com SET EMAIL_TO=svnupdates@yourdomain.com SET EMAIL_FROM=svnupdates@yourdomain.com SET SUBJECT=SVN Update - %SITENAME% - rev %REV% - %REPOS% REM ************************************************************* REM * update the local working copy * REM * this will sync the new changes to your servers copy * REM ************************************************************* svn update %WORKING_COPY% 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 ************************************************************* svn log %WORKING_COPY% -v -r "%REV%" >> %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 ************************************************************* svn diff %WORKING_COPY% -c "%REV%" --no-diff-deleted >> %DIR%/email.txt REM ************************************************************* REM * send the e-mail message to the user * REM * * REM * NOTE: to create a SendEmail.log file, append: * REM * * REM * -l %DIR%/SendEmail.log * REM * * REM * at the end of the line below. * REM ************************************************************* sendEmail -s %SMTP_SERVER% -t %EMAIL_TO% -f %EMAIL_FROM% -u "%SUBJECT%" -o message-file=%DIR%/email.txt
A couple of notes on the script above:
- You'll need to download SendEmail in order to send the e-mail messages. In the environmental variable %PATH% you'll want to make sure to include the path where you copied the SendEmail.exe. In the example above, the SendEmail.exe is located in the C:\Utils directory.
- Make sure to go through the script and replace any variables declared with the SET command with the values that coorelated to your environment.
- In my case I required a working copy to be placed on my server, as it's used as a global development environment. If you do not require a local working copy, you can comment out the svn update %WORKING_COPY% line (by placing the command REM in front of the line.) You would then change your WORKING_COPY variable to the URL of your SVN repository—which would be file:///%REPOS%.
- The svn diff command can generate a ton of information. In most use cases, you probably do not want to add this information to the e-mail output.
If you have any problems getting this script working, I recommend you check out my blog entry on debugging SVN repository hook scripts in Windows.
Comments
For others that come across this, Here's where I got stumped. If you're running subversion with apache, this script will be run as Apache. I needed to run this against a network path like: \\server\share I couldn't, because apache didn't have network access rights.
I had to update the apache service (and perhaps the subversion service) to run using my user account. It worked fine after that.
@echo off
set REPOS=%1
set REV=%2
c:\SVN\ServiceRoot\bin\svnlook changed -r %REV% %REPOS% >
c:\SVN\Repo\CodeBoy\hooks\changed.txt
c:\python25\python C:\SVN\Repo\CodeBoy\hooks\updateChanged.py
This way you can only call an update on the modified paths instead of killing your box trying to update the entire checkout.
I have users set up with their smtp addresses as their user names. Is there a way to
SET EMAIL_TO= with the value of the user committing the file(s)?
The follow SVN command would get you the author of an update:
svnlook author -r "%REV%" "%REPOS%"
See this URL for more usage:
http://svnbook.red-bean.com/en/1.4/svn.ref.svnlook...
You'd need to capture that output and get it into a variable to send it to the author (since the post-commit unfortunately doesn't pass author information to script.)
Just curious as to why you'd only want to notify the commiter via e-mail--since they'll know immediately if their commit passed or failed.
The from address in the message ought to be the author of the commit.
The to address is the person that will push the files.
Gotcha. Here's a link that should help you capture the author information from the svnlook command:
http://weblogs.asp.net/lorenh/archive/2006/03/24/4...
Pay attention to the comment that mentions:
FOR /F "tokens=*" %%i in ('%~dp0sometool.exe') do SET TOOLOUTPUT=%%i
Thanks for your response.
Since sometool.exe is svnlook, how would that be set?
When I have this:
FOR /F "tokens=*" %%i in ('%~dp0C:\svnserve\bin\svnlook author -r "%REV%" "%REPOS%"') do SET TOOLOUTPUT=%%i
and
SET EMAIL_FROM=%TOOLOUTPUT%
this is the post-commit log:
The filename, directory name, or volume label syntax is incorrect.
Dec 03 09:34:34 myusername sendEmail[4084]: WARNING => The argument after -f was not an email address!
Dec 03 09:34:34 myusername sendEmail[4084]: ERROR => You must specify a 'from' field! Try --help.
I got this to work by copying the svnlook.exe into the hooks folder and using the syntax
FOR /F "tokens=*" %%i in ('%~dp0svnlook.exe author -r "%REV%" "%REPOS%"') do SET TOOLOUTPUT=%%i
Since svnlook.exe is 53 kb, this will do for now until I understand the %~ function.
-Peace
You don't need svnlook in the hooks folder, you just need to specify the path to executable. As my other blog entry on troubleshooting post-commit hooks talks about, hooks do not have access to environmental variables.
This means your batch file has a PATH environment that's empty (which is why svnlook might run from a command prompt without the full path.)
Anyway, just use a path to the svnlook.exe and all should be well.
There is a path set:
SET PATH=%PATH%;%DIR%;C:\svnserve;C:\svnserve\utils
I would think [svnlook] would be available like [svn log] and [sendEmail].
Since this is a standalone Subversion instance running as a Windows service, and the root repository folder is located on a different drive, and the FOR command in conjunction with the %~ command is not fully understood by me, perhaps this is why I choose to get it to work by placing svnlook in the hooks folder.
I think I have it running now without having to have svnlook in the hooks directory.
I removed the %~dp0, and just have the line as
FOR /F "tokens=*" %%i in ('C:\svnserve\svnlook.exe author -r "%REV%" "%REPOS%"') do SET TOOLOUTPUT=%%i
and then I can place
SET EMAIL_FROM=%TOOLOUTPUT% for use in the sendEmail command.
Thanks!
See my blog entry on debugging post-commit scripts for tips:
http://blog.pengoworks.com/index.cfm/2008/2/5/Debu...
I get the following in my log file:
C:\apache>svn update c:\checkout\procedures
Authentication realm: <http://address:80> Subversion repository
Password for 'SYSTEM':
I never created an account named system and I am committing from another machine using tortoise. Where does the script get its login info?
Thanks!
SYSTEM is a special Windows account. Sounds like the SYSTEM account does not have access to write tot he c:\checkout\procedures folder.
When I run the script, I get this error in my log file....the email runs, though without any info in it, but I get this error...can you explain this...all we need to do is run the script so we can update our development area.
Certificate information:
- Hostname:
- Valid:
- Issuer:
- Fingerprint:
(R)eject, accept (t)emporarily or accept (p)ermanently? svn: OPTIONS of 'https://server name/TestingRepository/trunk': Server certificate verification failed: issuer is not trusted (https://server name:8443)
Feb 06 14:56:56 server sendEmail[6196]: Email was sent successfully! From: <email address> To: <another email address> Subject: [SVN Update - subversion testing - rev 18 - E:\Repositories\TestingRepository] Server: [mailserver:25]
Also, use the physical path to the repository files instead of the URL--which will completely get rid of the need to use SSL altogether.
Are you referring to the UNC that is used through-out SVN? I don't believe we are using URL's for Repositories and or working files areas. We do have certs developed by Verasign for our system, so I am perplexed as to why it would not like them. Perhaps we are looking at the wrong kind of cert? I work with Daniel Fredericks and we really like SVN, provided we can get past this issue.
Just wanted to thank you for this code. We figured out what our issue was and this code works great.
I received the same output:
Password for 'SYSTEM':
And I solved it by adding the --username ARG and --password ARG options to the end of the svn up command.
