Merge Visual Studio Resource Files (.resx) using SortResX
Have you ever tried to merge WinForms .resx files and ended up with a big headache because the conflict blocks are huge and you don't know how the result should be? The SortResX tool will solve your problem, find out how in the next lines.
The problem
Plastic SCM provides lots of tools for merging correctly source code files, and that’s great, because not many Version Control Systems provide a good support for merging. Some of those systems provide a great branching mechanism, but the REAL problem about branching is not the branching process itself, but the merging process..
Anyway, some of us miss some kind of support for other file types. I’m not thinking about documentation; if someone can write a semantic merge tool for real text he or she probably would deserve the next Nobel Prize, for sure. I was thinking about XML files. Lots of development tools use XML files for saving configuration properties or share some information with other tools. Some of those tools change those XML files massively when a user change just a small property, so in the end the dude who integrates the changes get mad trying to solve the conflicts originated by that damned tool. Most of the times that dude it’s me, and if the conflict cannot be solved in a reasonable amount of time, I tend to discard the task and… well, that’s not parallel development, you know.
An approach to merging XML files
We use at Codice Software a very simple tool that help us merging changes in resources files, which fit perfectly in this problem. Some day I thought: “Hey, why don’t we share this with other users? Probably they would find it useful!”, and a couple of days after that someone reported that he had problems merging XML files and he would like a tool that helped him with this task.
The tool source code is available at GitHub and it is rather simple: it reads an XML file, sorts alphabetically in memory all the keys and write them back to the file in that order.
Next, I’ll explain to you how we use this tool to make our lifes easier and work a little bit less. A .resx file looks like this usually:
<data name="ThumbTopper.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</data>
<data name="ThumbTopper.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>Private</value>
</data>
Simplifying:
<data name=”key” …>
<value>whatever</value>
</data>
The sortresx.exe takes the “name” as a key and sorts all the keys alphabetically. Let’s execute sortresx with some of the examples provided in the GitHub repository:
C:\>sortresx.exe examples\clientcommonTranslations.resx
C:\>
Beautiful, isn’t it? Well, what did you expect? Fireworks? This tool is designed for being used with Plastic SCM to merge files, so writing some output when everything goes ok is not that useful, as we’ll see a little bit later.
If you open the “clientcommonTranslations.resx” file and move some key:
to a different location in the same file (notice the line numbers):
Now we run sortresx again:
C:\>sortresx.exe clientcommonTranslations.resxand open again the “clientcommonTranslations.resx file:
You’ll see that the file has been sorted alphabetically and the moved key went back to it’s previous place (the examples provided are already sorted in alphabetical order).
Using sortresx.exe in Plastic SCM
Let’s move on to the point I wanted to show you today: how does sortresx.exe help to merge easily .resx files?
Firstly, configure sortresx as an external mergetool in Plastic SCM that deals with .resx files. Open your client.conf file (located in c:\%USER%\AppData\plastic4) and add the following inside the <MergeTools> section:
<MergeToolData>
<FileExtensions>*.resx</FileExtensions>
<Tools>
<string>sortresx "@sourcefile"</string>
<string>sortresx "@basefile"</string>
<string>sortresx "@destinationfile"</string>
<string>mergetool -b="@basefile" -bn="@basesymbolic" -bh="@basehash" -s="@sourcefile" -sn="@sourcesymbolic" -sh="@sourcehash" -d="@destinationfile" -dh="@destinationhash" -a -r="@output" -t="@filetype" -i="@comparationmethod" -e="@fileencoding" -m="@mergetype"</string>
</Tools>
</MergeToolData>
I assume that the place where sortresx.exe is located is in the %PATH% ($PATH in Unix). Otherwise you must specify the full path to the program or it won’t be found. I have it located in the Plastic SCM client.
We do this change manually instead of doing it from the Preferences dialog because, as you can see above, we need to specify multiple tools: one for each contributor, and finally we specify our good ol’ mergetool to process the sorted files. Now, if we open the Preferences window, we’ll see that a new rule has been added for resx file and the merge tool used is “MULTIPLE_TOOLS”:
So far so good. Now, this is what it will happen from this moment on when we try to merge .resx files:
1.- Base, source and destination contributors are processed by sortresx.
2.- Then, after sorting alphabetically the keys, mergetool processes the three files. If there’s any manual conflict, mergetool is shown. Otherwise it’s not.
As you can see, this approach assumes that the position is not important regarding keys modification, but the names of those keys. If the modified names are close to each other or match, then there is a conflict that must be solved manually.
Easy, isn’t it? Let’s see a typical use case.
Initially, we have a resources file that it’s not sorted at all. User 1 modifies the resx file removing some keys that are no longer necessary between lines 67 and 76, and User 2 add some keys between lines 72 and 77:
If these changes would be merged right now, a manual conflict would appear in mergetool, since the same lines have been modified: changes made by User1 and User 2 are overlapped.
But if we put sortresx.exe in the middle, both contributors are sorted and the changes are reorganized along the file content. To simplify the case we’ll only show source and destination contributors:
When mergetool comes into play, it has much less work than before, now there’s no manual conflict anymore and the merge is automatic:
This is a rather simple case, but if we would have had lots of conflicts in different blocks, we would have saved some time and manual work with this procedure.
How about other XML types?
Well, probably you’re wondering now what happens with other XML structure files. There’s not a solution that applies to everything, so you’ll need to adapt this tool to your particular case. That’s why we decided to release the source code, because it’s possible that the binary doesn’t fit as-is in your setup, so feel free to modify it and adapt it to your particular project.
Take into account that this tool writes the original files and reorganizes their content, overwriting them. This is not a good solution if the program that handles your XML file doesn’t expect this, I mean: if the location of the keys are important this is not a good approach, definitely.
The basic idea that we applied here is: order all the entries of a given XML structure type by some criteria (the “name” of the localization keys, in this case). If you’re able to identify that entity, you can simplify your XML merges a lot.
0 comentarios: