[Development] Adding support for version number comparisons

Kobus Jaroslaw Jaroslaw.Kobus at digia.com
Thu Jul 10 15:47:45 CEST 2014

Hi All,

With the current state of QVersion (patchset 35) I see the following issues:
1. operator<() doesn't take the suffix into account (mentioned below)
2. There is no handling of sub version (you cannot differentiate 5.0.0, 5.0 and 5 - they are all equal)

The idea which could resolve these issues would be not to keep the suffix inside a QVersion class. I understand that there is a need for version numbers consisting of some labels for preliminary versions. That's why the idea is to provide a mechanism for preliminary versioning system in first place, and then resolve the labels problem with a simple number/string substitution.

The mentioned mechamism for preliminary versions would operate also on numbers, but one segment of the QVersion would be distinct. This distinct segment (call it preliminary segment) would be the indication for the comparator to treat that segment (and followed segments) in a special way (i.e. if we compare the preliminary segment with normal one, we say that preliminary is always less than normal one, even if its numerical value is greater). For now, in QString version for a QVersion, I will use "*" for this distinction.


All below are preliminary versions:

"5.4.0.*0" - the very first alpha version for the upcomming "5.4.0" release.
"5.4.0.*1.1" - beta 1 release
"5.4.0.*1.2" - beta 2 release
"5.4.0.*2.1" - rc 1 release
"5.4.0.*2.2" - rc 2 release

And finally there is:

"5.4.0" - we plan to release that, no preliminary marker

Later, we prepare for "5.4.1", we release in meantime:

"5.4.1.*0", and so on...

So, I propose to keep inside QVersion only segments and index of the preliminary segment, and drop suffix.

Later, we could provide a method for reading from and writing to string a QVersion instance, like:

QString QVersion::toString(const QStringList &labels) const; - this method would substitute a number for a preliminary segment with a string taken from labels. So, if e.g. my project's convention for naming of preliminary versions is like:

QStringList labels << "alhpa" << "beta" << "rc";

than QVersion would produce:

"5.4.0.alpha" for QVersion("5.4.0.*0").toString(labels);
"5.4.0.beta.1" for QVersion("5.4.0.*1.1").toString(labels);
"5.4.0.beta.2" for QVersion("5.4.0.*1.2").toString(labels);
"5.4.0.rc.1" for QVersion("5.4.0.*2.1").toString(labels);
"5.4.0.rc.2" for QVersion("5.4.0.*2.2").toString(labels);

For reading (e.g. QVersion::fromString(const QString &versionString, const QStringList &labels);) it would be symmetric. The advantage would be that we may discover invalid versions passed to that method (e.g. if our project doesn't know anything about "theta", and it's not on the list, we can detect it and return invalid version, instead of creating useless version object).

If you would like to see how it behaves, there is some implementation for it (the extension of a tool class for installer framework) here: https://codereview.qt-project.org/#/c/89604/
It doesn't implement toString() and fromString() which would take a QStringList yet, but it's trivial to implement it quickly. The rest of the mentioned approach is implemented. The class is inside a framework, but is doesn't dependent on it, so you may try to compile it and run outside.



From: development-bounces+jaroslaw.kobus=digia.com at qt-project.org [development-bounces+jaroslaw.kobus=digia.com at qt-project.org] on behalf of Keith Gardner [kreios4004 at gmail.com]
Sent: 10 July 2014 14:21
To: Thiago Macieira
Cc: <development at qt-project.org>
Subject: Re: [Development] Adding support for version number comparisons

On Sat, May 31, 2014 at 2:00 PM, Thiago Macieira <thiago.macieira at intel.com<mailto:thiago.macieira at intel.com>> wrote:
Em sex 09 maio 2014, às 11:36:08, Keith Gardner escreveu:
> I have been working on adding a class to QtCore (QVersion) to support
> storing version numbers, convert to/from QString, and having comparison
> operators.  My goal was to provide an API to assist in the following use
> cases:
>    - Plugin loading where there are multiple versions on the same system.
>    - File format validation.
>    - Executing an already installed command line application where the
>    behavior is dependent on the called application's version.
>    - Performing software installations and updates.
>    - QMake support for version number comparisons.
> Please share other potential use cases where this might be useful.

Ok, since we can't seem to agree, let's settle on the maximum common
denominator: QVersion will only compare the numeric part of a version number.
By default, two versions with the same numeric part will compare equally,
regardless of any suffixes that may be present.

Therefore, by default, given:
        QVersion a("5.3.0");
        QVersion b("5.3.0pl1");
        QVersion c("5.3.0beta1");

        a != b != c;            // since they aren't equal

        QVersion::compare(a, b) == 0;
        QVersion::compare(b, c) == 0;

In the review of the change, a potential issue with this form of compare with the operators when using QVersion as the key in a QMap.  Here is the scenario:
    QVersion a("5.3.0alpha");
    QVersion b("5.3.0beta");
    a != b; //true
    a < b; // false

    QMap<QVersion, QFoo> map;
    map[a] = foo1;
    map[b] = foo2;

With the example, map[a] now is set to "foo2" which is incorrect since 'a' != 'b'.  This is not an issue with QHash<QVersion, QFoo> since the suffix is included into the hashing of a QVersion.  How should we resolve this conflict with ordering without applying a semantic compare to the suffix?

More information about the Development mailing list