Skip to content

Commit 3d466d8

Browse files
committed
Fix: a semver without prerelease tags must be greater than one with tags. Add first unit tests (TBC).
1 parent f7134a4 commit 3d466d8

File tree

3 files changed

+158
-57
lines changed

3 files changed

+158
-57
lines changed

Tasks/EncodeSemverToInteger/EncodeSemverToInteger.ts

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,23 @@
1-
import path = require('path');
2-
import fs = require('fs-extra');
3-
import tl = require('vsts-task-lib/task');
4-
import semver = require('semver');
1+
import { Encoder } from "./encoder";
2+
import tl = require("vsts-task-lib/task");
3+
import semver = require("semver");
54

65
try {
7-
var sourceSemVer = tl.getInput("SourceSemver");
8-
var minorBits = parseInt(tl.getInput("MinorBits"));
9-
var patchBits = parseInt(tl.getInput("PatchBits"));
10-
var preReleaseTagBits = parseInt(tl.getInput("PreReleaseTagBits"));
11-
var preReleaseTagMap = JSON.parse(tl.getInput("PreReleaseTagMap"));
12-
var preReleaseNumberBits = parseInt(tl.getInput("PreReleaseNumberBits"));
13-
var outputVariable = tl.getInput("OutputVariable");
6+
let sourceSemVer = tl.getInput("SourceSemver");
7+
let minorBits = parseInt(tl.getInput("MinorBits"));
8+
let patchBits = parseInt(tl.getInput("PatchBits"));
9+
let preReleaseTagBits = parseInt(tl.getInput("PreReleaseTagBits"));
10+
let preReleaseTagMap = JSON.parse(tl.getInput("PreReleaseTagMap"));
11+
let preReleaseNumberBits = parseInt(tl.getInput("PreReleaseNumberBits"));
12+
let outputVariable = tl.getInput("OutputVariable");
1413

15-
var varRegex = /\$\((.*?)\)/g;
16-
sourceSemVer = sourceSemVer.replace(varRegex, (match, varName, offset, string) => tl.getVariable(varName));
14+
let varRegex = /\$\((.*?)\)/g;
15+
sourceSemVer = sourceSemVer.replace(varRegex, (match, varName, offset, s) => tl.getVariable(varName));
1716

1817
console.log("SourceSemVer : " + sourceSemVer);
1918

20-
var checkBounds = (value: number, bits: number, name: string) => {
21-
if (value >= (Math.pow(2, bits))) {
22-
throw new Error(name + " will overflow allocated bits. " + value.toString() + " >= " + (Math.pow(2, bits)).toString());
23-
}
24-
};
25-
26-
var majorBits = 32 - minorBits - patchBits - preReleaseNumberBits - preReleaseTagBits;
27-
28-
var parsedSemver = new semver.SemVer(sourceSemVer, false);
29-
30-
var code: number = 0;
31-
32-
checkBounds(parsedSemver.major, majorBits, "major");
33-
code += parsedSemver.major;
34-
35-
checkBounds(parsedSemver.minor, minorBits, "minor");
36-
code = code << minorBits;
37-
code += parsedSemver.minor;
38-
39-
checkBounds(parsedSemver.patch, patchBits, "patch");
40-
code = code << patchBits;
41-
code += parsedSemver.patch;
42-
43-
var preReleaseTagCode: number = (2 ^ preReleaseTagBits) - 1;
44-
var preReleaseNumber: number = 0;
45-
if (parsedSemver.prerelease && parsedSemver.prerelease.length) {
46-
var mapResult = preReleaseTagMap[parsedSemver.prerelease[0]];
47-
if (mapResult) {
48-
preReleaseTagCode = mapResult;
49-
} else {
50-
preReleaseTagCode = 0;
51-
}
52-
if (parsedSemver.prerelease.length > 1){
53-
preReleaseNumber = parseInt(parsedSemver.prerelease[1]);
54-
}
55-
}
56-
57-
checkBounds(preReleaseTagCode, preReleaseTagBits, "preReleaseTagBits");
58-
code = code << preReleaseTagBits;
59-
code += preReleaseTagCode;
60-
61-
checkBounds(preReleaseNumber, preReleaseNumberBits, "preReleaseNumberBits");
62-
code = code << preReleaseNumberBits;
63-
code += preReleaseNumber;
19+
let encoder = new Encoder(sourceSemVer);
20+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
6421

6522
console.log("computed versioncode : " + code.toString());
6623
tl.setVariable(outputVariable, code.toString());
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import semver = require("semver");
2+
3+
export class Encoder {
4+
constructor(private sourceSemVer: string) {
5+
}
6+
7+
private checkBounds(value: number, bits: number, name: string) {
8+
if (value >= (Math.pow(2, bits))) {
9+
throw new Error(name + " will overflow allocated bits. " + value.toString() + " >= " + (Math.pow(2, bits)).toString());
10+
}
11+
}
12+
13+
encode(minorBits: number, patchBits: number, preReleaseTagBits: number, preReleaseTagMap: any, preReleaseNumberBits: number): number {
14+
let majorBits = 32 - minorBits - patchBits - preReleaseNumberBits - preReleaseTagBits;
15+
16+
let parsedSemver = new semver.SemVer(this.sourceSemVer, false);
17+
18+
let code: number = 0;
19+
20+
this.checkBounds(parsedSemver.major, majorBits, "major");
21+
code += parsedSemver.major;
22+
23+
this.checkBounds(parsedSemver.minor, minorBits, "minor");
24+
code = code << minorBits;
25+
code += parsedSemver.minor;
26+
27+
this.checkBounds(parsedSemver.patch, patchBits, "patch");
28+
code = code << patchBits;
29+
code += parsedSemver.patch;
30+
31+
let preReleaseTagCode: number = Math.pow(2, preReleaseTagBits) - 1;
32+
let preReleaseNumber: number = Math.pow(2, preReleaseNumberBits) - 1;
33+
if (parsedSemver.prerelease && parsedSemver.prerelease.length) {
34+
let mapResult = preReleaseTagMap[parsedSemver.prerelease[0]];
35+
if (mapResult) {
36+
preReleaseTagCode = mapResult;
37+
} else {
38+
preReleaseTagCode = 0;
39+
}
40+
if (parsedSemver.prerelease.length > 1) {
41+
preReleaseNumber = parseInt(parsedSemver.prerelease[1]);
42+
}
43+
}
44+
45+
this.checkBounds(preReleaseTagCode, preReleaseTagBits, "preReleaseTagBits");
46+
code = code << preReleaseTagBits;
47+
code += preReleaseTagCode;
48+
49+
this.checkBounds(preReleaseNumber, preReleaseNumberBits, "preReleaseNumberBits");
50+
code = code << preReleaseNumberBits;
51+
code += preReleaseNumber;
52+
53+
return code;
54+
}
55+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"use strict";
2+
3+
import { Encoder } from "../../Tasks/EncodeSemverToInteger/encoder";
4+
5+
let minorBits = 5;
6+
let patchBits = 4;
7+
let preReleaseTagBits = 2;
8+
let preReleaseTagMap = { "rc": 2, "beta": 1, "alpha": 0, "unstable": 0 };
9+
let preReleaseNumberBits = 9;
10+
11+
describe("Simple encoding", () => {
12+
it(": '0.0.0-alpha.0' should be encoded to '0'.", () => {
13+
let encoder = new Encoder("0.0.0-alpha.0");
14+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
15+
expect(code).toEqual(0);
16+
});
17+
18+
it(": '0.0.0-alpha.1' should be encoded to '1'.", () => {
19+
let encoder = new Encoder("0.0.0-alpha.1");
20+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
21+
expect(code).toEqual(1);
22+
});
23+
24+
it(": '0.0.0-alpha.511' should be encoded to '511'.", () => {
25+
let encoder = new Encoder("0.0.0-alpha.511");
26+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
27+
expect(code).toEqual(511);
28+
});
29+
30+
it(": '0.0.0-beta.0' should be encoded to '512'.", () => {
31+
let encoder = new Encoder("0.0.0-beta.0");
32+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
33+
expect(code).toEqual(512);
34+
});
35+
36+
it(": '0.0.0-beta.511' should be encoded to '1023'.", () => {
37+
let encoder = new Encoder("0.0.0-beta.511");
38+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
39+
expect(code).toEqual(1023);
40+
});
41+
42+
it(": '0.0.0-rc.0' should be encoded to '1024'.", () => {
43+
let encoder = new Encoder("0.0.0-rc.0");
44+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
45+
expect(code).toEqual(1024);
46+
});
47+
48+
it(": '0.0.0' should be encoded to '2047'.", () => {
49+
let encoder = new Encoder("0.0.0");
50+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
51+
expect(code).toEqual(2047);
52+
});
53+
54+
it(": '0.0.1' should be encoded to '4095'.", () => {
55+
let encoder = new Encoder("0.0.1");
56+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
57+
expect(code).toEqual(4095);
58+
});
59+
60+
it(": '0.0.15' should be encoded to '32,767'.", () => {
61+
let encoder = new Encoder("0.0.15");
62+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
63+
expect(code).toEqual(32767);
64+
});
65+
66+
it(": '0.1.15' should be encoded to '65,535'.", () => {
67+
let encoder = new Encoder("0.1.15");
68+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
69+
expect(code).toEqual(65535);
70+
});
71+
72+
it(": '0.31.15' should be encoded to '1,048,575'.", () => {
73+
let encoder = new Encoder("0.31.15");
74+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
75+
expect(code).toEqual(1048575);
76+
});
77+
78+
it(": '1.31.15' should be encoded to '2,097,151'.", () => {
79+
let encoder = new Encoder("1.31.15");
80+
let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
81+
expect(code).toEqual(2097151);
82+
});
83+
84+
// it(": '4095.31.15' should be encoded to '2,147,483,648'.", () => {
85+
// let encoder = new Encoder("4095.31.15");
86+
// let code = encoder.encode(minorBits, patchBits, preReleaseTagBits, preReleaseTagMap, preReleaseNumberBits);
87+
// expect(code).toEqual(2147483648);
88+
// });
89+
});

0 commit comments

Comments
 (0)