Handle whole workspace in `pub upgrade [--tighten|--major-versions]` (#4213)
diff --git a/lib/src/command/add.dart b/lib/src/command/add.dart
index ddf9933..5a78500 100644
--- a/lib/src/command/add.dart
+++ b/lib/src/command/add.dart
@@ -349,15 +349,10 @@
dependencies.add(range);
}
- return Pubspec(
- original.name,
- version: original.version,
- sdkConstraints: original.sdkConstraints,
+ return original.copyWith(
dependencies: dependencies,
devDependencies: devDependencies,
dependencyOverrides: dependencyOverrides,
- workspace: original.workspace,
- resolution: original.resolution,
);
}
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index b1f17ac..9e1bcf7 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -105,14 +105,8 @@
?.firstWhereOrNull((element) => element.name == package.name);
final multiBreakingVersion = breakingPackagesResult
?.firstWhereOrNull((element) => element.name == package.name);
- final singleBreakingPubspec = Pubspec(
- compatiblePubspec.name,
- version: compatiblePubspec.version,
- sdkConstraints: compatiblePubspec.sdkConstraints,
- dependencies: compatiblePubspec.dependencies.values,
- devDependencies: compatiblePubspec.devDependencies.values,
- workspace: compatiblePubspec.workspace,
- );
+ final singleBreakingPubspec = compatiblePubspec.copyWith();
+
final dependencySet =
_dependencySetOfPackage(singleBreakingPubspec, package);
final kind = _kindString(compatiblePubspec, package.name);
@@ -745,13 +739,7 @@
final pubspec = (upgradeType == _UpgradeType.multiBreaking ||
upgradeType == _UpgradeType.smallestUpdate)
? stripVersionBounds(rootPubspec)
- : Pubspec(
- rootPubspec.name,
- dependencies: rootPubspec.dependencies.values,
- devDependencies: rootPubspec.devDependencies.values,
- sdkConstraints: rootPubspec.sdkConstraints,
- workspace: rootPubspec.workspace,
- );
+ : rootPubspec.copyWith();
final dependencySet = _dependencySetOfPackage(pubspec, package);
if (dependencySet != null) {
diff --git a/lib/src/command/remove.dart b/lib/src/command/remove.dart
index c2e7e32..2dd1b79 100644
--- a/lib/src/command/remove.dart
+++ b/lib/src/command/remove.dart
@@ -123,15 +123,10 @@
devDependencies.remove(package.name);
}
}
- return Pubspec(
- original.name,
- version: original.version,
- sdkConstraints: original.sdkConstraints,
+ return original.copyWith(
dependencies: dependencies.values,
devDependencies: devDependencies.values,
dependencyOverrides: overrides.values,
- workspace: original.workspace,
- resolution: original.resolution,
);
}
diff --git a/lib/src/command/upgrade.dart b/lib/src/command/upgrade.dart
index 1832187..8d3c966 100644
--- a/lib/src/command/upgrade.dart
+++ b/lib/src/command/upgrade.dart
@@ -3,9 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
-import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml_edit/yaml_edit.dart';
@@ -21,7 +19,6 @@
import '../sdk.dart';
import '../solver.dart';
import '../source/hosted.dart';
-import '../source/root.dart';
import '../utils.dart';
/// Handles the `upgrade` pub command.
@@ -141,14 +138,21 @@
await _runUpgrade(entrypoint);
if (_tighten) {
final changes = tighten(
- entrypoint.workspaceRoot.pubspec,
+ entrypoint,
entrypoint.lockFile.packages.values.toList(),
);
if (!_dryRun) {
- final newPubspecText = _updatePubspec(changes);
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
+ final changesForPackage = changes[package];
+ if (changesForPackage == null || changesForPackage.isEmpty) {
+ continue;
+ }
+ final newPubspecText =
+ _updatePubspecText(package, changesForPackage);
- if (changes.isNotEmpty) {
- writeTextFile(entrypoint.workspaceRoot.pubspecPath, newPubspecText);
+ if (changes.isNotEmpty) {
+ writeTextFile(package.pubspecPath, newPubspecText);
+ }
}
}
_outputChangeSummary(changes);
@@ -184,10 +188,10 @@
///
/// If a dependency has already been updated in [existingChanges], the update
/// will apply on top of that change (eg. preserving the new upper bound).
- Map<PackageRange, PackageRange> tighten(
- Pubspec pubspec,
+ Map<Package, Map<PackageRange, PackageRange>> tighten(
+ Entrypoint entrypoint,
List<PackageId> packages, {
- Map<PackageRange, PackageRange> existingChanges = const {},
+ Map<Package, Map<PackageRange, PackageRange>> existingChanges = const {},
}) {
final result = {...existingChanges};
if (argResults.flag('example') && entrypoint.example != null) {
@@ -195,27 +199,41 @@
'Running `upgrade --tighten` only in `${entrypoint.workspaceRoot.dir}`. Run `$topLevelProgram pub upgrade --tighten --directory example/` separately.',
);
}
- final toTighten = _packagesToUpgrade.isEmpty
- ? [
- ...pubspec.dependencies.values,
- ...pubspec.devDependencies.values,
- ]
- : [
- for (final name in _packagesToUpgrade)
- pubspec.dependencies[name] ?? pubspec.devDependencies[name],
- ].nonNulls;
- for (final range in toTighten) {
- final constraint = (result[range] ?? range).constraint;
+
+ final toTighten = <(Package, PackageRange)>[];
+
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
+ if (_packagesToUpgrade.isEmpty) {
+ for (final range in [
+ ...package.dependencies.values,
+ ...package.devDependencies.values,
+ ]) {
+ toTighten.add((package, range));
+ }
+ } else {
+ for (final packageToUpgrade in _packagesToUpgrade) {
+ final range = package.dependencies[packageToUpgrade] ??
+ package.devDependencies[packageToUpgrade];
+ if (range != null) {
+ toTighten.add((package, range));
+ }
+ }
+ }
+ }
+
+ for (final (package, range) in toTighten) {
+ final changesForPackage = result[package] ??= {};
+ final constraint = (changesForPackage[range] ?? range).constraint;
final resolvedVersion =
packages.firstWhere((p) => p.name == range.name).version;
if (range.source is HostedSource && constraint.isAny) {
- result[range] = range
+ changesForPackage[range] = range
.toRef()
.withConstraint(VersionConstraint.compatibleWith(resolvedVersion));
} else if (constraint is VersionRange) {
final min = constraint.min;
if (min != null && min < resolvedVersion) {
- result[range] = range.toRef().withConstraint(
+ changesForPackage[range] = range.toRef().withConstraint(
VersionRange(
min: resolvedVersion,
max: constraint.max,
@@ -232,27 +250,24 @@
/// Return names of packages to be upgraded, and throws [UsageException] if
/// any package names not in the direct dependencies or dev_dependencies are given.
///
- /// This assumes that either `--major-versions` or `--null-safety` was passed.
+ /// This assumes that `--major-versions` was passed.
List<String> _directDependenciesToUpgrade() {
assert(_upgradeMajorVersions);
- final directDeps = [
- ...entrypoint.workspaceRoot.pubspec.dependencies.keys,
- ...entrypoint.workspaceRoot.pubspec.devDependencies.keys,
- ];
+ final directDeps = {
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) ...[
+ ...package.dependencies.keys,
+ ...package.devDependencies.keys,
+ ],
+ }.toList();
final toUpgrade =
_packagesToUpgrade.isEmpty ? directDeps : _packagesToUpgrade;
// Check that all package names in upgradeOnly are direct-dependencies
final notInDeps = toUpgrade.where((n) => !directDeps.contains(n));
if (toUpgrade.any(notInDeps.contains)) {
- var modeFlag = '';
- if (_upgradeMajorVersions) {
- modeFlag = '--major-versions';
- }
-
usageException('''
-Dependencies specified in `$topLevelProgram pub upgrade $modeFlag <dependencies>` must
+Dependencies specified in `$topLevelProgram pub upgrade --major-versions <dependencies>` must
be direct 'dependencies' or 'dev_dependencies', following packages are not:
- ${notInDeps.join('\n - ')}
@@ -263,15 +278,11 @@
}
Future<void> _runUpgradeMajorVersions() async {
- // TODO(https://github.com/dart-lang/pub/issues/4127): This should operate
- // on all pubspecs in the workspace.
final toUpgrade = _directDependenciesToUpgrade();
-
- final resolvablePubspec = stripVersionBounds(
- entrypoint.workspaceRoot.pubspec,
- stripOnly: toUpgrade,
- );
-
+ final workspace = {
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace)
+ package.dir: package,
+ };
// Solve [resolvablePubspec] in-memory and consolidate the resolved
// versions of the packages into a map for quick searching.
final resolvedPackages = <String, PackageId>{};
@@ -281,10 +292,16 @@
return await resolveVersions(
SolveType.upgrade,
cache,
- Package(
- resolvablePubspec,
+ Package.load(
entrypoint.workspaceRoot.dir,
- entrypoint.workspaceRoot.workspaceChildren,
+ entrypoint.cache.sources,
+ withPubspecOverrides: true,
+ loadPubspec: (
+ path, {
+ expectedName,
+ required withPubspecOverrides,
+ }) =>
+ stripVersionBounds(workspace[path]!.pubspec),
),
);
},
@@ -293,40 +310,42 @@
for (final resolvedPackage in solveResult.packages) {
resolvedPackages[resolvedPackage.name] = resolvedPackage;
}
-
- // Changes to be made to `pubspec.yaml`.
+ final dependencyOverriddenDeps = <String>[];
+ // Changes to be made to `pubspec.yaml` of each package.
// Mapping from original to changed value.
- var changes = <PackageRange, PackageRange>{};
- final declaredHostedDependencies = [
- ...entrypoint.workspaceRoot.pubspec.dependencies.values,
- ...entrypoint.workspaceRoot.pubspec.devDependencies.values,
- ].where((dep) => dep.source is HostedSource);
- for (final dep in declaredHostedDependencies) {
- final resolvedPackage = resolvedPackages[dep.name]!;
- if (!toUpgrade.contains(dep.name)) {
- // If we're not trying to upgrade this package, or it wasn't in the
- // resolution somehow, then we ignore it.
- continue;
- }
+ var changes = <Package, Map<PackageRange, PackageRange>>{};
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
+ final declaredHostedDependencies = [
+ ...package.dependencies.values,
+ ...package.devDependencies.values,
+ ].where((dep) => dep.source is HostedSource);
+ for (final dep in declaredHostedDependencies) {
+ final resolvedPackage = resolvedPackages[dep.name]!;
+ if (!toUpgrade.contains(dep.name)) {
+ // If we're not trying to upgrade this package, or it wasn't in the
+ // resolution somehow, then we ignore it.
+ continue;
+ }
- // Skip [dep] if it has a dependency_override.
- if (entrypoint.workspaceRoot.dependencyOverrides.containsKey(dep.name)) {
- continue;
- }
+ // Skip [dep] if it has a dependency_override.
+ if (entrypoint.workspaceRoot.dependencyOverrides
+ .containsKey(dep.name)) {
+ dependencyOverriddenDeps.add(dep.name);
+ continue;
+ }
- if (dep.constraint.allowsAll(resolvedPackage.version)) {
- // If constraint allows the resolvable version we found, then there is
- // no need to update the `pubspec.yaml`
- continue;
- }
+ if (dep.constraint.allowsAll(resolvedPackage.version)) {
+ // If constraint allows the resolvable version we found, then there is
+ // no need to update the `pubspec.yaml`
+ continue;
+ }
- changes[dep] = dep.toRef().withConstraint(
- VersionConstraint.compatibleWith(
- resolvedPackage.version,
- ),
- );
+ (changes[package] ??= {})[dep] = dep.toRef().withConstraint(
+ VersionConstraint.compatibleWith(resolvedPackage.version),
+ );
+ }
}
- var newPubspecText = _updatePubspec(changes);
+
if (_tighten) {
// Do another solve with the updated constraints to obtain the correct
// versions to tighten to. This should be fast (everything is cached, and
@@ -335,18 +354,21 @@
final solveResult = await resolveVersions(
SolveType.upgrade,
cache,
- Package(
- _updatedPubspec(newPubspecText, entrypoint),
+ Package.load(
entrypoint.workspaceRoot.dir,
- entrypoint.workspaceRoot.workspaceChildren,
+ entrypoint.cache.sources,
+ loadPubspec: (path, {expectedName, required withPubspecOverrides}) {
+ final package = workspace[path]!;
+ final changesForPackage = changes[package] ?? {};
+ return applyChanges(package.pubspec, changesForPackage);
+ },
),
);
changes = tighten(
- entrypoint.workspaceRoot.pubspec,
+ entrypoint,
solveResult.packages,
existingChanges: changes,
);
- newPubspecText = _updatePubspec(changes);
}
// When doing '--majorVersions' for specific packages we try to update other
@@ -358,18 +380,23 @@
_packagesToUpgrade.isEmpty ? SolveType.upgrade : SolveType.get;
if (!_dryRun) {
- if (changes.isNotEmpty) {
- writeTextFile(entrypoint.workspaceRoot.pubspecPath, newPubspecText);
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
+ final changesForPackage = changes[package] ?? {};
+ if (changesForPackage.isNotEmpty) {
+ final newPubspecText = _updatePubspecText(package, changesForPackage);
+ writeTextFile(package.pubspecPath, newPubspecText);
+ }
}
}
-
- await entrypoint
- .withWorkPubspec(_updatedPubspec(newPubspecText, entrypoint))
- .acquireDependencies(
- solveType,
- dryRun: _dryRun,
- precompile: !_dryRun && _precompile,
- );
+ await entrypoint.withUpdatedPubspecs({
+ for (final MapEntry(key: package, value: changesForPackage)
+ in changes.entries)
+ package: applyChanges(package.pubspec, changesForPackage),
+ }).acquireDependencies(
+ solveType,
+ dryRun: _dryRun,
+ precompile: !_dryRun && _precompile,
+ );
_outputChangeSummary(changes);
@@ -387,59 +414,82 @@
_showOfflineWarning();
}
- Pubspec _updatedPubspec(String contents, Entrypoint entrypoint) {
- String? overridesFileContents;
- final overridesPath =
- p.join(entrypoint.workspaceRoot.dir, Pubspec.pubspecOverridesFilename);
- try {
- overridesFileContents = readTextFile(overridesPath);
- } on IOException {
- overridesFileContents = null;
+ Pubspec applyChanges(
+ Pubspec original,
+ Map<PackageRange, PackageRange> changes,
+ ) {
+ final dependencies = {...original.dependencies};
+ final devDependencies = {...original.devDependencies};
+
+ for (final change in changes.values) {
+ if (dependencies[change.name] != null) {
+ dependencies[change.name] = change;
+ } else {
+ devDependencies[change.name] = change;
+ }
}
- return Pubspec.parse(
- contents,
- cache.sources,
- location: Uri.parse(entrypoint.workspaceRoot.pubspecPath),
- overridesFileContents: overridesFileContents,
- overridesLocation: Uri.file(overridesPath),
- containingDescription: RootDescription(entrypoint.workspaceRoot.dir),
+ return original.copyWith(
+ dependencies: dependencies.values,
+ devDependencies: devDependencies.values,
);
}
- /// Updates `pubspec.yaml` with given [changes].
- String _updatePubspec(
+ /// Loads `pubspec.yaml` of [package] and applies [changes] to its
+ /// (dev)-dependencies.
+ ///
+ /// Returns the updated textual representation using yaml-edit to preserve
+ /// structure.
+ String _updatePubspecText(
+ Package package,
Map<PackageRange, PackageRange> changes,
) {
ArgumentError.checkNotNull(changes, 'changes');
- final yamlEditor =
- YamlEditor(readTextFile(entrypoint.workspaceRoot.pubspecPath));
- final deps = entrypoint.workspaceRoot.pubspec.dependencies.keys;
+ final yamlEditor = YamlEditor(readTextFile(package.pubspecPath));
+ final deps = package.dependencies.keys;
for (final change in changes.values) {
final section =
deps.contains(change.name) ? 'dependencies' : 'dev_dependencies';
yamlEditor.update(
[section, change.name],
- pubspecDescription(change, cache, entrypoint.workspaceRoot),
+ pubspecDescription(change, cache, package),
);
}
return yamlEditor.toString();
}
/// Outputs a summary of changes made to `pubspec.yaml`.
- void _outputChangeSummary(Map<PackageRange, PackageRange> changes) {
- ArgumentError.checkNotNull(changes, 'changes');
-
- if (changes.isEmpty) {
- final wouldBe = _dryRun ? 'would be made to' : 'to';
- log.message('\nNo changes $wouldBe pubspec.yaml!');
+ void _outputChangeSummary(
+ Map<Package, Map<PackageRange, PackageRange>> changes,
+ ) {
+ if (entrypoint.workspaceRoot.workspaceChildren.isEmpty) {
+ final changesToWorkspaceRoot = changes[entrypoint.workspaceRoot] ?? {};
+ if (changesToWorkspaceRoot.isEmpty) {
+ final wouldBe = _dryRun ? 'would be made to' : 'to';
+ log.message('\nNo changes $wouldBe pubspec.yaml!');
+ } else {
+ final changed = _dryRun ? 'Would change' : 'Changed';
+ log.message('\n$changed ${changesToWorkspaceRoot.length} '
+ '${pluralize('constraint', changesToWorkspaceRoot.length)} in pubspec.yaml:');
+ changesToWorkspaceRoot.forEach((from, to) {
+ log.message(' ${from.name}: ${from.constraint} -> ${to.constraint}');
+ });
+ }
} else {
- final changed = _dryRun ? 'Would change' : 'Changed';
- log.message('\n$changed ${changes.length} '
- '${pluralize('constraint', changes.length)} in pubspec.yaml:');
- changes.forEach((from, to) {
- log.message(' ${from.name}: ${from.constraint} -> ${to.constraint}');
- });
+ if (changes.isEmpty) {
+ final wouldBe = _dryRun ? 'would be made to' : 'to';
+ log.message('\nNo changes $wouldBe any pubspec.yaml!');
+ }
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) {
+ final changesToPackage = changes[package] ?? {};
+ if (changesToPackage.isEmpty) continue;
+ final changed = _dryRun ? 'Would change' : 'Changed';
+ log.message('\n$changed ${changesToPackage.length} '
+ '${pluralize('constraint', changesToPackage.length)} in ${package.pubspecPath}:');
+ changesToPackage.forEach((from, to) {
+ log.message(' ${from.name}: ${from.constraint} -> ${to.constraint}');
+ });
+ }
}
}
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index bc809a8..861c9df 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -334,16 +334,15 @@
}
}
- /// Creates an entrypoint at the same location, that will use [pubspec] for
- /// resolution of the [workPackage].
- Entrypoint withWorkPubspec(Pubspec pubspec) {
+ /// Creates an entrypoint at the same location, but with each pubspec in
+ /// [updatedPubspec] replacing the with one for the corresponding package.
+ Entrypoint withUpdatedPubspecs(Map<Package, Pubspec> updatedPubspecs) {
final existingPubspecs = <String, Pubspec>{};
// First extract all pubspecs from the workspace.
for (final package in workspaceRoot.transitiveWorkspace) {
- existingPubspecs[package.dir] = package.pubspec;
+ existingPubspecs[package.dir] =
+ updatedPubspecs[package] ?? package.pubspec;
}
- // Then override the one of the workPackage.
- existingPubspecs[p.canonicalize(workPackage.dir)] = pubspec;
final newWorkspaceRoot = Package.load(
workspaceRoot.dir,
cache.sources,
@@ -352,7 +351,7 @@
expectedName,
required withPubspecOverrides,
}) =>
- existingPubspecs[p.canonicalize(dir)] ??
+ existingPubspecs[dir] ??
Pubspec.load(
dir,
cache.sources,
@@ -372,6 +371,12 @@
);
}
+ /// Creates an entrypoint at the same location, that will use [pubspec] for
+ /// resolution of the [workPackage].
+ Entrypoint withWorkPubspec(Pubspec pubspec) {
+ return withUpdatedPubspecs({workPackage: pubspec});
+ }
+
/// Creates an entrypoint given package and lockfile objects.
/// If a SolveResult is already created it can be passed as an optimization.
Entrypoint.global(
diff --git a/lib/src/package.dart b/lib/src/package.dart
index d7f8642..ca6b3f6 100644
--- a/lib/src/package.dart
+++ b/lib/src/package.dart
@@ -64,7 +64,10 @@
while (stack.isNotEmpty) {
final current = stack.removeLast();
yield current;
- stack.addAll(current.workspaceChildren);
+ // Because we pick from the end of the stack, elements are added in
+ // reverse, such that they will be visited in the order they appear in the
+ // list.
+ stack.addAll(current.workspaceChildren.reversed);
}
}
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index a67a894..2a951ad 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -407,6 +407,31 @@
);
}
+ Pubspec copyWith({
+ String? name,
+ Version? version,
+ Iterable<PackageRange>? dependencies,
+ Iterable<PackageRange>? devDependencies,
+ Iterable<PackageRange>? dependencyOverrides,
+ Map? fields,
+ Map<String, SdkConstraint>? sdkConstraints,
+ List<String>? workspace,
+ //this.dependencyOverridesFromOverridesFile = false,
+ Resolution? resolution,
+ }) {
+ return Pubspec(
+ name ?? this.name,
+ version: version ?? this.version,
+ dependencies: dependencies ?? this.dependencies.values,
+ devDependencies: devDependencies ?? this.devDependencies.values,
+ dependencyOverrides:
+ dependencyOverrides ?? this.dependencyOverrides.values,
+ sdkConstraints: sdkConstraints ?? this.sdkConstraints,
+ workspace: workspace ?? this.workspace,
+ resolution: resolution ?? this.resolution,
+ );
+ }
+
/// Ensures that [node] is a mapping.
///
/// If [node] is already a map it is returned.
diff --git a/lib/src/pubspec_utils.dart b/lib/src/pubspec_utils.dart
index 74b2ce8..646114c 100644
--- a/lib/src/pubspec_utils.dart
+++ b/lib/src/pubspec_utils.dart
@@ -13,32 +13,12 @@
/// Returns a new [Pubspec] without [original]'s dev_dependencies.
Pubspec stripDevDependencies(Pubspec original) {
- ArgumentError.checkNotNull(original, 'original');
-
- return Pubspec(
- original.name,
- version: original.version,
- sdkConstraints: original.sdkConstraints,
- dependencies: original.dependencies.values,
- devDependencies: [], // explicitly give empty list, to prevent lazy parsing
- dependencyOverrides: original.dependencyOverrides.values,
- workspace: original.workspace,
- );
+ return original.copyWith(devDependencies: []);
}
/// Returns a new [Pubspec] without [original]'s dependency_overrides.
Pubspec stripDependencyOverrides(Pubspec original) {
- ArgumentError.checkNotNull(original, 'original');
-
- return Pubspec(
- original.name,
- version: original.version,
- sdkConstraints: original.sdkConstraints,
- dependencies: original.dependencies.values,
- devDependencies: original.devDependencies.values,
- dependencyOverrides: [],
- workspace: original.workspace,
- );
+ return original.copyWith(dependencyOverrides: []);
}
/// Returns new pubspec with the same dependencies as [original] but with the
@@ -54,7 +34,6 @@
Iterable<String>? stripOnly,
bool stripLowerBound = false,
}) {
- ArgumentError.checkNotNull(original, 'original');
stripOnly ??= [];
List<PackageRange> stripBounds(
@@ -80,14 +59,9 @@
return result;
}
- return Pubspec(
- original.name,
- version: original.version,
- sdkConstraints: original.sdkConstraints,
+ return original.copyWith(
dependencies: stripBounds(original.dependencies),
devDependencies: stripBounds(original.devDependencies),
- dependencyOverrides: original.dependencyOverrides.values,
- workspace: original.workspace,
);
}
@@ -117,14 +91,9 @@
return result;
}
- return Pubspec(
- original.name,
- version: original.version,
- sdkConstraints: original.sdkConstraints,
+ return original.copyWith(
dependencies: fixBounds(original.dependencies),
devDependencies: fixBounds(original.devDependencies),
- dependencyOverrides: original.dependencyOverrides.values,
- workspace: original.workspace,
);
}
diff --git a/test/workspace_test.dart b/test/workspace_test.dart
index 7bf8638..967c737 100644
--- a/test/workspace_test.dart
+++ b/test/workspace_test.dart
@@ -478,14 +478,6 @@
- myapp any
- both ^1.0.0
-b 1.1.1
-
-dependencies:
-- myapp 1.2.3
- - both ^1.0.0
- - b any
-- both 1.0.0
-
a 1.1.1
dependencies:
@@ -498,6 +490,14 @@
dev dependencies:
- both 1.0.0
+b 1.1.1
+
+dependencies:
+- myapp 1.2.3
+ - both ^1.0.0
+ - b any
+- both 1.0.0
+
transitive dependencies:
- transitive 1.0.0''',
);
@@ -515,14 +515,6 @@
- myapp any
- both ^1.0.0
-b 1.1.1
-
-dependencies:
-- myapp 1.2.3
- - both ^1.0.0
- - b any
-- both 1.0.0
-
a 1.1.1
dependencies:
@@ -532,6 +524,14 @@
- foo 1.0.0
- transitive ^1.0.0
+b 1.1.1
+
+dependencies:
+- myapp 1.2.3
+ - both ^1.0.0
+ - b any
+- both 1.0.0
+
transitive dependencies:
- transitive 1.0.0''',
);
@@ -546,12 +546,6 @@
- b 1.1.1 [myapp both]
- both 1.0.0
-b 1.1.1
-
-dependencies:
-- both 1.0.0
-- myapp 1.2.3 [both b]
-
a 1.1.1
dependencies:
@@ -561,6 +555,12 @@
dev dependencies:
- both 1.0.0
+b 1.1.1
+
+dependencies:
+- both 1.0.0
+- myapp 1.2.3 [both b]
+
transitive dependencies:
- transitive 1.0.0''',
);
@@ -775,4 +775,322 @@
exitCode: DATA,
);
});
+
+ test('`upgrade` upgrades all workspace', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
+ server.serve('bar', '1.0.0');
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^1.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'bar': '^1.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).create();
+ await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'});
+ server.serve('foo', '1.5.0');
+ server.serve('bar', '1.5.0');
+ await pubUpgrade(
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+> bar 1.5.0 (was 1.0.0)
+> foo 1.5.0 (was 1.0.0)''',
+ ),
+ );
+ });
+
+ test('`upgrade --major-versions` upgrades all workspace', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.5.0');
+ server.serve('foo', '2.0.0');
+ server.serve('bar', '1.0.0');
+ server.serve('bar', '2.0.0');
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^1.0.0', 'bar': '1.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '1.5.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).create();
+
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains('+ foo 1.5.0'),
+ );
+ await pubUpgrade(
+ args: ['--major-versions'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+Changed 2 constraints in pubspec.yaml:
+ foo: ^1.0.0 -> ^2.0.0
+ bar: 1.0.0 -> ^2.0.0
+
+Changed 1 constraint in a${s}pubspec.yaml:
+ foo: 1.5.0 -> ^2.0.0''',
+ ),
+ );
+
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^2.0.0', 'bar': '^2.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '^2.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).validate();
+ });
+ test('`upgrade --major-versions foo` upgrades foo in all workspace',
+ () async {
+ final server = await servePackages();
+ server.serve('foo', '1.5.0');
+ server.serve('foo', '2.0.0');
+ server.serve('bar', '1.0.0');
+ server.serve('bar', '2.0.0');
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^1.0.0', 'bar': '1.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '1.5.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).create();
+
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains('+ foo 1.5.0'),
+ );
+ await pubUpgrade(
+ args: ['--major-versions', 'foo'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+Changed 1 constraint in pubspec.yaml:
+ foo: ^1.0.0 -> ^2.0.0
+
+Changed 1 constraint in a${s}pubspec.yaml:
+ foo: 1.5.0 -> ^2.0.0''',
+ ),
+ );
+ // Second run should mention "any pubspec.yaml".
+ await pubUpgrade(
+ args: ['--major-versions', 'foo'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+No changes to any pubspec.yaml!''',
+ ),
+ );
+ await pubUpgrade(
+ args: ['--major-versions', 'foo', '--dry-run'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+No changes would be made to any pubspec.yaml!''',
+ ),
+ );
+
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^2.0.0', 'bar': '1.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '^2.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).validate();
+ });
+
+ test('`upgrade --tighten` updates all workspace', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.5.0');
+ server.serve('bar', '1.5.0');
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^1.0.0', 'bar': '^1.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a', 'b'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '^1.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ dir('b', [
+ libPubspec(
+ 'b',
+ '1.0.0',
+ deps: {'bar': '^1.5.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).create();
+
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains('+ foo 1.5.0'),
+ );
+ await pubUpgrade(
+ args: ['--tighten'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+Changed 2 constraints in pubspec.yaml:
+ foo: ^1.0.0 -> ^1.5.0
+ bar: ^1.0.0 -> ^1.5.0
+
+Changed 1 constraint in a${s}pubspec.yaml:
+ foo: ^1.0.0 -> ^1.5.0''',
+ ),
+ );
+
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^1.5.0', 'bar': '^1.5.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a', 'b'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '^1.5.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ dir('b', [
+ libPubspec(
+ 'b',
+ '1.0.0',
+ deps: {'bar': '^1.5.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).validate();
+ });
+
+ test('`upgrade --major-versions --tighten` updates all workspace', () async {
+ final server = await servePackages();
+ server.serve('foo', '1.5.0');
+ server.serve('bar', '1.5.0');
+ server.serve('foo', '2.0.0');
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ deps: {'foo': '^1.0.0', 'bar': '^1.0.0'},
+ sdk: '^3.7.0',
+ extras: {
+ 'workspace': ['a', 'b'],
+ },
+ ),
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.0.0',
+ deps: {'foo': '^1.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ dir('b', [
+ libPubspec(
+ 'b',
+ '1.0.0',
+ deps: {'bar': '^1.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ ]).create();
+
+ await pubGet(
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains('+ foo 1.5.0'),
+ );
+ await pubUpgrade(
+ args: ['--tighten', '--major-versions'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+Changed 2 constraints in pubspec.yaml:
+ foo: ^1.0.0 -> ^2.0.0
+ bar: ^1.0.0 -> ^1.5.0
+
+Changed 1 constraint in a${s}pubspec.yaml:
+ foo: ^1.0.0 -> ^2.0.0
+
+Changed 1 constraint in b${s}pubspec.yaml:
+ bar: ^1.0.0 -> ^1.5.0''',
+ ),
+ );
+ });
}
+
+final s = p.separator;