found drama

get oblique

a better version comparator

by Rob Friesel

Back in February, I wrote a little Ruby script to deal with sorting version numbers as they’re dumped out of the git tag command. The problem (in a nutshell) is that "1.0.2" < "1.0.10" — except that git returns these as strings which sort alphabetically. Hence the original Ruby script.

Now: if you’re behaving yourself, and following “The Driessen Model” more/less to the letter, then you should only have properly formatted tags in your git repo(s) and this won’t be a problem. But we also know from experience that people will inevitably mess this up, be it through negligence, naiveté, and/or a good ol’ fashioned nonconformist spirit.

Now, that original script was good, but it had a few flaws. For one thing, it was destructive; you wouldn’t always get out what you put in.1 And though it dealt reasonably well with arbitrary depth, it also relied on some good ol’ fashioned “Ruby magic” to resolve some of the mis-matched version string lengths.2

So how do we deal with this more robustly? How do we deal with “semantic” tags (e.g., my-awesome-beta-feature) in the repo?3 Or tags that follow the J2SE versioning recommendation (e.g., 1.2.3_04, as in our example above)?

Well, we could try something like this:4

…which still isn’t perfect (i.e., it shoves “semantic” tags to the beginning of the list) but will handle both “dotted” and J2SE versions with aplomb and will fail much more gracefully and somewhat more predictably. Most importantly, the list you get out is the same as the list that you put in.

Also: the logic is a little more portable. Here’s the same comparator but implemented in Groovy:56

  1. For example, if you put in 1.2.3_04 then you would get back 1.2.304. []
  2. Although you could also argue that that was the reason to use Ruby instead of (fill in the blank) other language. []
  3. Which (as an aside) the original script would simply coerce into 0. []
  4. …given a list of “version tags” like this: []
  5. And/but: it’s probably worth mentioning that I implemented this “more robust” version of the comparator in Groovy first. Because that’s what I’m using pretty much all day long. Ruby is more like… “for fun”. []
  6. And no, I’m not ashamed of the version history on that Gist. []

About Rob Friesel

Software engineer by day, science fiction writer by night. Author of The PhantomJS Cookbook and a short story in Please Do Not Remove. View all posts by Rob Friesel →

One Response to a better version comparator

Leave a Reply

Your email address will not be published. Required fields are marked *