Add support for 4 part version numbers (#8925)

* first crack at fix

* after test complete

* pr feedback + tests

* fix whitespace

* PR fedback
This commit is contained in:
Arvind Ranasaria
2020-02-13 16:59:22 -08:00
committed by GitHub
parent 321b41b7e1
commit 0c56d44e4f
4 changed files with 161 additions and 3 deletions

View File

@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SemVer } from 'semver';
function fourPart2SemVer(version: string): string {
if (version.includes('-')) {
//return unchanged if version contains a pre-release suffix
return version;
} else {
let parts: string[] = version.split('.');
if (parts.length > 3) {
version = `${parts[0]}.${parts[1]}.${parts[2]}+${parts.slice(3).join('.')}`;
}
return version;
}
}
/**
* This Proxy for SemVer behaves the same way as the SamVer except the build number of the SemVer specification at: https://semver.org/ is prefixed by a '.' as well instead of a '+'. So while the BNF for valid SemVer is:
<valid semver> ::= <version core>
| <version core> "-" <pre-release>
| <version core> "+" <build>
| <version core> "-" <pre-release> "+" <build>
<version core> ::= <major> "." <minor> "." <patch>
SemVerProxy support the following BNF:
<valid semver> ::= <version core>
| <version core> "-" <pre-release>
| <version core> "." <build>
| <version core> "-" <pre-release> "+" <build>
<version core> ::= <major> "." <minor> "." <patch>
*/
export class SemVerProxy extends SemVer {
private _version: string;
constructor(version: string | SemVerProxy, loose?: boolean) {
let ver: string;
if (version instanceof SemVer) {
ver = version.version;
if (!ver) {
throw new Error('Invalid version');
}
} else {
ver = fourPart2SemVer(version);
}
super(ver, loose);
if (ver.includes('-')) {
this._version = ver;
} else {
this._version = ver.replace('+', '.'); // change back any '+' character used to delimit the build portion of the version with a '.'
}
}
get version(): string {
return this._version;
}
}

View File

@@ -11,6 +11,7 @@ import { AzdataInstallLocationKey, DeploymentConfigurationKey } from '../../cons
import { Command, OsDistribution, ToolType } from '../../interfaces';
import { IPlatformService } from '../platformService';
import { dependencyType, ToolBase } from './toolBase';
import { SemVerProxy } from './SemVerProxy';
const localize = nls.loadMessageBundle();
export const AzdataToolName = 'azdata';
@@ -58,7 +59,7 @@ export class AzdataTool extends ToolBase {
protected getVersionFromOutput(output: string): SemVer | undefined {
let version: SemVer | undefined = undefined;
if (output && output.split(EOL).length > 0) {
version = new SemVer(output.split(EOL)[0].replace(/ /g, ''));
version = new SemVerProxy(output.split(EOL)[0].replace(/ /g, ''));
}
return version;
}

View File

@@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import assert = require('assert');
import { SemVerProxy } from '../services/tools/SemVerProxy';
interface Expected {
[index: string]: string | number | undefined | Error
major?: number;
minor?: number;
patch?: number;
build?: string;
raw?: string;
prerelease?: string;
version?: string | Error
}
interface TestDefinition {
testName: string;
inputVersion: string;
expected: Expected;
}
class SymVerProxyTest extends SemVerProxy {
[index: string]: any;
constructor(version: string | SemVerProxy, loose?: boolean) {
super(version, loose);
}
}
const testDefinitions: TestDefinition[] = [
{
testName: 'SemVerProxyTest: canonical 3 part version - Pre-existing common SymVers work as before', inputVersion: '1.2.3', expected: {
major: 1,
minor: 2,
patch: 3,
raw: '1.2.3',
version: '1.2.3'
}
},
{
testName: 'SemVerProxyTest: canonical 4 part version', inputVersion: '1.2.3.4', expected: {
major: 1,
minor: 2,
patch: 3,
build: '4',
raw: '1.2.3+4',
version: '1.2.3.4'
}
},
{
testName: 'SemVerProxyTest: canonical 8 part version', inputVersion: '1.2.3.4.5.6.7.8', expected: {
major: 1,
minor: 2,
patch: 3,
build: '4,5,6,7,8',
raw: '1.2.3+4.5.6.7.8',
version: '1.2.3.4.5.6.7.8'
}
},
{
testName: 'SemVerProxyTest: canonical pre-rel version', inputVersion: '1.2.3-rc1.22.33.44+55.66.77', expected: {
major: 1,
minor: 2,
patch: 3,
build: '55,66,77',
prerelease: 'rc1,22,33,44',
raw: '1.2.3-rc1.22.33.44+55.66.77',
version: '1.2.3-rc1.22.33.44+55.66.77'
}
}
];
function validate(test: TestDefinition, semVerProxy: SymVerProxyTest) {
for (const key in test.expected) {
const expected = test.expected[key];
if (expected) {
assert.equal(semVerProxy[key].toString(), expected.toString(), `validation for property ${key} failed.`);
}
}
}
suite('SemVeryProxy Tests', function (): void {
testDefinitions.forEach((semVerTest: TestDefinition) => {
test(semVerTest.testName, () => {
const semVerProxy = new SymVerProxyTest(semVerTest.inputVersion);
validate(semVerTest, semVerProxy);
});
});
});

View File

@@ -102,7 +102,7 @@ export class ResourceTypePickerDialog extends DialogBase {
};
const versionColumn: azdata.TableColumn = {
value: localize('deploymentDialog.toolVersionColumnHeader', "Version"),
width: 60
width: 75
};
const minVersionColumn: azdata.TableColumn = {
value: localize('deploymentDialog.toolMinimumVersionColumnHeader', "Required Version"),
@@ -110,7 +110,7 @@ export class ResourceTypePickerDialog extends DialogBase {
};
const installedPathColumn: azdata.TableColumn = {
value: localize('deploymentDialog.toolDiscoveredPathColumnHeader', "Discovered Path or Additional Information"),
width: 570
width: 580
};
this._toolsTable = view.modelBuilder.table().withProperties<azdata.TableComponentProperties>({
data: [],