Handle non-default hosts in `upgrade --major-versions` (#3947)
diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index b8a23cd..6286f74 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -20,6 +20,7 @@
import '../package.dart';
import '../package_name.dart';
import '../pubspec.dart';
+import '../pubspec_utils.dart';
import '../sdk.dart';
import '../solver.dart';
import '../source/git.dart';
@@ -685,23 +686,17 @@
final ref = update.ref;
final name = ref.name;
final resultId = resultPackages.firstWhere((id) => id.name == name);
- var description = ref.description;
- final versionConstraintString =
- constraint == null ? '^${resultId.version}' : constraint.toString();
- late Object? pubspecInformation;
- if (description is HostedDescription &&
- description.url == cache.hosted.defaultUrl) {
- pubspecInformation = versionConstraintString;
- } else {
- pubspecInformation = {
- ref.source.name: ref.description.serializeForPubspec(
- containingDir: entrypoint.rootDir,
- languageVersion: entrypoint.root.pubspec.languageVersion,
- ),
- if (description is HostedDescription || constraint != null)
- 'version': versionConstraintString
- };
- }
+
+ Object? description = pubspecDescription(
+ ref.withConstraint(
+ constraint ??
+ (ref.source is HostedSource
+ ? VersionConstraint.compatibleWith(resultId.version)
+ : VersionConstraint.any),
+ ),
+ cache,
+ entrypoint,
+ );
if (yamlEditor.parseAt(
[dependencyKey],
@@ -713,14 +708,14 @@
yamlEditor.update(
[dependencyKey],
wrapAsYamlNode(
- {name: pubspecInformation},
+ {name: description},
collectionStyle: CollectionStyle.BLOCK,
),
);
} else {
final packagePath = [dependencyKey, name];
- yamlEditor.update(packagePath, pubspecInformation);
+ yamlEditor.update(packagePath, description);
}
/// Remove the package from dev_dependencies if we are adding it to
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index bbe28ef..8cf9821 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -211,7 +211,7 @@
for (final dep in declaredHostedDependencies) {
final resolvedPackage = resolvedPackages[dep.name]!;
if (!toUpgrade.contains(dep.name)) {
- // If we're not to upgrade this package, or it wasn't in the
+ // If we're not trying to upgrade this package, or it wasn't in the
// resolution somehow, then we ignore it.
continue;
}
@@ -296,25 +296,16 @@
Map<PackageRange, PackageRange> changes,
) {
ArgumentError.checkNotNull(changes, 'changes');
-
final yamlEditor = YamlEditor(readTextFile(entrypoint.pubspecPath));
final deps = entrypoint.root.pubspec.dependencies.keys;
- final devDeps = entrypoint.root.pubspec.devDependencies.keys;
for (final change in changes.values) {
- if (deps.contains(change.name)) {
- yamlEditor.update(
- ['dependencies', change.name],
- // TODO(jonasfj): Fix support for third-party pub servers.
- change.constraint.toString(),
- );
- } else if (devDeps.contains(change.name)) {
- yamlEditor.update(
- ['dev_dependencies', change.name],
- // TODO: Fix support for third-party pub servers
- change.constraint.toString(),
- );
- }
+ final section =
+ deps.contains(change.name) ? 'dependencies' : 'dev_dependencies';
+ yamlEditor.update(
+ [section, change.name],
+ pubspecDescription(change, cache, entrypoint),
+ );
}
return yamlEditor.toString();
}
diff --git a/lib/src/pubspec_utils.dart b/lib/src/pubspec_utils.dart
index 5edf74a..f843337 100644
--- a/lib/src/pubspec_utils.dart
+++ b/lib/src/pubspec_utils.dart
@@ -5,8 +5,11 @@
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
+import 'entrypoint.dart';
import 'package_name.dart';
import 'pubspec.dart';
+import 'source/hosted.dart';
+import 'system_cache.dart';
/// Returns a new [Pubspec] without [original]'s dev_dependencies.
Pubspec stripDevDependencies(Pubspec original) {
@@ -145,3 +148,35 @@
/// just return an empty version constraint.
return VersionConstraint.empty;
}
+
+/// Returns a somewhat normalized version the description of a dependency with a
+/// version constraint (what comes after the version name in a dependencies
+/// section) as a json-style object.
+///
+/// Will use just the constraint for dependencies hosted at the default host.
+///
+/// Relative paths will be relative to [relativeEntrypoint].
+///
+/// The syntax used for hosted will depend on the language version of
+/// [relativeEntrypoint]
+Object? pubspecDescription(
+ PackageRange range,
+ SystemCache cache,
+ Entrypoint relativeEntrypoint,
+) {
+ final description = range.description;
+
+ final constraint = range.constraint;
+ if (description is HostedDescription &&
+ description.url == cache.hosted.defaultUrl) {
+ return constraint.toString();
+ } else {
+ return {
+ range.source.name: description.serializeForPubspec(
+ containingDir: relativeEntrypoint.rootDir,
+ languageVersion: relativeEntrypoint.root.pubspec.languageVersion,
+ ),
+ if (!constraint.isAny) 'version': constraint.toString()
+ };
+ }
+}
diff --git a/test/add/hosted/non_default_pub_server_test.dart b/test/add/hosted/non_default_pub_server_test.dart
index 7be0095..c2a339e 100644
--- a/test/add/hosted/non_default_pub_server_test.dart
+++ b/test/add/hosted/non_default_pub_server_test.dart
@@ -219,7 +219,7 @@
]).validate();
await d.appDir(
dependencies: {
- 'foo': {'version': 'any', 'hosted': url}
+ 'foo': {'hosted': url}
},
).validate();
});
diff --git a/test/upgrade/upgrade_major_versions_test.dart b/test/upgrade/upgrade_major_versions_test.dart
index 691b221..51d7263 100644
--- a/test/upgrade/upgrade_major_versions_test.dart
+++ b/test/upgrade/upgrade_major_versions_test.dart
@@ -307,5 +307,32 @@
]),
);
});
+
+ test('works with an explicit "hosted" description:', () async {
+ await servePackages();
+ final alternativeServer = await startPackageServer();
+ alternativeServer.serve('foo', '1.0.0');
+ alternativeServer.serve('foo', '2.0.0');
+ await d.appDir(
+ dependencies: {
+ 'foo': {'hosted': alternativeServer.url, 'version': '^1.0.0'},
+ },
+ ).create();
+
+ await pubGet();
+
+ await pubUpgrade(
+ args: ['--major-versions'],
+ output: allOf([
+ contains('Changed 1 constraint in pubspec.yaml:'),
+ contains('foo: ^1.0.0 -> ^2.0.0'),
+ ]),
+ );
+ await d.appDir(
+ dependencies: {
+ 'foo': {'hosted': alternativeServer.url, 'version': '^2.0.0'},
+ },
+ ).validate();
+ });
});
}