Archive for the ‘Source Control’ Category

Setting Up Local Source Control With Subversion

Saturday, December 19th, 2009

I love source control, but I tend not to use it for my “at-home” development for the simple fact that setting up a separate server is overkill, and I don’t like to have random server processes running on my personal machine.  Unfortunately, this means that I lose out on my favorite use for source control – the ability to test and try out new code and features without worrying about screwing up the “main” development.

However, after recently spending a fair amount of time undoing and redoing some changes to a website I am working on, I have decided that enough is enough, and I set out to install a local source control system on my development computer.

Initially I decided to look into Git.  It certainly seemed to fit my need, so I began to look into using it.  It wasn’t long before I realized that I had to get a “special” version of git to run on my windows box.  This was less than ideal for me, especially when  began reading about how much work was left to be done on the Windows version.  The last thing I need is an unstable version control system.

After having experienced a failure in my attempt to use the new and exciting tools (and yes, I am aware of Mercurial – it certainly seemed like a better fit for me), I decided to try to see if I could get the tried and true Subversion to do what I wanted.  It took me all of about 5 minutes of searching to determine that I could in fact use subversion to access a local repository, with no need for for a server or network access.

This was perfect.  I downloaded the Tortoise-SVN client, and sure enough there was an option right there in the client to create a local repository.

Context menu for Tortoise SVN

So I created a folder (“c:\svn”) off my root and created a repository there.  All that was left was to import my existing files into the repository.  Again, tortoise-svn made it simple.  I navigated to the root of the project I wanted to add, selected the root folder, and chose the “import” item.

Tortoise-SVN Import Dialog

Unfortunately, this is where I hit my first snag.  According to the documentation, to connect to a local repository, you simply use the “file://” protocol, followed by the full path to the desired repository directory (in my case, “c:\svn”).  So, I attempted the url “file://c:\svn\”, but received an error:

Unable to open an ra_local session to URL
Unable to open repository ‘file://c:/svn/’

This was not a very helpful error.  I knew the repository existed at the location “c:\svn”, but how could I connect to it?  Looking online for the error message did not seem to provide much in the way of resolution for me, so I began to try various combinations of the protocol and the path.  Finally, I found that “file://” plus “/svn/” successfully connected.  In hind-sight it seemed obvious subversion would expect a linux-style notation, but the examples I found online all used a windows-style volume and path notation.

Once I had imported my existing data into the repository, all that remained was for me to check out a copy back into my original directory.

Tortoise-SVN Checkout

Clicking OK popped up a warning that the directory was not empty, which I accepted, and the files were all “checked out” from the repository and were ready to be worked on.

That’s all there was to it.  I now have a fully working local source control client without the need for a server.

Subversion, Command Line, and Redirecting the Standard Output

Tuesday, January 13th, 2009

I'm going to interrupt my estimation tool project in order to comment about an interesting mini-project that I finished last night.? Being a big fan of code reviews, I have recently managed to convince my team at work to require reviews for all code checked into the main repository.? Once I had everyone on board, I used a handy subversion hook provided by our review tool to enforce our new review policy.? This has worked well for the past month or two, until just recently when our project began to move into the pre-release testing phase.

The problem is that we have a large number of test models and the inability to commit new models without a review was beginning to hold up our progress on testing.? So it was requested that I exclude the test model directory from the review requirement.? It sounded pretty simple, so the first thing I tried was to look at the hook provided by our review tool to determine if I could have it exclude files or directories.? Unfortunately, it couldn't.? A quick web search turned up nothing resembling the hook I needed, so this left me with only one basic recourse – write my own.? Besides, it was an interesting diversion from my usual responsibilities.

Since we use subversion, setting up the hook was simple.? Essentially, I edited the pre-commit template to first call my own custom application that would determine if the changes being committed could be excluded from the review requirement.? If they could not be excluded, I called the review hook.? Simple, except I still had to figure out how to find out which files were being changed and figure out how to access that information programmatically.

The first problem was easy – SVNLook was made for just this occurrence.? With it you can discover a wealth of information about a given transaction.? The problem is that it is a command-line application that writes its output to Standard Out.? Of course, I know all about the theory of redirecting the standard output and so forth, but having spent my entire career doing graphical desktop and web-based applications, I had never had the chance to actually attempt it.

Fortunately, C# makes the entire process ridiculously easy:

????? System.Diagnostics.Process svnLook = new System.Diagnostics.Process();
????? svnLook.StartInfo.FileName = "svnlook.exe";
????? svnLook.StartInfo.UseShellExecute = false;
????? svnLook.StartInfo.RedirectStandardOutput = true;
????? svnLook.Start();
????? string output = svnLook.StandardOutput.ReadToEnd();

?

That's all there is to it.? The local variable “output” holds the entire output of the svnlook program.? The ReadToEnd method is useful because it blocks until the stream is closed, allowing you to block until the execution is complete.

There are other ways to do this (such as using the System.Console.SetOut method), but this was by far the easiest method I found.? Note that you must set the UseShellExecute property to false if you redirect the standard output, otherwise you will get an invalid operation exception (according to the documentation).

All things told, it was a refreshing change of pace for me, and a fun way to spend an hour or so at work.? I may even write and post a full-featured hook one of these days (of course, I'd probably use a different language to make it as portable as possible). In the meantime, I guess I should get back to my own mini-project…

Commit Wars

Monday, December 15th, 2008

Quick show of hands…? How many of you have gotten into a commit war?? I think we all know what I'm talking about – some projects even have rules that exist solely to prevent commit wars from occurring (they generally take the form of limiting the frequency of commits for a given file).? These things generally start out innocently.? Some well-intentioned developer opens up a file and decides that a couple of variable names aren't as clear as they should be.? So he renames them.? Since he is already in there, he reformats a couple of lines of code to meet his personal preferences and commits the file.

The original developer is then informed of a defect in her code.? Nothing serious – a simple mistake in the index being used.? She opens the file and is confused by the naming scheme – it seems the new names conflicted with the index name, and resulted in the defect.? In addition, the code was reformatted in an odd manner.? A firm believer in “the one true brace style”, and already on edge for taking the blame for a defect introduced by someone else, she reverts back to the original check-in and reformats the entire file to fit her preference.

The first developer notes the change in the file and the loss of all his insightful and very carefully chosen variables names.? Now furious, he undoes the commit and sends a nasty note to the original developer instructing her to leave his changes alone.

Not one to take something like this lying down, the original developer begins to nit all of his code in reviews.? When he doesn't fix her complaints, she comes in afterwards and changes it anyway.

Preventing Escalation

In hind sight, commit wars are remarkably simple to prevent.? Simply by mandating a standard code format you can avoid the majority of commit wars.? In addition, it is critical to ensure that your reviews focus on real problems and not on simply stylistic or implementation preferences by the reviewer.?

Of course, the most crucial element to preventing a commit war is to create an environment and team where there is enough respect that the developers do not feel the need to look over each other's shoulders.? If no one can trust the rest of the team to do things right, then every little change is subject to enhanced scrutiny, and possible retaliation.

Finally, if every change requires a peer review, most of these problems will never make it past the review.? Too often, teams believe that only the major changes should be reviewed.? But by putting a lightweight review process in place to review every code change, you can avoid the sorts of unnecessary changes that create commit wars.? Of course, if you actually expect to get things one, you had better make sure that your reviews are quick and painless…

Controlling Installers

Wednesday, August 13th, 2008

This is a topic that I don't really know what common practice is but I seem
to consistently encounter resistance when I suggest it.? I am a firm believer
that any and all installers created should be controlled and versioned the same
as any other artifact of development.? That means it goes in source control.? To
me, it just makes sense – that way at any point in time you can go back and grab
the exact bits that were built and (possibly) delivered.? There is no substitute
for having the exact copy when an obscure bug report filters in.?

Just recently we delivered a new version of our software to testing.? Our
group has a very limited testing staff, and so it ended up being a day or two
before they were able to install and begin testing the software.? Within 15
minutes of installing the software, we began to get all sorts of bug reports.?
Nothing was working.? Of course during this time, the development staff had
continued pressing on to meet their deadlines, and had not encountered any of
the issues being encountered by the test staff.? Dutifully we reverted back to
the version of the software being run by test in an attempt to verify what was
occurring.? Unfortunately, we don't control copies of our installers, so we had
to rebuild them.? Once that was done, we installed and ran a few tests, but
everything seemed fine.? We showed test what was happening and they agreed that
everything seemed OK.? We decided to re-install the software on our test boxes.?
We installed the software and sure enough, all the problems went away.? A
miracle, right?? Or maybe someone secretly fixed all the problems and delivered
them and that's what was built…

In general, there seems to be two lines of resistance to including the
installer in source control.? The first is the belief that source control
doesn't handle binaries well.? This may have been true many years ago, but any
mature source control system should handle binary files just as easily as text
files.? When people claim that is the case I immediately suggest they upgrade
their system.? The second line of resistance seems to be that since the build is
deterministic and completely automated, it will always produce the exact same
result.? In theory this is true, but in practice there are far too many
variables to rely on a bit-for-bit copy every time.

For example, as it turns out, in our case the problem was due to a licensing
issue.? We had received a new runtime license for some software we are using,
and had forgotten to put it on the build machine.? The build incorporated the
old license (which has expired), and so after it was installed and test began to
run it, the software was unable to retrieve a valid license, and failed.? Of
course, by this time, we had updated the license on the build machine, so when
we attempted to reproduce the issue by rebuilding our software, we built the
correct license into the software and viola! problem solved.

So, it is not enough to revert the source code back to the original state and
have an automated build, you really should be reverting the entire build machine
back to the state it was in when the software was built.? That should guarantee
that you reliably build the exact same bits as when it was originally built.?
But then again, if you are going to go to that much trouble, why not simply
control the installers themselves?

?