Visual Studio and vsDiffMerge with Mercurial and TortoiseHg

Typically, when I have worked within Visual Studio on source-controlled projects I have used Team Foundation Server (TFS). With my current employer, we use Mercurial, and we use TortoiseHg to interface with it. For me this seemed to be a disconnected experience and I have been looking for ways deeply integrate it. To that end, I have been using VisualHg as my source code control provider in Visual Studio, and recently found a way to use Visual Studio as my Diff and Merge tool from TortoiseHg. I have detailed the process of setting this up below, and authored an installer, which automates these steps. I will not cover the steps for setting up, nor using VisualHg as its own site does a good job of that already.

What you will need

Verify a few things first

  • You should have a file named vsDiffMerge.exe in the Visual Studio IDE directory, typically “C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\vsDiffMerge.exe”.
  • You should have a file named Mercurial.ini in your user directory, typically “C:\Users\%USERNAME%” or “%USERPROFILE%”.
  • TortoiseHg is NOT currently running. If you cannot shut down TortoiseHg, that is fine but will require a restart at the end.

If we have everything we need, and have verified the few things mentioned above, we are ready to proceed. We will do most of the work in Mercurial.ini, and a new batch file that we will create. The batch file will handle calling the Visual Studio components and give us a simple path to configure in Mercurial.ini. Therefore, we will start there.

Wire it up

Open the text editor and create a new file. Copy the batch script code below into the new file and then save the new file as HgVsDiffMerge.bat in your user directory (%USERPROFILE%).

If you are using Visual Studio 2012, then change the variable “VS120COMNTOOLS” to “VS110COMNTOOLS”, or if you are using Visual Studio 2010 then change the variable “VS120COMNTOOLS” to “VS100COMNTOOLS”.

Now, make a backup copy of your Mercurial.ini file. If you just read that and ignored it, please stop and go make that backup copy of Mercurial.ini now.

Now open Mercurial.ini in your text editor. We will focus on a couple of sections in here. The first section (which may not exist) is the “merge-tools” section. If you do not have a “merge-tools” section, you will create one. Here we tell Mercurial, and TortoiseHg, about the batch script we created earlier. The section should look like the snippet below.

Now Mercurial and TortoiseHg know that there is a merge tool called vsDiffMerge. They know where to find it, and how to invoke it for a merge or diff. Now we will tell them to do so. In the “ui” section, set the value of “merge” to “vsDiffMerge”. In the “tortoisehg” section, set the value of “vdiff” to “vsDiffMerge”.

Save the Mercurial.ini file.

If TortoiseHg has been running this whole time, shut it down. Now launch TortoiseHg and select a change-set, right click any non-binary file in the change-set and select “Diff to parent”. If all went well, you should be looking at Visual Studio comparing your two file versions. You will also notice that now you have some of the benefits like hovering to see variable types and other useful diff and merge tools. This will be similar for merges, but will have an additional pane below those two, showing the result of the merge that would be committed.

You can also download the installer I authored which automates these tasks. It is available here as HgVsDiffMergeSetup.zip (zipped MSI).

Eliminating #if Preprocessor Directives

Maybe it’s just me, maybe I’m old school, or maybe I’m not old school enough. In my opinion using the #if preprocessor directive should be a last resort, not a first choice. Consider the scenario where you are working on a project as part of a team. You create a class with a method that does something useful…and then people start coding against it. Of course, they trust that you’ve provided a stable implementation and they don’t need to review your code prior to calling it. So maybe your implementation looks something like this…

So your colleague came along and started using this new utility and finding it very helpful. His implementation might look something like this…

The code compiles and tests out GREAT! It passes through the CI (continuous integration) process just fine, and even makes it through QA without any problem. Then the code is built for release…and that configuration doesn’t define the DEBUG directive. So what happens to the code now?

  • AwesomeProgram.cs: error CS1501: No overload for method ‘DoSomethingUseful’ takes 2 arguments

Now your colleagues’ code has broken the build that everyone thought was solid through QA. That call to DoSomethingUseful should have been written to only pass the second parameter #if DEBUG, but how was your colleague going to know that? There was no commenting that the IDE could recognize to warn the user that the ‘value’ parameter is conditional, the parameter name didn’t indicate that it was only present #if DEBUG, so short of NOT trusting your implementation and reading every method you provide (which the whole team will be doing now) there was no way for anyone to know. All of that embarrassment, trouble, and the resulting mistrust of your code could have been avoided.

Another, even more painful scenario, is one that the compiler cannot catch for you and can very easily make it into production. The over simplified example below shows how misusing preprocessor directives can easily cause you trouble in production, the code compiles perfectly with or without the preprocessor symbol DEBUG being defined. This could easily be a much more important or critical bit of code inside the #if, here it’ll just save us from a null reference exception when DEBUG is defined and introduce a possible null reference exception in production.

In this example, the directive simply should not have been used. Perhaps a better example of a possible proper use for #if would be…

…at least now we can see the clear benefit in the alternate code. If debug then make sure we have a string value for some reason, otherwise return early because there’s no reason to continue.

How can you avoid this using a ConditionalAttribute?

With the ConditionalAttribute we get a few of benefits. Depending on your particular situation you may be able to get other benefits.

  1. All of the code, always exists and always has to compile.
  2. All of the code can be seen by the editor for advanced actions like refactoring and symbol renames.
  3. Even the debug scenario could operate like the release scenario without modifying anything other than the debug method body.

How is this ok for release? Well simply put, the compiler will turn the DebugFixUpString method into a no-op, so that any runtime code which would have called it is now just calling no-op.

Here’s what the reflected code looks like for a release code of the ConditionalAttribute example above.

You can clearly see that our conditional method still exists, but you can also clearly see that the compiler has removed the call to it because the DEBUG symbol was not defined at compile time.

Another common scenario for preprocessor directives is compatibility. Consider the situation where you’re creating an SDK and providing functionality supporting multiple .Net Framework versions. You might be thinking, this is a place for #if for sure! Not really. We can still avoid #if in multi-version targeting pretty easily.

Using a simple project structure and partial classes we can target different .Net Frameworks with differing framework functionality and underlying implementation, without affecting the eventual implementation details. Here’s a project structure example where a .Net Framework 4.0 project was created, and then backward compatibility was introduced in a .Net Framework 3.5 project which simply links in all the 4.0 project files and splits the classes with compatibility issues into partial classes to provide alternate implementations for .Net Framework 3.5 targets.

Preprocessor Directives Project Structure

The BestUtilityEver class is now split between three files. One common file in which the implementation is compatible with both framework versions, one v3.5 file for the v3.5  specifics and one v4.0 file with the v4.0 specifics. All three files form one single class at runtime and provide all the required signatures for the consuming implementations. Here’s what those files look like.

 

So, how do you avoid #if in your code?

  • Don’t use preprocessor directives
    Figure out why you have this variation and try to design it out of your solution, if you can’t try some other mechanism, possibly the ConditionalAttribute or something like it, that the compiler can understand to gracefully handle variations.
  • Know your tools
    Know what your development tools are capable of, and what your compiler is capable of.
  • Comment your code
    If you exhaust all other options and have to use preprocessor directives then comment your code in a way that the IDE your team uses can understand so other team members at least have the chance to understand that they need to pay more attention than usual to this particular implementation. Give your colleagues a fighting chance to not break the build.

While I was writing this, a colleague of mine sent me a link to a case study titled “#ifdef Confirmed Harmful: Promoting Understandable Software Variation” asserting that preprocessor directives are actually harmful to managing software variation. It was a very interesting read, have a look for yourself. What are your thoughts and experiences on preprocessor directives? Am I right, am I wrong, have I just gone completely off the deep end? Like I said in the beginning; maybe it’s just me, maybe I’m old school, or maybe I’m not old school enough, but I want to know what you think.

You’re infinitely more likely to find a better solution if you look for one.