From c450621edb50bac2a24a5e8db38c57aba4710920 Mon Sep 17 00:00:00 2001 From: Sergio Zharinov Date: Wed, 1 Jul 2020 15:50:32 +0400 Subject: [PATCH] fix(maven): Use consistent precision for extended ranges (#6623) --- lib/versioning/maven/compare.ts | 73 ++++++++++++++++++++++++++---- lib/versioning/maven/index.spec.ts | 30 +++++++++--- 2 files changed, 86 insertions(+), 17 deletions(-) diff --git a/lib/versioning/maven/compare.ts b/lib/versioning/maven/compare.ts index 9440cd7f75df05..375c394226b2ea 100644 --- a/lib/versioning/maven/compare.ts +++ b/lib/versioning/maven/compare.ts @@ -113,7 +113,7 @@ const zeroToken: NumberToken = { isTransition: false, }; -function tokenize(versionStr: string): Token[] { +function tokenize(versionStr: string, preserveMinorZeroes = false): Token[] { let buf: Token[] = []; let result: Token[] = []; let leadingZero = true; @@ -126,7 +126,7 @@ function tokenize(versionStr: string): Token[] { leadingZero = false; result = result.concat(buf); buf = []; - } else if (leadingZero) { + } else if (leadingZero || preserveMinorZeroes) { result = result.concat(buf); buf = []; } @@ -444,6 +444,36 @@ function rangeToStr(fullRange: Range[]): string | null { return intervals.join(','); } +function tokensToStr(tokens: Token[]): string { + return tokens.reduce((result, token, idx) => { + const prefix = token.prefix === PREFIX_DOT ? '.' : '-'; + return `${result}${idx !== 0 && token.val !== '' ? prefix : ''}${ + token.val + }`; + }, ''); +} + +function coerceRangeValue(prev: string, next: string): string { + const prevTokens = tokenize(prev, true); + const nextTokens = tokenize(next, true); + const resultTokens = nextTokens.slice(0, prevTokens.length); + const align = Math.max(0, prevTokens.length - nextTokens.length); + if (align > 0) { + resultTokens.push(...prevTokens.slice(prevTokens.length - align)); + } + return tokensToStr(resultTokens); +} + +function incrementRangeValue(value: string): string { + const tokens = tokenize(value); + const lastToken = tokens[tokens.length - 1]; + if (typeof lastToken.val === 'number') { + lastToken.val += 1; + return coerceRangeValue(value, tokensToStr(tokens)); + } + return value; +} + function autoExtendMavenRange( currentRepresentation: string, newValue: string @@ -482,17 +512,40 @@ function autoExtendMavenRange( return currentRepresentation; } } + const interval = range[nearestIntervalIdx]; - if (interval.rightValue !== null) { - interval.rightValue = newValue; - } else { - interval.leftValue = newValue; + const { leftValue, rightValue } = interval; + if ( + leftValue !== null && + rightValue !== null && + incrementRangeValue(leftValue) === rightValue + ) { + interval.leftValue = coerceRangeValue(leftValue, newValue); + interval.rightValue = incrementRangeValue(interval.leftValue); + } else if (rightValue !== null) { + if (interval.rightType === INCLUDING_POINT) { + const tokens = tokenize(rightValue); + const lastToken = tokens[tokens.length - 1]; + if (typeof lastToken.val === 'number') { + interval.rightValue = coerceRangeValue(rightValue, newValue); + } else { + interval.rightValue = newValue; + } + } else { + interval.rightValue = incrementRangeValue( + coerceRangeValue(rightValue, newValue) + ); + } + } else if (leftValue !== null) { + interval.leftValue = coerceRangeValue(leftValue, newValue); } + if (interval.leftValue && interval.rightValue) { - if (compare(interval.leftValue, interval.rightValue) !== 1) { - return rangeToStr(range); - } - return currentRepresentation; + const correctRepresentation = + compare(interval.leftValue, interval.rightValue) !== 1 + ? rangeToStr(range) + : null; + return correctRepresentation || currentRepresentation; } return rangeToStr(range); } diff --git a/lib/versioning/maven/index.spec.ts b/lib/versioning/maven/index.spec.ts index e6fcd8b74c32b7..cb74cea649333b 100644 --- a/lib/versioning/maven/index.spec.ts +++ b/lib/versioning/maven/index.spec.ts @@ -245,21 +245,37 @@ describe('versioning/maven/compare', () => { const sample = [ ['[1.2.3]', '1.2.3', '[1.2.3]'], ['[1.2.3]', '1.2.4', '[1.2.4]'], + ['[1.0.0,1.2.3]', '0.0.1', '[1.0.0,1.2.3]'], ['[1.0.0,1.2.3]', '1.2.4', '[1.0.0,1.2.4]'], ['[1.0.0,1.2.23]', '1.1.0', '[1.0.0,1.2.23]'], ['(,1.0]', '2.0', '(,2.0]'], ['],1.0]', '2.0', '],2.0]'], - ['(,1.0)', '2.0', '(,2.0)'], - ['],1.0[', '2.0', '],2.0['], - ['[1.0,1.2],[1.3,1.5)', '1.2.4', '[1.0,1.2.4],[1.3,1.5)'], - ['[1.0,1.2],[1.3,1.5[', '1.2.4', '[1.0,1.2.4],[1.3,1.5['], + ['(,1.0)', '2.0', '(,3.0)'], + ['],1.0[', '2.0', '],3.0['], + ['[1.0,1.2.3],[1.3,1.5)', '1.2.4', '[1.0,1.2.4],[1.3,1.5)'], + ['[1.0,1.2.3],[1.3,1.5[', '1.2.4', '[1.0,1.2.4],[1.3,1.5['], ['[1.2.3,)', '1.2.4', '[1.2.4,)'], ['[1.2.3,[', '1.2.4', '[1.2.4,['], ['[1.2.3,]', '1.2.4', '[1.2.3,]'], // invalid range - ['[0.21,0.22)', '0.20.21', '[0.21,0.22)'], + ['[0.21,0.22)', '0.20.21', '[0.20,0.21)'], ['[0.21,0.22)', '0.21.1', '[0.21,0.22)'], - ['[0.21,0.22)', '0.22.1', '[0.21,0.22.1)'], - ['[0.21,0.22)', '0.23', '[0.21,0.23)'], + ['[0.21,0.22.0)', '0.22.1', '[0.21,0.22.2)'], + ['[0.21,0.22)', '0.23', '[0.23,0.24)'], + + ['[1.8,1.9)', '1.9.0.1', '[1.9,1.10)'], + ['[1.8a,1.9)', '1.9.0.1', '[1.8a,1.10)'], + ['[1.8,1.9.0)', '1.9.0.1', '[1.8,1.10.0)'], + ['[1.8,1.9.0.0)', '1.9.0.1', '[1.8,1.9.0.2)'], + ['[1.8,1.9.0.0)', '1.10.1', '[1.8,1.10.2.0)'], + + ['[1.8,1.9)', '1.9.1', '[1.9,1.10)'], + ['[1.8,1.9)', '1.10.0', '[1.10,1.11)'], + ['[1.8,1.9)', '1.10.1', '[1.10,1.11)'], + + ['(,1.0.0]', '2.0.0', '(,2.0.0]'], + ['(,1.0]', '2.0.0', '(,2.0]'], + ['(,1]', '2.0.0', '(,2]'], + ['(,1.0.0-foobar]', '2.0.0', '(,2.0.0]'], ]; sample.forEach(([oldRepr, newValue, newRepr]) => { expect(autoExtendMavenRange(oldRepr, newValue)).toEqual(newRepr);