Support for different versioning strategies in dependency_services (#3320)

diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index 47805bc..dd3379f 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -118,11 +118,25 @@
             'name': p.name,
             'version': p.version.toString(),
             'kind': _kindString(pubspec, p.name),
-            'constraint': originalConstraint == null
+            'constraintBumped': originalConstraint == null
                 ? null
                 : upgradeType == UpgradeType.compatible
                     ? originalConstraint.toString()
                     : VersionConstraint.compatibleWith(p.version).toString(),
+            'constraintWidened': originalConstraint == null
+                ? null
+                : upgradeType == UpgradeType.compatible
+                    ? originalConstraint.toString()
+                    : _widenConstraint(originalConstraint, p.version)
+                        .toString(),
+            'constraintBumpedIfNeeded': originalConstraint == null
+                ? null
+                : upgradeType == UpgradeType.compatible
+                    ? originalConstraint.toString()
+                    : originalConstraint.allows(p.version)
+                        ? originalConstraint.toString()
+                        : VersionConstraint.compatibleWith(p.version)
+                            .toString(),
             'previousVersion': currentPackages[p.name]?.version.toString(),
             'previousConstraint': originalConstraint?.toString(),
           };
@@ -135,7 +149,9 @@
               'version': null,
               'kind':
                   'transitive', // Only transitive constraints can be removed.
-              'constraint': null,
+              'constraintBumped': null,
+              'constraintWidened': null,
+              'constraintBumpedIfNeeded': null,
               'previousVersion':
                   currentPackages[oldPackageName]?.version.toString(),
               'previousConstraint': null,
@@ -379,3 +395,30 @@
           ? pubspec.devDependencies
           : null;
 }
+
+VersionConstraint _widenConstraint(
+    VersionConstraint original, Version newVersion) {
+  if (original.allows(newVersion)) return original;
+  if (original is VersionRange) {
+    final min = original.min;
+    final max = original.max;
+    if (max != null && newVersion >= max) {
+      return VersionRange(
+        min: min,
+        includeMin: original.includeMin,
+        max: newVersion.nextBreaking.firstPreRelease,
+      );
+    }
+    if (min != null && newVersion <= min) {
+      return VersionRange(
+          min: newVersion,
+          includeMin: true,
+          max: max,
+          includeMax: original.includeMax);
+    }
+  }
+
+  if (original.isEmpty) return newVersion;
+  throw ArgumentError.value(
+      original, 'original', 'Must be a Version range or empty');
+}
diff --git a/test/dependency_services/dependency_services_test.dart b/test/dependency_services/dependency_services_test.dart
index 4503e67..f25cf2d 100644
--- a/test/dependency_services/dependency_services_test.dart
+++ b/test/dependency_services/dependency_services_test.dart
@@ -144,18 +144,22 @@
       ..serve('foo', '1.2.3')
       ..serve('foo', '2.2.3')
       ..serve('bar', '1.2.3')
-      ..serve('bar', '2.2.3');
+      ..serve('bar', '2.2.3')
+      ..serve('boo', '1.2.3');
     await d.dir(appPath, [
       d.pubspec({
         'name': 'app',
         'dependencies': {
           'foo': '^1.0.0',
           'bar': '^1.0.0',
+          'boo': '^1.0.0',
         },
       })
     ]).create();
     await pubGet();
     server.serve('foo', '1.2.4');
+    server.serve('boo', '1.2.4');
+
     await listReportApply(context, [
       _PackageVersion('foo', Version.parse('1.2.4')),
     ], reportAssertions: (report) {
diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt
index 368a120..7b8290e 100644
--- a/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt
+++ b/test/testdata/goldens/dependency_services/dependency_services_test/Adding transitive.txt
@@ -48,7 +48,9 @@
           "name": "foo",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         },
@@ -56,7 +58,9 @@
           "name": "transitive",
           "version": "1.0.0",
           "kind": "transitive",
-          "constraint": null,
+          "constraintBumped": null,
+          "constraintWidened": null,
+          "constraintBumpedIfNeeded": null,
           "previousVersion": null,
           "previousConstraint": null
         }
@@ -66,7 +70,9 @@
           "name": "foo",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         },
@@ -74,7 +80,9 @@
           "name": "transitive",
           "version": "1.0.0",
           "kind": "transitive",
-          "constraint": null,
+          "constraintBumped": null,
+          "constraintWidened": null,
+          "constraintBumpedIfNeeded": null,
           "previousVersion": null,
           "previousConstraint": null
         }
diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt
index 4c3fd0b..c133458 100644
--- a/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt
+++ b/test/testdata/goldens/dependency_services/dependency_services_test/Compatible.txt
@@ -1,7 +1,7 @@
 # GENERATED BY: test/dependency_services/dependency_services_test.dart
 
 $ cat pubspec.yaml
-{"name":"app","dependencies":{"foo":"^1.0.0","bar":"^1.0.0"},"environment":{"sdk":">=0.1.2 <1.0.0"}}
+{"name":"app","dependencies":{"foo":"^1.0.0","bar":"^1.0.0","boo":"^1.0.0"},"environment":{"sdk":">=0.1.2 <1.0.0"}}
 $ cat pubspec.lock
 # Generated by pub
 # See https://dart.dev/tools/pub/glossary#lockfile
@@ -13,6 +13,13 @@
       url: "http://localhost:$PORT"
     source: hosted
     version: "1.2.3"
+  boo:
+    dependency: "direct main"
+    description:
+      name: boo
+      url: "http://localhost:$PORT"
+    source: hosted
+    version: "1.2.3"
   foo:
     dependency: "direct main"
     description:
@@ -35,6 +42,12 @@
       "constraint": "^1.0.0"
     },
     {
+      "name": "boo",
+      "version": "1.2.3",
+      "kind": "direct",
+      "constraint": "^1.0.0"
+    },
+    {
       "name": "foo",
       "version": "1.2.3",
       "kind": "direct",
@@ -61,7 +74,9 @@
           "name": "bar",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         }
@@ -71,7 +86,52 @@
           "name": "bar",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
+          "previousVersion": "1.2.3",
+          "previousConstraint": "^1.0.0"
+        }
+      ]
+    },
+    {
+      "name": "boo",
+      "version": "1.2.3",
+      "kind": "direct",
+      "latest": "1.2.4",
+      "constraint": "^1.0.0",
+      "compatible": [
+        {
+          "name": "boo",
+          "version": "1.2.4",
+          "kind": "direct",
+          "constraintBumped": "^1.0.0",
+          "constraintWidened": "^1.0.0",
+          "constraintBumpedIfNeeded": "^1.0.0",
+          "previousVersion": "1.2.3",
+          "previousConstraint": "^1.0.0"
+        }
+      ],
+      "singleBreaking": [
+        {
+          "name": "boo",
+          "version": "1.2.4",
+          "kind": "direct",
+          "constraintBumped": "^1.2.4",
+          "constraintWidened": "^1.0.0",
+          "constraintBumpedIfNeeded": "^1.0.0",
+          "previousVersion": "1.2.3",
+          "previousConstraint": "^1.0.0"
+        }
+      ],
+      "multiBreaking": [
+        {
+          "name": "boo",
+          "version": "1.2.4",
+          "kind": "direct",
+          "constraintBumped": "^1.2.4",
+          "constraintWidened": "^1.0.0",
+          "constraintBumpedIfNeeded": "^1.0.0",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         }
@@ -88,7 +148,9 @@
           "name": "foo",
           "version": "1.2.4",
           "kind": "direct",
-          "constraint": "^1.0.0",
+          "constraintBumped": "^1.0.0",
+          "constraintWidened": "^1.0.0",
+          "constraintBumpedIfNeeded": "^1.0.0",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         }
@@ -98,7 +160,9 @@
           "name": "foo",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         }
@@ -108,7 +172,9 @@
           "name": "foo",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         }
@@ -126,7 +192,7 @@
 -------------------------------- END OF OUTPUT ---------------------------------
 
 $ cat pubspec.yaml
-{"name":"app","dependencies":{"foo":"^1.0.0","bar":"^1.0.0"},"environment":{"sdk":">=0.1.2 <1.0.0"}}
+{"name":"app","dependencies":{"foo":"^1.0.0","bar":"^1.0.0","boo":"^1.0.0"},"environment":{"sdk":">=0.1.2 <1.0.0"}}
 $ cat pubspec.lock
 # Generated by pub
 # See https://dart.dev/tools/pub/glossary#lockfile
@@ -138,6 +204,13 @@
       url: "http://localhost:$PORT"
     source: hosted
     version: "1.2.3"
+  boo:
+    dependency: "direct main"
+    description:
+      name: boo
+      url: "http://localhost:$PORT"
+    source: hosted
+    version: "1.2.3"
   foo:
     dependency: "direct main"
     description:
diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt b/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt
index 3a0133a..bfc5a78 100644
--- a/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt
+++ b/test/testdata/goldens/dependency_services/dependency_services_test/Removing transitive.txt
@@ -61,7 +61,9 @@
           "name": "foo",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         },
@@ -69,7 +71,9 @@
           "name": "transitive",
           "version": null,
           "kind": "transitive",
-          "constraint": null,
+          "constraintBumped": null,
+          "constraintWidened": null,
+          "constraintBumpedIfNeeded": null,
           "previousVersion": "1.0.0",
           "previousConstraint": null
         }
@@ -79,7 +83,9 @@
           "name": "foo",
           "version": "2.2.3",
           "kind": "direct",
-          "constraint": "^2.2.3",
+          "constraintBumped": "^2.2.3",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.2.3",
           "previousVersion": "1.2.3",
           "previousConstraint": "^1.0.0"
         },
@@ -87,7 +93,9 @@
           "name": "transitive",
           "version": null,
           "kind": "transitive",
-          "constraint": null,
+          "constraintBumped": null,
+          "constraintWidened": null,
+          "constraintBumpedIfNeeded": null,
           "previousVersion": "1.0.0",
           "previousConstraint": null
         }
diff --git a/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt b/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt
index 1b3af24..10f5426 100644
--- a/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt
+++ b/test/testdata/goldens/dependency_services/dependency_services_test/multibreaking.txt
@@ -62,7 +62,9 @@
           "name": "bar",
           "version": "2.0.0",
           "kind": "direct",
-          "constraint": "^2.0.0",
+          "constraintBumped": "^2.0.0",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.0.0",
           "previousVersion": "1.0.0",
           "previousConstraint": "^1.0.0"
         },
@@ -70,7 +72,9 @@
           "name": "foo",
           "version": "3.0.1",
           "kind": "direct",
-          "constraint": "^3.0.1",
+          "constraintBumped": "^3.0.1",
+          "constraintWidened": ">=1.0.0 <4.0.0",
+          "constraintBumpedIfNeeded": "^3.0.1",
           "previousVersion": "1.0.0",
           "previousConstraint": "^1.0.0"
         }
@@ -87,7 +91,9 @@
           "name": "foo",
           "version": "1.5.0",
           "kind": "direct",
-          "constraint": "^1.0.0",
+          "constraintBumped": "^1.0.0",
+          "constraintWidened": "^1.0.0",
+          "constraintBumpedIfNeeded": "^1.0.0",
           "previousVersion": "1.0.0",
           "previousConstraint": "^1.0.0"
         }
@@ -97,7 +103,9 @@
           "name": "foo",
           "version": "2.0.0",
           "kind": "direct",
-          "constraint": "^2.0.0",
+          "constraintBumped": "^2.0.0",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.0.0",
           "previousVersion": "1.0.0",
           "previousConstraint": "^1.0.0"
         }
@@ -107,7 +115,9 @@
           "name": "foo",
           "version": "3.0.1",
           "kind": "direct",
-          "constraint": "^3.0.1",
+          "constraintBumped": "^3.0.1",
+          "constraintWidened": ">=1.0.0 <4.0.0",
+          "constraintBumpedIfNeeded": "^3.0.1",
           "previousVersion": "1.0.0",
           "previousConstraint": "^1.0.0"
         },
@@ -115,7 +125,9 @@
           "name": "bar",
           "version": "2.0.0",
           "kind": "direct",
-          "constraint": "^2.0.0",
+          "constraintBumped": "^2.0.0",
+          "constraintWidened": ">=1.0.0 <3.0.0",
+          "constraintBumpedIfNeeded": "^2.0.0",
           "previousVersion": "1.0.0",
           "previousConstraint": "^1.0.0"
         }