Skip to content

Commit

Permalink
fix(versioning/nuget): correctly compare semver v2 versions (#13056)
Browse files Browse the repository at this point in the history
  • Loading branch information
viceice committed Dec 11, 2021
1 parent 49f1d5a commit c7dbbd8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 19 deletions.
22 changes: 15 additions & 7 deletions lib/versioning/nuget/index.spec.ts
Expand Up @@ -56,13 +56,21 @@ describe('versioning/nuget/index', () => {
});

test.each`
a | b | expected
${'2.4.2'} | ${'2.4.1'} | ${true}
${'2.4-beta'} | ${'2.4-alpha'} | ${true}
${'1.9'} | ${'2'} | ${false}
${'1.9'} | ${'1.9.1'} | ${false}
${'2.4.0'} | ${'2.4.0-beta'} | ${true}
${'2.4.0-alpha'} | ${'2.4.0'} | ${false}
a | b | expected
${'2.4.2'} | ${'2.4.1'} | ${true}
${'2.4-beta'} | ${'2.4-alpha'} | ${true}
${'1.9'} | ${'2'} | ${false}
${'1.9'} | ${'1.9.1'} | ${false}
${'2.4.0'} | ${'2.4.0-beta'} | ${true}
${'2.4.0-alpha'} | ${'2.4.0'} | ${false}
${'1.2.0-beta.333'} | ${'1.2.0-beta.66'} | ${true}
${'1.2.0-beta2'} | ${'1.2.0-beta10'} | ${true}
${'1.2.0.1'} | ${'1.2.0'} | ${true}
${'1.2.0.1'} | ${'1.2.0.1-beta'} | ${true}
${'1.2.0.1-beta'} | ${'1.2.0.1'} | ${false}
${undefined} | ${'1.2.0'} | ${true}
${'1.2.0+1'} | ${'1.2.0'} | ${false}
${'1.2.0'} | ${'1.2.0+1'} | ${false}
`('isGreaterThan($a, $b) === $expected', ({ a, b, expected }) => {
expect(nuget.isGreaterThan(a, b)).toBe(expected);
});
Expand Down
40 changes: 28 additions & 12 deletions lib/versioning/nuget/index.ts
@@ -1,5 +1,7 @@
import semver from 'semver';
import { regEx } from '../../util/regex';
import * as generic from '../loose/generic';
import type { GenericVersion } from '../loose/generic';
import type { VersioningApi } from '../types';

export const id = 'nuget';
Expand All @@ -11,23 +13,34 @@ export const supportsRanges = false;

const pattern = regEx(/^(\d+(?:\.\d+)*)(-[^+]+)?(\+.*)?$/);

function parse(version: string): any {
function parse(version: string): GenericVersion {
const matches = pattern.exec(version);
if (!matches) {
return null;
}
const [, prefix, prereleasesuffix] = matches;
const [, prefix, prerelease] = matches;
const release = prefix.split('.').map(Number);
return { release, suffix: prereleasesuffix || '' };
return { release, prerelease: prerelease || '' };
}

function compare(version1: string, version2: string): number {
function compareSemVer(version1: string, version2: string): number | null {
const parsed1 = semver.parse(version1);
const parsed2 = semver.parse(version2);

if (!(parsed1 && parsed2)) {
return null;
}

return parsed1.compare(parsed2);
}

function compareLegacy(version1: string, version2: string): number {
const parsed1 = parse(version1);
const parsed2 = parse(version2);
// istanbul ignore if
if (!(parsed1 && parsed2)) {
return 1;
}

const length = Math.max(parsed1.release.length, parsed2.release.length);
for (let i = 0; i < length; i += 1) {
// 2.1 and 2.1.0 are equivalent
Expand All @@ -38,30 +51,33 @@ function compare(version1: string, version2: string): number {
}
}
// numeric version equals
const suffixComparison = parsed1.suffix.localeCompare(parsed2.suffix);
const suffixComparison = parsed1.prerelease.localeCompare(parsed2.prerelease);
if (suffixComparison !== 0) {
// Empty suffix should compare greater than non-empty suffix
if (parsed1.suffix === '') {
if (parsed1.prerelease === '') {
return 1;
}
if (parsed2.suffix === '') {
if (parsed2.prerelease === '') {
return -1;
}
}
return suffixComparison;
}

function isStable(version: string): boolean {
const parsed = parse(version);
return parsed && parsed.suffix === '';
function compare(version1: string, version2: string): number {
const res = compareSemVer(version1, version2);
if (res !== null) {
return res;
}

return compareLegacy(version1, version2);
}

export const api: VersioningApi = {
...generic.create({
parse,
compare,
}),
isStable,
};

export default api;

0 comments on commit c7dbbd8

Please sign in to comment.