Archive for Diffing

MacHg 0.9.17 released!

I am happy to announce that I have just released MacHg 0.9.17.

You can get the latest MacHg from the downloads, and you can view the latest release notes here.

MacHg 0.9.17 greatly improves external diffing and merging tool support. You can now simply select a diffing tool and separately a merging tool from the drop down menus in the advanced preferences of MacHg. MacHg now directly supports the following external tools: FileMerge, Araxis Merge, P4Merge, DiffMerge, kdiff3, DeltaWalker, Kaleidoscope, Changes, DiffFork, BBEdit, and TextWrangler. Additionally, more development has gone into NSTask handling, which solves several bugs in this critical area. Mercurial extensions are now only referenced when needed for a small speed boost. MacHg 0.9.17 also updates the included version of Mercurial to the latest Mercurial 1.8.1. Other improvements in ssh configuration and disclosures have been added. In addition, other small fixes and enhancements have been made including fixing bugs #76, #98, #122, #163, #179, #198, #209, #211, #212, #214, #217, #218, as well as other unreported issues.

As in the other recent versions it’s now really close to version MacHg 1.0.0. This version puts on yet more polish. For end users, the notable new changes are the fact that most of the common external diffing and merging tools are now directly supported in MacHg. This was probably the second most requested issue users seemed to have.

As you can see from the following picture you can now simply just choose a tool…

Most of the external tools can be anywhere on your machine, but a few of them need to be in specific locations to run (e.g., p4merge). (MacHg tells you if you need to put a tool in a specific place.) Thus to use an external tool just download it from the publisher’s website. Then install it somewhere on your machine, then run it once and quit it (to ensure that OSX knows where it is). Then finally select that tool in the drop down in the advanced preferences in MacHg and do your diffs and/or merges with it.

(On a personal note, of the free tools I still think FileMerge is the nicest, but that’s probably because I am used to it. Certainly, p4merge is also quite nice, and DiffMerge is nice as well.) Also note that currently the only tool I am aware of which does binary merges is Araxis Merge.

If you are an author who makes an external diff or merging tool and would like me to add direct support for it to MacHg, please contact me. Ideally, if you are an external tool author then the diffing and/or merging scripts should live inside your application bundle, since client tools, like MacHg, can look up the location of your application bundle via the bundle identifier and thus get the direct path to the script. This means that the user only has to have the application installed somewhere on the machine and then the client, like MacHg, can do the rest (i.e. there doesn’t need to be any further configuration or installation of tools.) By the way, a notable exception to this rule is that for Kaleidoscope its users need to install the command line tools before MacHg can use this external tool. (MacHg recognizes this and puts up an alert telling you that you need to install these tools. Of course, this step isn’t that onerous, but anything we can do to easy users’ configuration hassles is an improvement.)

Also I would like to thank the authors of all of the commercial external diffing and merging tools used in MacHg for kindly providing me a license so I can do testing! Thanks guys!

Another change here is that the password option has been taken out for ssh. One might think this is a retrograde step; but actually it had never worked correctly in the first place. It turns out that in all my testing, I had my ssh keys set up in such a way that the password was ignored and it just worked. Due to a new warning in Mercurial 1.8.1 I realized this wasn’t working like it should. It turns out that it’s a security risk to pass the password through to another tool by embedding it in the URL. (This is due to the fact that if there is anyone else on your machine, they could simply read the password from listing the processes running on the machine. For this reason the creators of ssh tried to make it very difficult to pass a password or accept passwords through the normal channels, hence forcing clients to use more secure channels.) The gory details are in the email thread here. Thus, in the end I found that the best thing to do is ensure the client has their ssh keys set up correctly and non-interactively in order to do clean ssh connections.

Right on to the final MacHg changes before 1.0.0.

Cheers, Jason

Comments (2)

Unified diffs and GUI clients

Recently a user of MacHg asked how to display the differences in a file inside MacHg.

I personally have an opinion on this which differs somewhat from the established dogma. Thus I will outline my position here so I don’t have to elaborate it elsewhere, and hopefully it will make other GUI designers at least think about this issue.

The situation right now is that almost all GUI clients for Revision Control Systems (RCS’s) show differences “in application” through unified diffs. This is done because unified diffs are rather short and compact. But unified diffs don’t show all the surrounding code; and really in a large section of code with several changes, it is very difficult to immediately see what changes are occurring.

In fact, every single external GUI diffing program that I have seen has as default a side-by-side diff. (Some programs allow as an option, unified diffs, but it’s definitely something which is not the main thrust of the program.)

So, why does every single program that is dedicated to showing differences, display differences in a way different to that used inside almost all RCS GUI clients?

The reason is that most people sooner or later are forced into being able to recognize unified diffs. And after much exposure they begin to expect to see unified diffs, even though they are a very suboptimal way to view diffs.

Why do people get used to unified diffs? The reason is that since unified diffs are the raw format for diffs and are plain ASCII, they can be easily emailed around and inspected by people using tools which have nothing to do with diffing (eg email clients, text editors, displaying text on a web page, etc). In fact in some lists, sending unified diffs is the default way to exchange information, since in email ASCII is the lowest common denominator. (For instance, the mercurial development mailing list uses unified diffs as an interchange means of publicly discussing proposed changes.)

Of course, email is a very convenient interchange system, so developers are reading these unified diffs all day. Thus when some developer goes to create an RCS GUI client, they naturally put in the stuff they are working with all day, eg unified diffs.

But let’s take a look at what happens here in a screen shot from another RCS GUI client. (Note: I am not singling out this client amongst others, since many other clients do exactly the same thing.) However, of the overall window size (892 pixels x 689 pixels) the part which shows this unified diff is quite small (624 pixels x 192 pixels). Thus, just 19.5% of the window size is dedicated to showing the differences from one version of a file to the next in a semi-obfiscated patch interchange format.

I think its just sub-optimal.

(Of course for some die hard developers who eat, sleep, and breath unified diffs, maybe having some in program unified diff display is semi-convenient. However, to a large degree such people tend to use the command line in any case, so dedicating GUI features for them is futile.)

In this day and age of 32 inch LCD monitors, I think GUI RCS client programs need to live a little and somehow encourage the showing of diffs in the format that well… all dedicated GUI diffing programs use. Ie right now, use a very fast dedicated client or in-application code which shows the diff in a side-by-side format with full context in a large window.

(That said I have had more than a few requests for this feature in MacHg. And I try and do what users want… So maybe later I will have to toe the line and add these unified diffs into MacHG… But I am resisting for now…)

Comments (1)

FileMerge and UTF-8

I really like apples FileMerge tool for comparing files but you can sometimes get problems when diffing files which are UTF-8. In fact when you have non-ascii characters, with eg umlauts or graves, etc the diff will look like it has garbage in it.  For background see this hint at Mac OSX Hints for a bit of background on this. Basically to make sure FileMerge does a nice diff on files which are UTF-8 encoded you need to set the extended attribute com.apple.TextEncoding to be ‘UTF-8;134217984‘, and then your diffs will work correctly. I needed to solve this exact problem for MacHg. Thus a general diff script for whatever revision system which uses FileMerge should set this attribute correctly. Ie if you are using, git, subvbersion, Mercurial, bazzar, or anything else likely the script for diffing should be setting the text-encdoing extended attribute.

It can be done by adding the following script somewhere on your unix path fmdiff.sh. Eg unzip and move this bash script to ~/bin/fmdiff.sh (assuming this is on your $PATH). This is a typical filemaker diff script as you can find floating around, eg here.  However the important part of this script is at the end where we have:

# Find the com.apple.TextEncoding extended attributes of the files
leftattributes=xattr -p com.apple.TextEncoding "$leftfile" 2>/dev/null
rightattributes=xattr -p com.apple.TextEncoding "$rightfile" 2>/dev/null

if the encodings are not UTF-8, then make them UTF-8

shopt -s nocasematch if [ -z "$leftattributes" ] || [ "$leftattributes" != "UTF-8;134217984" ]; then xattr -w com.apple.TextEncoding "UTF-8;134217984" "$leftfile" fi if [ -z "$rightattributes" ] || [ "$rightattributes" != "UTF-8;134217984" ]; then xattr -w com.apple.TextEncoding "UTF-8;134217984" "$rightfile" fi shopt -u nocasematch

This snipped of code above in the script ensures that the extended attribute is set on each of the files before they are diffed using apple’s opendiff which in turn calls FileMerge.

After fmdiff.sh is installed you can simply call fmdiff in exactly the same way as opendiff. Eg:

Leave a Comment

Make FileMerge diff .plist files

In doing macintosh program development I had often come across the case where I wanted to view the difference between two .plist files. Specifically when you are doing diffs of say your UserDefaults.plist in your application you are developing in XCode say…

Previously .plist files were all stored as ASCII files but in OSX 10.4 Apple started compressing them. If you attempt to diff one of these compressed .plist files in FileMerge it complains that the files are binary and should it proceed anyway. If you do proceed you get a comparison between garbage and garbage and you can’t see any of your changes to verify that you made the right changes in Xcode.

Anyway I had googled for a solution but didn’t find one easily. But recently this annoyed me enough that I overcame the thresh-hold of annoyance and looked for a solution. (likely you are reading this post for the same reason!) So it turns out that its pretty easy to get FileMerge to nicely display diffs of .plist files.

You need to add a simple filter to FileMerge. You can do this by hand.

  1. Open File Merge
  2. Go to Preferences -> Filters
  3. After the last item in the list of filters double click to enter new values and enter without the quote characters
  4. ‘plist’ in the extension column.
  5. ‘/usr/bin/plutil -convert xml1 -o –  $(FILE)’ in the Filter column.
  6. ‘Filtered’ in the Display column.
  7. ‘No’ in the Apply* column

Thats it. It should look like something like (I have a few other filters in there as well):

Picture of final FileMerge preferences

FileMerge Preferences

Or if you are more macho about such things, execute the following in the terminal:

defaults write com.apple.FileMerge Filters -array-add '{ Apply = 0; Display = 0; Extension = plist; Filter = "/usr/bin/plutil -convert xml1 -o -  \$(FILE)"; }'

Thats it. Go do some diffing!

Comments (4)