This is wildly speculative, and is no way descriptive of current Sparkle behaviour or semantics. Caveat emptor.

Poset Versioning

The idea behind this proposal is to use Posets to model the relationship between different versions of a single application. Posets (partially ordered sets) are a mathematical model of ordered relationships between objects; here, we are looking to model the order of two versions, so as to determine whether an available version should supersede (be offered for installation, etc.) an existing installed version.

Technically, we only want to use strict posets (different versions can't be considered equal), which are isomorphic to directed acyclic graphs (more on that later)

Throughout this discussion, posets will be shown diagrammatically from left-to-right, rather than the traditional bottom-to-top Arrow heads are also sometimes omitted, but it should be obvious which way they should go.

Example

Let's jump straight into an example where this could be useful:

                            --- 2.0b1 <-- 2.0b2 <-- 2.0b3 <--
                           /                                 \
0.1 <-- 0.2 <-- 0.9 <-- 1.0 <-- 1.1 <---- 1.2 <-------------- 2.0 <-- ...

This represents the versions of an application that has some initial releases (0.1 up to 1.0), then starts a "beta" branch (2.0b*) while still making a couple of point releases on the "stable" branch (1.*). You'll notice that any pair of versions are either comparable (we can follow a directed path from one to the other), or they are incomparable (there is no directed path between them).

This gives us a few very useful things immediately:

  • An iron-clad version comparison method. The developer can use whatever wacky versioning scheme they want, yet we can always work out the proper order of two versions by walking the poset.
  • An easy (and sensible) way to collate release notes, again by walking the poset.
  • A clean way to represent branches (see below)

Even if you don't want to use this mechanism, Sparkle could auto-generate a temporary poset structure using its existing version comparison functions, and you'd end up with a straight linear poset (which is actually a totally ordered set).

Branches

We simply label the first version of a branch, subject to one restriction: all the labels must be pair-wise comparable. That is, for any two branch labels, you must be able to follow a directed path from one of them to the other. Also, only one branch label per version is permitted.

To determine what branch a version is considered to be a part of, we follow a directed path (or paths) back until we hit a label on those paths:

  • If we can only hit one label, we take that label.
  • If we can hit multiple labels, we take the minimum label, as determined by their ordering in the poset.

In the example above, we could label 1.0 as "stable", and 2.0b1 as "beta". That means that all the pre-1.0 versions would be "default", 2.0b1, 2.0b2 and 2.0b3 would be "beta", and all the others are "stable". The reason behind the restriction for branch labels is to allow for cases such as version 2.0, which can reach both the "stable" and "beta" labels via different paths.

Implementation

I think the Sparkle version tagging should be taken out of the single <enclosure> tag, instead sitting parallel with that inside the relevant <item>:

<item>
  <title>Version 2.0</title>
  <description><![CDATA[
  <p>Here are my normal release notes for this version. Ain't it grand?
  </p>
  ]]></description>
  <enclosure url="whatever-2.0.dmg" 
    sparkle:md5Sum="58388107817bbe26ad9ca40391364965"
    length="652454" type="application/octet-stream" />
  <sparkle:version>2.0</sparkle:version>
  <sparkle:supersedes>1.3</sparkle:supersedes>
  <sparkle:supersedes>2.0b3</sparkle:supersedes> <!-- as many as we want -->
  <sparkle:branch>stable</sparkle:branch>   <!-- optional, of course -->
</item>

Or something like that. My XML-fu isn't great, and I think this is diverging from standard RSS. All versions would have a similar <item> entry in the appcast XML file.

While I like the simplicity, there is a problem with the above XML example: it requires the version names to be unique. While that may not affect many developers, who's to say that everyone names their versions with the same logic? I'd recommend that the sparkle:supersedes tag can include (but shouldn't require) a branch tag to uniquely ID the version, in case of naming collisions. -Groxx