2020-07-05 05:35:49 +00:00
|
|
|
import { satisfies } from '@renovatebot/ruby-semver';
|
2020-01-14 13:16:58 +00:00
|
|
|
import { logger } from '../../../logger';
|
2020-05-01 16:03:48 +00:00
|
|
|
import bump from './bump';
|
2020-01-14 13:16:58 +00:00
|
|
|
|
|
|
|
function countInstancesOf(str: string, char: string): number {
|
|
|
|
return str.split(char).length - 1;
|
|
|
|
}
|
|
|
|
|
2020-01-14 16:37:19 +00:00
|
|
|
function isMajorRange(range: string): boolean {
|
2020-04-12 16:09:36 +00:00
|
|
|
const splitRange = range.split(',').map((part) => part.trim());
|
2020-01-14 16:37:19 +00:00
|
|
|
return (
|
|
|
|
splitRange.length === 1 &&
|
2020-08-11 06:08:16 +00:00
|
|
|
splitRange[0]?.startsWith('~>') &&
|
2020-01-14 16:37:19 +00:00
|
|
|
countInstancesOf(splitRange[0], '.') === 0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-01-14 13:16:58 +00:00
|
|
|
function isCommonRubyMajorRange(range: string): boolean {
|
2020-04-12 16:09:36 +00:00
|
|
|
const splitRange = range.split(',').map((part) => part.trim());
|
2020-01-14 13:16:58 +00:00
|
|
|
return (
|
|
|
|
splitRange.length === 2 &&
|
2020-08-11 06:08:16 +00:00
|
|
|
splitRange[0]?.startsWith('~>') &&
|
2020-01-14 13:16:58 +00:00
|
|
|
countInstancesOf(splitRange[0], '.') === 1 &&
|
2020-08-11 06:08:16 +00:00
|
|
|
splitRange[1]?.startsWith('>=')
|
2020-01-14 13:16:58 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function isCommonRubyMinorRange(range: string): boolean {
|
2020-04-12 16:09:36 +00:00
|
|
|
const splitRange = range.split(',').map((part) => part.trim());
|
2020-01-14 13:16:58 +00:00
|
|
|
return (
|
|
|
|
splitRange.length === 2 &&
|
2020-08-11 06:08:16 +00:00
|
|
|
splitRange[0]?.startsWith('~>') &&
|
2020-01-14 13:16:58 +00:00
|
|
|
countInstancesOf(splitRange[0], '.') === 2 &&
|
2020-08-11 06:08:16 +00:00
|
|
|
splitRange[1]?.startsWith('>=')
|
2020-01-14 13:16:58 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function reduceOnePrecision(version: string): string {
|
|
|
|
const versionParts = version.split('.');
|
|
|
|
// istanbul ignore if
|
2020-03-17 11:15:22 +00:00
|
|
|
if (versionParts.length === 1) {
|
|
|
|
return version;
|
|
|
|
}
|
2020-01-14 13:16:58 +00:00
|
|
|
versionParts.pop();
|
|
|
|
return versionParts.join('.');
|
|
|
|
}
|
2019-01-03 05:32:08 +00:00
|
|
|
|
2020-05-13 14:52:04 +00:00
|
|
|
export function matchPrecision(existing: string, next: string): string {
|
|
|
|
let res = next;
|
|
|
|
while (res.split('.').length > existing.split('.').length) {
|
|
|
|
res = reduceOnePrecision(res);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-11-24 07:43:24 +00:00
|
|
|
export default ({ to, range }: { range: string; to: string }): string => {
|
2019-01-13 10:06:28 +00:00
|
|
|
if (satisfies(to, range)) {
|
|
|
|
return range;
|
|
|
|
}
|
2020-01-14 13:16:58 +00:00
|
|
|
let newRange;
|
|
|
|
if (isCommonRubyMajorRange(range)) {
|
|
|
|
const firstPart = reduceOnePrecision(to);
|
|
|
|
newRange = `~> ${firstPart}, >= ${to}`;
|
|
|
|
} else if (isCommonRubyMinorRange(range)) {
|
|
|
|
const firstPart = reduceOnePrecision(to) + '.0';
|
|
|
|
newRange = `~> ${firstPart}, >= ${to}`;
|
2020-01-14 16:37:19 +00:00
|
|
|
} else if (isMajorRange(range)) {
|
|
|
|
const majorPart = to.split('.')[0];
|
|
|
|
newRange = '~>' + (range.includes(' ') ? ' ' : '') + majorPart;
|
2020-01-14 13:16:58 +00:00
|
|
|
} else {
|
|
|
|
const lastPart = range
|
|
|
|
.split(',')
|
2020-04-12 16:09:36 +00:00
|
|
|
.map((part) => part.trim())
|
2022-01-05 15:33:37 +00:00
|
|
|
.slice(-1)
|
|
|
|
.join();
|
2020-01-14 13:16:58 +00:00
|
|
|
const lastPartPrecision = lastPart.split('.').length;
|
|
|
|
const toPrecision = to.split('.').length;
|
|
|
|
let massagedTo: string = to;
|
|
|
|
if (!lastPart.startsWith('<') && toPrecision > lastPartPrecision) {
|
2020-04-12 16:09:36 +00:00
|
|
|
massagedTo = to.split('.').slice(0, lastPartPrecision).join('.');
|
2020-01-14 13:16:58 +00:00
|
|
|
}
|
|
|
|
const newLastPart = bump({ to: massagedTo, range: lastPart });
|
|
|
|
newRange = range.replace(lastPart, newLastPart);
|
2020-05-13 14:52:04 +00:00
|
|
|
const firstPart = range
|
|
|
|
.split(',')
|
|
|
|
.map((part) => part.trim())
|
|
|
|
.shift();
|
|
|
|
if (firstPart && !satisfies(to, firstPart)) {
|
|
|
|
let newFirstPart = bump({ to: massagedTo, range: firstPart });
|
|
|
|
newFirstPart = matchPrecision(firstPart, newFirstPart);
|
|
|
|
newRange = newRange.replace(firstPart, newFirstPart);
|
|
|
|
}
|
2020-01-14 13:16:58 +00:00
|
|
|
}
|
|
|
|
// istanbul ignore if
|
|
|
|
if (!satisfies(to, newRange)) {
|
|
|
|
logger.warn(
|
|
|
|
{ range, to, newRange },
|
|
|
|
'Ruby versioning getNewValue problem: to version is not satisfied by new range'
|
|
|
|
);
|
|
|
|
return range;
|
2019-12-21 09:59:07 +00:00
|
|
|
}
|
2020-01-14 13:16:58 +00:00
|
|
|
return newRange;
|
2019-01-13 10:06:28 +00:00
|
|
|
};
|