Skip to content

Instantly share code, notes, and snippets.

@danielflower
Created September 6, 2012 13:59
Show Gist options
  • Save danielflower/3656539 to your computer and use it in GitHub Desktop.
Save danielflower/3656539 to your computer and use it in GitHub Desktop.
Javascript comparison function for Maven version strings, where a snapshot is older than a release version. Useful for sorting arrays of Maven versions. Disclaimer: only claims to support the patterns as described by the unit tests.
/**
* Compares two Maven version strings and returns value suitable for use in Array.sort.
* @param {String} v1
* @param {String} v2
* @return {Number} Negative number if v1 is older than v2; positive number if v1 is newer than v2; 0 if equal.
*/
exports.mavenVersionSortComparer = function (v1, v2) {
// Strategy: pad each part of the version with zeros so strings are same length, then do string compare.
// Snapshot version have an extra 0 put on the end, whereas release versions have a 1 on the end
// e.g. 1.5-SNAPSHOT vs. 1.10.0 => 1.05.0.a vs. 1.10.0.c
// e.g. 1.5 => [1,5]
var v1Bits = v1.split(".");
var v2Bits = v2.split(".");
var v1OriginalLength = v1Bits.length;
var v2OriginalLength = v2Bits.length;
// equalise the number of parts, e.g. [1, 5] => [1,5,0]
while (v1Bits.length < v2Bits.length) {
v1Bits.push("0");
}
while (v2Bits.length < v1Bits.length) {
v2Bits.push("0");
}
// Change snapshot versions to have an extra ".0" and release versions to have an extra ".1"
function alterBasedOnSnapshotOrReleaseVersion(bits, potentialTextPosition) {
if (bits[potentialTextPosition].indexOf("-SNAPSHOT") > 0) {
bits[potentialTextPosition] = bits[potentialTextPosition].replace("-SNAPSHOT", "");
bits.push("0");
} else if (bits[potentialTextPosition].indexOf("-") > 0) {
bits[potentialTextPosition] = bits[potentialTextPosition].replace(/\-.*/, "");
bits.push("1");
} else {
bits.push("2");
}
}
alterBasedOnSnapshotOrReleaseVersion(v1Bits, v1OriginalLength - 1);
alterBasedOnSnapshotOrReleaseVersion(v2Bits, v2OriginalLength - 1);
// pad with zeros, e.g. [1,5,0] => [1,05,0]
for (var i = 0; i < v1Bits.length; i++) {
var targetLength = Math.max(v1Bits[i].length, v2Bits[i].length);
while (v1Bits[i].length < targetLength) {
v1Bits[i] = "0" + v1Bits[i];
}
while (v2Bits[i].length < targetLength) {
v2Bits[i] = "0" + v2Bits[i];
}
}
// back to normal, e.g. [1,05,0] => 1.05.0
var transformed1 = v1Bits.join(".");
var transformed2 = v2Bits.join(".");
console.log("v1: " + v1 + "=>" + transformed1 + ", v2: " + v2 + "=>" + transformed2);
return transformed1.localeCompare(transformed2);
};
// Some nodeunit tests
function assertOldIsOlderThanNewer(test, oldOne, newOne) {
test.ok(convert.mavenVersionSortComparer(oldOne, newOne) < 0, "older (" + oldOne + ") compared to newer (" + newOne + ")");
test.ok(convert.mavenVersionSortComparer(newOne, oldOne) > 0, "newer (" + newOne + ") compared to older (" + oldOne + ")");
}
function assertVersionsAreSame(test, v1, v2) {
test.strictEqual(convert.mavenVersionSortComparer(v1, v2), 0, "v1 (" + v1 + ") compared to v2 (" + v2 + ")");
test.strictEqual(convert.mavenVersionSortComparer(v2, v1), 0, "v2 (" + v2 + ") compared to v1 (" + v1 + ")");
}
exports.majorVersionIsNewerThanMinorVersion = function (test) {
assertOldIsOlderThanNewer(test, "1.6.9", "2.0.0");
assertOldIsOlderThanNewer(test, "1.996.999", "2.0.0");
assertOldIsOlderThanNewer(test, "1", "2.0.0");
assertOldIsOlderThanNewer(test, "1.0", "2.0.0");
assertOldIsOlderThanNewer(test, "1.0", "2.0.0");
test.done();
};
exports.versionsAreComparedNumerically = function (test) {
assertOldIsOlderThanNewer(test, "1.6.0", "1.10.0");
assertOldIsOlderThanNewer(test, "1.6.999999999", "1.100.0");
test.done();
};
exports.snapshotsAreOlderThanReleaseVersionsIfVersionsAreSame = function (test) {
assertOldIsOlderThanNewer(test, "1.0.0-SNAPSHOT", "1.0.0");
assertOldIsOlderThanNewer(test, "1.0-SNAPSHOT", "1.0.0");
assertOldIsOlderThanNewer(test, "1-SNAPSHOT", "1.0.0");
test.done();
};
exports.snapshotsAreIgnoredIfVersionsAreDifferent = function (test) {
assertOldIsOlderThanNewer(test, "1.6.9-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.996.999-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.0-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.0-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.6.9", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1.996.999", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1.0", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1.0", "2.0.0-SNAPSHOT");
test.done();
};
exports.snapshotsAreIgnoredIfVersionsAreDifferent = function (test) {
assertOldIsOlderThanNewer(test, "1.6.9-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.996.999-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.0-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.0-SNAPSHOT", "2.0.0");
assertOldIsOlderThanNewer(test, "1.6.9", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1.996.999", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1.0", "2.0.0-SNAPSHOT");
assertOldIsOlderThanNewer(test, "1.0", "2.0.0-SNAPSHOT");
test.done();
};
exports.nonStandardTextIsNewerThanSnapshotButOlderThanReleaseVersion = function (test) {
assertOldIsOlderThanNewer(test, "1.6.9-SNAPSHOT", "1.6.9-hotfix");
assertOldIsOlderThanNewer(test, "1.6.9-hotfix", "1.6.9");
test.done();
};
exports.versionsAreSameEvenWithDifferentNumberOfParts = function (test) {
assertVersionsAreSame(test, "1.20.300", "1.20.300");
assertVersionsAreSame(test, "1.20", "1.20.0");
assertVersionsAreSame(test, "1", "1.0.0");
test.done();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment