From de5c4b8702ae64a957c294bb35638099bdb785a6 Mon Sep 17 00:00:00 2001 From: RahulGautamSingh <rahul_ug@cse.nits.ac.in> Date: Tue, 21 Dec 2021 22:28:50 +0530 Subject: [PATCH] refactor(semver): ensure strict null check (#13161) Co-authored-by: Michael Kriese <michael.kriese@visualon.de> --- lib/versioning/semver-coerced/index.spec.ts | 8 +++- lib/versioning/semver-coerced/index.ts | 47 ++++++++++++++------- lib/versioning/semver/index.ts | 3 +- tsconfig.strict.json | 2 + 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/lib/versioning/semver-coerced/index.spec.ts b/lib/versioning/semver-coerced/index.spec.ts index 25fdee12ad..2741806679 100644 --- a/lib/versioning/semver-coerced/index.spec.ts +++ b/lib/versioning/semver-coerced/index.spec.ts @@ -68,15 +68,19 @@ describe('versioning/semver-coerced/index', () => { it('should return false for lower version in strict semver', () => { expect(semverCoerced.isGreaterThan('3.1.2', '4.1.0')).toBeFalsy(); }); + + it('should return false if version cannot be coerced', () => { + expect(semverCoerced.isGreaterThan('e.e.e', '4.1.0')).toBeFalsy(); + }); }); describe('.isLessThanRange(version, range)', () => { it('should return true for a lower version in strict semver', () => { - expect(semverCoerced.isLessThanRange('1.0.2', '~2.0')).toBeTruthy(); + expect(semverCoerced.isLessThanRange?.('1.0.2', '~2.0')).toBeTruthy(); }); it('should return false for in-range version in strict semver', () => { - expect(semverCoerced.isLessThanRange('3.0.2', '~3.0')).toBeFalsy(); + expect(semverCoerced.isLessThanRange?.('3.0.2', '~3.0')).toBeFalsy(); }); }); diff --git a/lib/versioning/semver-coerced/index.ts b/lib/versioning/semver-coerced/index.ts index 9806270592..941f276e7a 100644 --- a/lib/versioning/semver-coerced/index.ts +++ b/lib/versioning/semver-coerced/index.ts @@ -1,3 +1,4 @@ +import is from '@sindresorhus/is'; import semver, { SemVer } from 'semver'; import stable from 'semver-stable'; import { regEx } from '../../util/regex'; @@ -11,15 +12,20 @@ export const supportsRanges = false; const { is: isStable } = stable; function sortVersions(a: string, b: string): number { - return semver.compare(semver.coerce(a), semver.coerce(b)); + const aCoerced = semver.coerce(a); + const bCoerced = semver.coerce(b); + + return aCoerced && bCoerced ? semver.compare(aCoerced, bCoerced) : 0; } function getMajor(a: string | SemVer): number | null { - return semver.major(semver.coerce(a)); + const aCoerced = semver.coerce(a); + return aCoerced ? semver.major(aCoerced) : null; } function getMinor(a: string | SemVer): number | null { - return semver.minor(semver.coerce(a)); + const aCoerced = semver.coerce(a); + return aCoerced ? semver.minor(aCoerced) : null; } function getPatch(a: string | SemVer): number | null { @@ -27,11 +33,14 @@ function getPatch(a: string | SemVer): number | null { } function matches(version: string, range: string): boolean { - return semver.satisfies(semver.coerce(version), range); + const coercedVersion = semver.coerce(version); + return coercedVersion ? semver.satisfies(coercedVersion, range) : false; } function equals(a: string, b: string): boolean { - return semver.eq(semver.coerce(a), semver.coerce(b)); + const aCoerced = semver.coerce(a); + const bCoerced = semver.coerce(b); + return aCoerced && bCoerced ? semver.eq(aCoerced, bCoerced) : false; } function isValid(version: string): string | boolean | null { @@ -42,10 +51,10 @@ function getSatisfyingVersion( versions: string[], range: string ): string | null { - const coercedVersions = versions.map((version) => { - const coercedVersion = semver.coerce(version); - return coercedVersion ? coercedVersion.version : null; - }); + const coercedVersions = versions + .map((version) => semver.coerce(version)?.version) + .filter(is.string); + return semver.maxSatisfying(coercedVersions, range); } @@ -53,19 +62,24 @@ function minSatisfyingVersion( versions: string[], range: string ): string | null { - const coercedVersions = versions.map((version) => { - const coercedVersion = semver.coerce(version); - return coercedVersion ? coercedVersion.version : null; - }); + const coercedVersions = versions + .map((version) => semver.coerce(version)?.version) + .filter(is.string); + return semver.minSatisfying(coercedVersions, range); } function isLessThanRange(version: string, range: string): boolean { - return semver.ltr(semver.coerce(version), range); + const coercedVersion = semver.coerce(version); + return coercedVersion ? semver.ltr(coercedVersion, range) : false; } function isGreaterThan(version: string, other: string): boolean { - return semver.gt(semver.coerce(version), semver.coerce(other)); + const coercedVersion = semver.coerce(version); + const coercedOther = semver.coerce(other); + return coercedVersion && coercedOther + ? semver.gt(coercedVersion, coercedOther) + : false; } const startsWithNumberRegex = regEx(`^\\d`); @@ -81,7 +95,8 @@ function isSingleVersion(version: string): string | boolean | null { } // If this is left as an alias, inputs like "17.04.0" throw errors -export const isVersion = (input: string): string | boolean => isValid(input); +export const isVersion = (input: string): string | boolean | null => + isValid(input); export { isVersion as isValid, getSatisfyingVersion }; diff --git a/lib/versioning/semver/index.ts b/lib/versioning/semver/index.ts index 76ee0b6b53..dc9f8485b3 100644 --- a/lib/versioning/semver/index.ts +++ b/lib/versioning/semver/index.ts @@ -24,7 +24,8 @@ const { } = semver; // If this is left as an alias, inputs like "17.04.0" throw errors -export const isVersion = (input: string): string => valid(input); +export const isVersion = (input: string): string | boolean | null => + valid(input); export { isVersion as isValid, getSatisfyingVersion }; diff --git a/tsconfig.strict.json b/tsconfig.strict.json index 9076ab5e2e..8fd3ec0ec6 100644 --- a/tsconfig.strict.json +++ b/tsconfig.strict.json @@ -46,6 +46,8 @@ "lib/util/url.ts", "lib/versioning/swift/*.ts", "lib/versioning/ubuntu/*.ts", + "lib/versioning/semver/*.ts", + "lib/versioning/semver-coerced/*.ts", "lib/workers/pr/changelog/hbs-template.ts", "lib/workers/pr/changelog/types.ts", "lib/workers/repository/init/types.ts", -- GitLab