From d69ab02bc555dc804133bc3039b78ae78d6a4a85 Mon Sep 17 00:00:00 2001
From: Phil Nelson <philip@whatsbeef.net>
Date: Fri, 9 Jul 2021 17:14:42 +1000
Subject: [PATCH] fix: widening support in composer versioning (#10753)

---
 lib/versioning/composer/index.spec.ts | 46 +++++++++++++++++++++++++--
 lib/versioning/composer/index.ts      | 33 ++++++++++++-------
 2 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/lib/versioning/composer/index.spec.ts b/lib/versioning/composer/index.spec.ts
index 1e7aa29ff4..610613f148 100644
--- a/lib/versioning/composer/index.spec.ts
+++ b/lib/versioning/composer/index.spec.ts
@@ -306,12 +306,52 @@ describe('semver.getNewValue()', () => {
     ).toEqual('~3.0');
     expect(
       semver.getNewValue({
-        currentValue: '~1.2 || ~2.0',
+        currentValue: '~1.2 || ~2.0 || ~3.0',
         rangeStrategy: 'widen',
         currentVersion: '2.0.0',
-        newVersion: '3.1.0',
+        newVersion: '5.1.0',
+      })
+    ).toEqual('~1.2 || ~2.0 || ~3.0 || ~5.0');
+    expect(
+      semver.getNewValue({
+        currentValue: '^1.2',
+        rangeStrategy: 'widen',
+        currentVersion: '1.2.0',
+        newVersion: '2.0.0',
+      })
+    ).toEqual('^1.2 || ^2.0');
+    expect(
+      semver.getNewValue({
+        currentValue: '~1.2',
+        rangeStrategy: 'widen',
+        currentVersion: '1.2.0',
+        newVersion: '2.4.0',
+      })
+    ).toEqual('~1.2 || ~2.0');
+    expect(
+      semver.getNewValue({
+        currentValue: '~1.2',
+        rangeStrategy: 'widen',
+        currentVersion: '1.2.0',
+        newVersion: '1.9.0',
+      })
+    ).toEqual('~1.2');
+    expect(
+      semver.getNewValue({
+        currentValue: '^1.2',
+        rangeStrategy: 'widen',
+        currentVersion: '1.2.0',
+        newVersion: '1.9.0',
+      })
+    ).toEqual('^1.2');
+    expect(
+      semver.getNewValue({
+        currentValue: '^1.0 || ^2.0',
+        rangeStrategy: 'widen',
+        currentVersion: '2.0.0',
+        newVersion: '2.1.0',
       })
-    ).toEqual('~1.2 || ~2.0 || ~3.0');
+    ).toEqual('^1.0 || ^2.0');
   });
   it('returns newVersion if unsupported', () => {
     expect(
diff --git a/lib/versioning/composer/index.ts b/lib/versioning/composer/index.ts
index a6f497ea32..e9f22f9a3a 100644
--- a/lib/versioning/composer/index.ts
+++ b/lib/versioning/composer/index.ts
@@ -172,20 +172,29 @@ function getNewValue({
       newVersion: padZeroes(normalizeVersion(newVersion)),
     });
   }
-  if (currentValue.includes(' || ')) {
-    const lastValue = currentValue.split('||').pop().trim();
-    const replacementValue = getNewValue({
-      currentValue: lastValue,
-      rangeStrategy,
-      currentVersion,
-      newVersion,
-    });
-    if (rangeStrategy === 'replace') {
-      newValue = replacementValue;
-    } else if (rangeStrategy === 'widen') {
-      newValue = currentValue + ' || ' + replacementValue;
+
+  if (rangeStrategy === 'widen' && matches(newVersion, currentValue)) {
+    newValue = currentValue;
+  } else {
+    const hasOr = currentValue.includes(' || ');
+    if (hasOr || rangeStrategy === 'widen') {
+      const lastValue = hasOr
+        ? currentValue.split('||').pop().trim()
+        : currentValue;
+      const replacementValue = getNewValue({
+        currentValue: lastValue,
+        rangeStrategy: 'replace',
+        currentVersion,
+        newVersion,
+      });
+      if (rangeStrategy === 'replace') {
+        newValue = replacementValue;
+      } else {
+        newValue = currentValue + ' || ' + replacementValue;
+      }
     }
   }
+
   if (!newValue) {
     logger.warn(
       { currentValue, rangeStrategy, currentVersion, newVersion },
-- 
GitLab