CVS Autoupdate on Windows

Want to automatically update/create the latest versions of files on CVS on Windows? It can be done, and it’s quite useful when developing server-side applications!

I’m working on a ColdFusion project in a small team, and wanted to take advantage of CVS to prevent editing same files at the same time. Because of the nature of the project the components could not be tested on local systems, and recreating the actual .cfm, .cfc, .xml, etc. files after every edit didn’t seem very much fun. I had previously used CVS on UNIX side and knew that autoupdate would be possible. However, to get it running on Windows required some extra steps.

On the UNIX side all that is needed is that you check out a working copy to the repository (or other) folder which is accessible under web root (so that you can test the files via the web server), and then add something like this to the loginfo:

ALL ((cd /path/to/repository/module; cvs -q update -d) &) >> /dev/null 2>&1

The ampersand (inside the parentheses) forks the process and thus cicumvents the problem with CVS repository locking. Whenever a commit is made, the update is run, and you can view the latest files via the web browser.

BUT on Windows this doesn’t work. I initially wrote a small batch file like so:

cd e:pathtorepositorymodule
"c:Program FilesCVSNTcvs.exe" update -d

… and initially thought that it works. But it soon dawned on me that the update was always one version behind the current. That’s because the current version was still locked by the CVS when I called the batch file from loginfo.

Lots of searching on the web ensued. Finally, I came across Jouni Heikniemi’s website on »CVS: Using loginfo to send mail with diffs on Win32/CVSNT». While I did not need the diff/mail functionality, the core problem was the same: how to bypass the CVS file locking in Windows’s threaded environment? Jouni had solved the problem by creating two Perl files, one of which is called from loginfo, and the second one is subsequently called from the first one, thus spawning a new process that waits around for a few seconds for the CVS locks to be released, and then performs the update.

I adapted Jouni’s Perl files for the purpose of auto-update. The resulting files are extremely simple.

#!c:/perl/bin/perl -w

# Spawn another process to avoid CVS locking. 

# Construct the path to
$autoupdatepath = "e:/inetpub/cvstools/";

# Call the system command interpreter and start a new process
system($ENV{'COMSPEC'}, '/c', 'start', $autoupdatepath);


#!c:/perl/bin/perl -w

# Wait for a moment so that the main (calling) CVS task finishes 
# and releases repository locks. Then run update.

sleep 5;

chdir "e:/inetpub/wwwroot/cvsdev/viaproject" 
	or die "cd failedn";

@args = ("c:/Program Files/CVSNT/cvs.exe", "update", "-d");

system(@args) == 0 
	or die "system @args failed: $?";

(I realize the Perl code could probably be more eloquent, but Perl is not my forte, and this works. :))

Now I simply call the first file from loginfo with…

ALL c:/perl/bin/perl e:/inetpub/cvstools/

.. and when a commit is made, within few seconds the resulting files are updated as well, and I can hit refresh on my web browser pointing to the development directory to see whether the edit produced the desired result.

By the way, this all pertains to cvsnt! Client, on the other hand, can be anything that supports cvs. Eclipse, of course, is a nice IDE, but for many smaller projects TortoiseCVS is perhaps more suitable (it’s lighter, and you can use any editor you like.. like UltraEdit :)).

If I have gone out of my way to do do something very simple in a very difficult way, please feel free to comment!