LockFocus

Dynamic Sparkle Release Notes

By now I’m sure all Mac OS X developers have heard of Sparkle – the excellent auto-updating framework by Andy Matuschak. When I added Sparkle to Lexicon, I only ran into one problem. The release notes that Sparkle displays are decided by what version you are updating to, but they should depend only on what version you are updating from.

This might sound a little backwards at first, but let me explain. In the most common updating circumstances, you want all of your customers on the latest version. Here’s an example: You first release your 1.0, and later release 1.1 to with a killer new feature-everyone updating should see the 1.1 release notes, which mention the new feature. Then later you release 1.2, which has some bug fixes. Now you’ll want everyone to update to 1.2, so you don’t want to show just the 1.1 changes by themselves. But, what about the people who are still running 1.0? You want them to see the changes and features in 1.1 in addition to those from 1.2. If we know what version they’re updating from, we can figure out which release notes to show (always going up to the latest release).

So I made a minor change to Sparkle to address this. In the checkForUpdatesAndNotify: method in SUUpdater.m, I added the line in bold:

// ... code to get appcastString from user defaults or Info.plist
SUAppcast *appcast = [[SUAppcast alloc] init];
[appcast setDelegate:self];
appcastString = [NSString stringWithFormat:appcastString,
    SUHostAppVersion()];
[appcast fetchAppcastFromURL:[NSURL URLWithString:appcastString]];

Now instead of getting a request for something like:

http://downloads.likethought.com/appcasts/lexicon.rss

I get a request for:

http://downloads.likethought.com/appcasts/lexicon.php?version=1.0

In this appcast file, you can specify a URL for the change notes. I send them all to the same PHP file (since they will all be updating to whatever the latest version is), and I pass this PHP file the $version variable. This is what my changes PHP file looks like:

<html>
    <body>
    <?php
        $versionNum = ereg_replace("[^[:digit:]]","",$version);
        while(strlen($versionNum) < 3) {
            $versionNum = $versionNum . "0";
        }
        if ($versionNum < 110) {
            echo "<h2>Changes in 1.1</h2><ul>";
            echo "<li>Added killer new feature</li>";
            echo "</ul>";
        }
        if ($versionNum < 120) {
            echo "<h2>Changes in 1.2</h2><ul>";
            echo "<li>Bug Fixes</li>";
            echo "</ul>";
        }
    ?>
    </body>
</html>

I only do very basic processing, strip out non-numeric text and convert the version to an integer, then check which changes they need to see. If you want to implement something similar, you could check for more differences in the version (like 1.0, 1.0b, 1.0rc-final, etc) or you could only prompt users to update to the same major version that they are running (i.e. not from 1.x to 2.x). The most important change is just the line in bold added to the Sparkle code. With that added, you can tweak to your heart’s desire.