From 8b834509975a8eaa29c157c8bf641cef5891ce0d Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 13 May 2020 16:52:04 +0200
Subject: [PATCH] fix(ruby): better replace for complex ranges

---
 lib/versioning/ruby/index.spec.ts         |  1 +
 lib/versioning/ruby/strategies/replace.ts | 17 +++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/lib/versioning/ruby/index.spec.ts b/lib/versioning/ruby/index.spec.ts
index 3a155f4274..f3a29ebeea 100644
--- a/lib/versioning/ruby/index.spec.ts
+++ b/lib/versioning/ruby/index.spec.ts
@@ -513,6 +513,7 @@ describe('semverRuby', () => {
           '2.20.1',
         ],
         ['~> 6.0.0', '~> 5.2.0', 'replace', '5.2.4.1', '6.0.2.1'],
+        ['~> 5.0, < 6', '~> 4.0, < 5', 'replace', '4.7.5', '5.0.0'],
       ].forEach(
         ([expected, currentValue, rangeStrategy, fromVersion, toVersion]) => {
           expect(
diff --git a/lib/versioning/ruby/strategies/replace.ts b/lib/versioning/ruby/strategies/replace.ts
index 25eae772a4..8c62949d2e 100644
--- a/lib/versioning/ruby/strategies/replace.ts
+++ b/lib/versioning/ruby/strategies/replace.ts
@@ -45,6 +45,14 @@ function reduceOnePrecision(version: string): string {
   return versionParts.join('.');
 }
 
+export function matchPrecision(existing: string, next: string): string {
+  let res = next;
+  while (res.split('.').length > existing.split('.').length) {
+    res = reduceOnePrecision(res);
+  }
+  return res;
+}
+
 export default ({ to, range }: { range: string; to: string }): string => {
   if (satisfies(to, range)) {
     return range;
@@ -72,6 +80,15 @@ export default ({ to, range }: { range: string; to: string }): string => {
     }
     const newLastPart = bump({ to: massagedTo, range: lastPart });
     newRange = range.replace(lastPart, newLastPart);
+    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);
+    }
   }
   // istanbul ignore if
   if (!satisfies(to, newRange)) {
-- 
GitLab