diff --git a/lib/versioning/ruby/index.ts b/lib/versioning/ruby/index.ts index 8389ef7efac2b6d928cb277321c7310e2b4887e4..49fc24fee781064552d39f2930bdd34a75f2c8ec 100644 --- a/lib/versioning/ruby/index.ts +++ b/lib/versioning/ruby/index.ts @@ -13,32 +13,44 @@ import { parse as parseRange, ltr } from './range'; import { isSingleOperator, isValidOperator } from './operator'; import { pin, bump, replace } from './strategies'; -const equals = (left: string, right: string): boolean => eq(left, right); +function vtrim<T = unknown>(version: T): string | T { + if (typeof version === 'string') return version.replace(/^v/, ''); + return version; +} -const getMajor = (version: string): number => parseVersion(version).major; -const getMinor = (version: string): number => parseVersion(version).minor; -const getPatch = (version: string): number => parseVersion(version).patch; +const equals = (left: string, right: string): boolean => + eq(vtrim(left), vtrim(right)); -export const isVersion = (version: string): boolean => !!valid(version); -const isGreaterThan = (left: string, right: string): boolean => gt(left, right); +const getMajor = (version: string): number => + parseVersion(vtrim(version)).major; +const getMinor = (version: string): number => + parseVersion(vtrim(version)).minor; +const getPatch = (version: string): number => + parseVersion(vtrim(version)).patch; + +export const isVersion = (version: string): boolean => !!valid(vtrim(version)); +const isGreaterThan = (left: string, right: string): boolean => + gt(vtrim(left), vtrim(right)); const isLessThanRange = (version: string, range: string): boolean => - ltr(version, range); + ltr(vtrim(version), vtrim(range)); const isSingleVersion = (range: string): boolean => { - const { version, operator } = parseRange(range); + const { version, operator } = parseRange(vtrim(range)); return operator ? isVersion(version) && isSingleOperator(operator) : isVersion(version); }; -const isStable = (version: string): boolean => - parseVersion(version).prerelease ? false : isVersion(version); +function isStable(version: string): boolean { + const v = vtrim(version); + return parseVersion(v).prerelease ? false : isVersion(v); +} export const isValid = (input: string): boolean => input .split(',') - .map(piece => piece.trim()) + .map(piece => vtrim(piece.trim())) .every(range => { const { version, operator } = parseRange(range); @@ -48,11 +60,11 @@ export const isValid = (input: string): boolean => }); export const matches = (version: string, range: string): boolean => - satisfies(version, range); + satisfies(vtrim(version), vtrim(range)); const maxSatisfyingVersion = (versions: string[], range: string): string => - maxSatisfying(versions, range); + maxSatisfying(versions.map(vtrim), vtrim(range)); const minSatisfyingVersion = (versions: string[], range: string): string => - minSatisfying(versions, range); + minSatisfying(versions.map(vtrim), vtrim(range)); const getNewValue = ( currentValue: string, @@ -60,22 +72,31 @@ const getNewValue = ( _fromVersion: string, toVersion: string ): string => { + let result = null; switch (rangeStrategy) { case 'pin': - return pin({ to: toVersion }); + result = pin({ to: vtrim(toVersion) }); + break; case 'bump': - return bump({ range: currentValue, to: toVersion }); + result = bump({ range: vtrim(currentValue), to: vtrim(toVersion) }); + break; case 'replace': - return replace({ range: currentValue, to: toVersion }); + result = replace({ range: vtrim(currentValue), to: vtrim(toVersion) }); + break; // istanbul ignore next default: logger.warn(`Unsupported strategy ${rangeStrategy}`); - return null; } + + if (currentValue !== vtrim(currentValue) && isSingleVersion(result)) { + result = `v${result}`; + } + + return result; }; export const sortVersions = (left: string, right: string): number => - gt(left, right) ? 1 : -1; + gt(vtrim(left), vtrim(right)) ? 1 : -1; export const api: VersioningApi = { equals, diff --git a/test/versioning/ruby.spec.ts b/test/versioning/ruby.spec.ts index e6ac7f6fb016199cccae232443a00f3c7e2110e1..fcadfa217c07ac6a030c50f39859e3ef77b753b6 100644 --- a/test/versioning/ruby.spec.ts +++ b/test/versioning/ruby.spec.ts @@ -52,18 +52,25 @@ describe('semverRuby', () => { describe('.isVersion', () => { it('returns true when version is valid', () => { + expect(semverRuby.isVersion('0')).toBe(true); + expect(semverRuby.isVersion('v0')).toBe(true); + expect(semverRuby.isVersion('v1')).toBe(true); + expect(semverRuby.isVersion('v1.2')).toBe(true); + expect(semverRuby.isVersion('v1.2.3')).toBe(true); expect(semverRuby.isVersion('1')).toBe(true); expect(semverRuby.isVersion('1.1')).toBe(true); expect(semverRuby.isVersion('1.1.2')).toBe(true); expect(semverRuby.isVersion('1.1.2.3')).toBe(true); expect(semverRuby.isVersion('1.1.2-4')).toBe(true); expect(semverRuby.isVersion('1.1.2.pre.4')).toBe(true); + expect(semverRuby.isVersion('v1.1.2.pre.4')).toBe(true); }); it('returns false when version is invalid', () => { expect(semverRuby.isVersion(undefined)).toBe(false); expect(semverRuby.isVersion('')).toBe(false); expect(semverRuby.isVersion(null)).toBe(false); + expect(semverRuby.isVersion('v')).toBe(false); expect(semverRuby.isVersion('tottally-not-a-version')).toBe(false); }); }); @@ -349,6 +356,7 @@ describe('semverRuby', () => { it('returns correct version for pin strategy', () => { [ ['1.2.3', '1.0.3', 'pin', '1.0.3', '1.2.3'], + ['v1.2.3', 'v1.0.3', 'pin', '1.0.3', '1.2.3'], ['1.2.3', '= 1.0.3', 'pin', '1.0.3', '1.2.3'], ['1.2.3', '!= 1.0.3', 'pin', '1.0.4', '1.2.3'], ['1.2.3', '> 1.0.3', 'pin', '1.0.4', '1.2.3'], @@ -367,6 +375,7 @@ describe('semverRuby', () => { it('returns correct version for bump strategy', () => { [ ['1.2.3', '1.0.3', 'bump', '1.0.3', '1.2.3'], + ['v1.2.3', 'v1.0.3', 'bump', '1.0.3', '1.2.3'], ['= 1.2.3', '= 1.0.3', 'bump', '1.0.3', '1.2.3'], ['!= 1.0.3', '!= 1.0.3', 'bump', '1.0.0', '1.2.3'], ['> 1.2.2', '> 1.0.3', 'bump', '1.0.4', '1.2.3'], @@ -396,6 +405,7 @@ describe('semverRuby', () => { it('returns correct version for replace strategy', () => { [ ['1.2.3', '1.0.3', 'replace', '1.0.3', '1.2.3'], + ['v1.2.3', 'v1.0.3', 'replace', '1.0.3', '1.2.3'], ['= 1.2.3', '= 1.0.3', 'replace', '1.0.3', '1.2.3'], ['!= 1.0.3', '!= 1.0.3', 'replace', '1.0.0', '1.2.3'], ['< 1.2.4', '< 1.0.3', 'replace', '1.0.0', '1.2.3'],