Last week I mentioned how I had uploaded a new version of Symbol::Approx::Sub. Because there were pretty major changes to the inner workings of the module (although the interface still looked the same) I decided that I would move it from version 2.07 to version 3. At the same time, I decided that I would switch to a semantic versioning scheme.
Later in the week, I released minor updates to a few more of my modules. And I decided to apply semantic versioning to those as well. But as I was only making minor packaging fixes to these modules, I didn’t increment the major version number. For example, Array::Compare went from 12.2 to 12.2.1.
It turns out that was a mistake.
Well, I don’t really think it was a mistake. I think it was the right thing to do. But it appears that my opinion is at odds with what some parts of the Perl toolchain think.
Last night I got this bug report. It seems that by switching to three-part semantic versions, the version number can (in some quite common circumstances) appear to decrease.
To my mind, a version number is a dot-separated sequence of numbers. So 12.2 is smaller than 12.2.1. Any sane version number comparison will separate the two strings on dots and compare the individual components. Any missing components (12.2 is, for example, one component shorter than 12.2.1) should be assumed to be zero.
But that’s not what the Perl toolchain does. Observe:
$ perl -Mversion -E"say version->parse('2.12')->normal"
$ perl -Mversion -E"say version->parse('2.12.1')->normal"
$ perl -Mversion -E"say version->parse('2.12') <=> version->parse('2.12.1')"
When the version number with two components (2.12) is split into components, the second component is bizarrely treated as a three-digit number so it becomes 120 instead of 12 and when it is compared with the second component of the three-component version, 120 is obviously larger than 12 and any tool which relies on this behaviour to work out which version of a module is the most recent will get the wrong answer.
This leads to other “interesting” effects. In my head, versions 1.1, 1.01 and 1.001 are all the same version. The leading zeroes mean nothing. But under this scheme, they are very different version numbers.
I know that versioning isn’t as easy as it should be and I know that some people use bizarre versioning systems. And I’m pretty sure that no matter how bizarre a versioning system is, you’ll almost certainly find an example of it on CPAN. So I suppose that this behaviour was a “least worse” scenario that was chosen to make the most sense given CPAN’s wide range of versioning schemes.
Personally, I see it as a bug in version.pm. But I’m not going to report it as such as I’m sure the Perl toolchain gang know what they’re doing and have very good reasons for adopting this seemingly broken behaviour.
I just need to remember to be more careful when switching my modules to semantic versioning. Using a minor or patch level version change when switching to semantic versioning is likely to lead to confusion and bug reports. Only a major level change (as I did with Symbol::Approx::Sub) is guaranteed to work.
And, I suppose, I’ll need to release Array::Compare 3.0.0 to CPAN pretty soon.
Also published on Medium.