diff --git a/lib/manager/bundler/__snapshots__/extract.spec.ts.snap b/lib/manager/bundler/__snapshots__/extract.spec.ts.snap index 8471162943b7a1eb33e739aa6451bb9adc63777e..50ae40eb87c7e898619b6d1ecdd99274e21edea2 100644 --- a/lib/manager/bundler/__snapshots__/extract.spec.ts.snap +++ b/lib/manager/bundler/__snapshots__/extract.spec.ts.snap @@ -1595,7 +1595,7 @@ Object { "skipReason": "no-version", }, Object { - "currentValue": ">= 3.0.5, < 3.2", + "currentValue": "\\">= 3.0.5\\", \\"< 3.2\\"", "datasource": "rubygems", "depName": "listen", "lockedVersion": "3.1.5", diff --git a/lib/manager/bundler/extract.ts b/lib/manager/bundler/extract.ts index 225def6ef0a24fbb18f940083da6616a4c185a2d..2d746b5e29b394c4edc90887efe81495fb903eee 100644 --- a/lib/manager/bundler/extract.ts +++ b/lib/manager/bundler/extract.ts @@ -53,10 +53,18 @@ export async function extractPackageFile( managerData: { lineNumber }, }; if (gemMatch[3]) { - dep.currentValue = gemMatch[0] + let currentValue = gemMatch[0] .substring(`gem ${gemDelimiter}${dep.depName}${gemDelimiter},`.length) - .replace(regEx(gemDelimiter, 'g'), '') .trim(); + // strip quotes unless it's a complex constraint + if ( + currentValue.startsWith(gemDelimiter) && + currentValue.endsWith(gemDelimiter) && + currentValue.split(gemDelimiter).length === 3 + ) { + currentValue = currentValue.slice(1, -1); + } + dep.currentValue = currentValue; } else { dep.skipReason = SkipReason.NoVersion; } diff --git a/lib/versioning/ruby/index.spec.ts b/lib/versioning/ruby/index.spec.ts index 5cbe03cc4378718d7980f907fbc35542384c486a..3fadf2d0216ab9778dd2c605fad9c42b00c67589 100644 --- a/lib/versioning/ruby/index.spec.ts +++ b/lib/versioning/ruby/index.spec.ts @@ -366,6 +366,14 @@ describe('semverRuby', () => { ['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'], ['4.7.8', '~> 4.7, >= 4.7.4', 'pin', '4.7.5', '4.7.8'], + [ + "'>= 3.0.5', '< 3.3'", + "'>= 3.0.5', '< 3.2'", + 'replace', + '3.1.5', + '3.2.1', + ], + ["'0.0.11'", "'0.0.10'", 'replace', '0.0.10', '0.0.11'], ].forEach( ([expected, currentValue, rangeStrategy, fromVersion, toVersion]) => { expect( diff --git a/lib/versioning/ruby/index.ts b/lib/versioning/ruby/index.ts index 334e27b46d0a6cb89e5e5036b7aeaafda84aa757..c0eadc29c2a0260dde7085000a252471b033ea1b 100644 --- a/lib/versioning/ruby/index.ts +++ b/lib/versioning/ruby/index.ts @@ -25,7 +25,7 @@ export const supportedRangeStrategies = ['bump', 'extend', 'pin', 'replace']; function vtrim<T = unknown>(version: T): string | T { if (typeof version === 'string') { - return version.replace(/^v/, ''); + return version.replace(/^v/, '').replace(/('|")/g, ''); } return version; } @@ -84,28 +84,39 @@ const getNewValue = ({ fromVersion, toVersion, }: NewValueConfig): string => { - let result = null; + let newValue = null; if (isVersion(currentValue)) { - return currentValue.startsWith('v') ? 'v' + toVersion : toVersion; + newValue = currentValue.startsWith('v') ? 'v' + toVersion : toVersion; + } else if (currentValue.replace(/^=\s*/, '') === fromVersion) { + newValue = currentValue.replace(fromVersion, toVersion); + } else { + switch (rangeStrategy) { + case 'pin': + newValue = pin({ to: vtrim(toVersion) }); + break; + case 'bump': + newValue = bump({ range: vtrim(currentValue), to: vtrim(toVersion) }); + break; + case 'replace': + newValue = replace({ + range: vtrim(currentValue), + to: vtrim(toVersion), + }); + break; + // istanbul ignore next + default: + logger.warn(`Unsupported strategy ${rangeStrategy}`); + } } - if (currentValue.replace(/^=\s*/, '') === fromVersion) { - return currentValue.replace(fromVersion, toVersion); + if (/^('|")/.exec(currentValue)) { + const delimiter = currentValue[0]; + return newValue + .split(',') + .map((element) => element.replace(/^(\s*)/, `$1${delimiter}`)) + .map((element) => element.replace(/(\s*)$/, `${delimiter}$1`)) + .join(','); } - switch (rangeStrategy) { - case 'pin': - result = pin({ to: vtrim(toVersion) }); - break; - case 'bump': - result = bump({ range: vtrim(currentValue), to: vtrim(toVersion) }); - break; - case 'replace': - result = replace({ range: vtrim(currentValue), to: vtrim(toVersion) }); - break; - // istanbul ignore next - default: - logger.warn(`Unsupported strategy ${rangeStrategy}`); - } - return result; + return newValue; }; export const sortVersions = (left: string, right: string): number =>