Split transitive dev_dependencies from other transitive dependencies (#2419)
diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index 0e544dd..56a8208 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -74,28 +74,41 @@
var resolvablePubspec = _stripVersionConstraints(upgradePubspec);
- SolveResult upgradableSolveResult;
- SolveResult resolvableSolveResult;
+ List<PackageId> upgradablePackages;
+ List<PackageId> resolvablePackages;
await log.warningsOnlyUnlessTerminal(
() => log.spinner(
'Resolving',
() async {
- upgradableSolveResult = await resolveVersions(
+ upgradablePackages = (await resolveVersions(
SolveType.UPGRADE,
cache,
Package.inMemory(upgradePubspec),
- );
+ ))
+ .packages;
- resolvableSolveResult = await resolveVersions(
+ resolvablePackages = (await resolveVersions(
SolveType.UPGRADE,
cache,
Package.inMemory(resolvablePubspec),
- );
+ ))
+ .packages;
},
),
);
+ final currentPackages = entrypoint.lockFile.packages.values;
+
+ /// The set of all dependencies (direct and transitive) that are in the
+ /// closure of the non-dev dependencies from the root in at least one of
+ /// the current, upgradable and resolvable resolutions.
+ final nonDevDependencies = <String>{
+ ...await nonDevDependencyClosure(entrypoint.root, currentPackages),
+ ...await nonDevDependencyClosure(entrypoint.root, upgradablePackages),
+ ...await nonDevDependencyClosure(entrypoint.root, resolvablePackages)
+ };
+
Future<_PackageDetails> analyzeDependency(PackageRef packageRef) async {
final name = packageRef.name;
final current = (entrypoint.lockFile?.packages ?? {})[name]?.version;
@@ -104,10 +117,10 @@
.map((id) => id.version)
.toList()
..sort(argResults['pre-releases'] ? null : Version.prioritize);
- final upgradable = upgradableSolveResult.packages
+ final upgradable = upgradablePackages
.firstWhere((id) => id.name == name, orElse: () => null)
?.version;
- final resolvable = resolvableSolveResult.packages
+ final resolvable = resolvablePackages
.firstWhere((id) => id.name == name, orElse: () => null)
?.version;
final latest = available.last;
@@ -118,7 +131,7 @@
await _describeVersion(name, source, description, upgradable),
await _describeVersion(name, source, description, resolvable),
await _describeVersion(name, source, description, latest),
- _kind(name, entrypoint));
+ _kind(name, entrypoint, nonDevDependencies));
}
final rows = <_PackageDetails>[];
@@ -135,9 +148,9 @@
...immediateDependencies.map((d) => d.name)
};
for (final id in [
- if (includeDevDependencies) ...entrypoint.lockFile.packages.values,
- ...upgradableSolveResult.packages,
- ...resolvableSolveResult.packages
+ ...currentPackages,
+ ...upgradablePackages,
+ ...resolvablePackages
]) {
final name = id.name;
if (!visited.add(name)) continue;
@@ -181,6 +194,24 @@
.source(source)
.describe(PackageId(name, source, version, description));
}
+
+ /// Computes the closure of the graph of dependencies (not including
+ /// dev_dependencies from [root], given the package versions in [resolution].
+ Future<Set<String>> nonDevDependencyClosure(
+ Package root, Iterable<PackageId> resolution) async {
+ final mapping =
+ Map<String, PackageId>.fromIterable(resolution, key: (id) => id.name);
+ final visited = <String>{root.name};
+ final toVisit = [...root.dependencies.keys];
+ while (toVisit.isNotEmpty) {
+ final name = toVisit.removeLast();
+ if (!visited.add(name)) continue;
+ final id = mapping[name];
+ toVisit.addAll(
+ (await cache.source(id.source).describe(id)).dependencies.keys);
+ }
+ return visited;
+ }
}
Pubspec _stripDevDependencies(Pubspec original) {
@@ -241,6 +272,8 @@
final devRows = rows.where((row) => row.kind == _DependencyKind.dev);
final transitiveRows =
rows.where((row) => row.kind == _DependencyKind.transitive);
+ final devTransitiveRows =
+ rows.where((row) => row.kind == _DependencyKind.devTransitive);
final formattedRows = <List<_FormattedString>>[
['Dependencies', 'Current', 'Upgradable', 'Resolvable', 'Latest']
@@ -261,6 +294,13 @@
: _format('\ntransitive dependencies', log.bold)
],
...await Future.wait(transitiveRows.map(marker)),
+ if (includeDevDependencies)
+ [
+ devTransitiveRows.isEmpty
+ ? _raw('\ntransitive dev_dependencies: all up-to-date')
+ : _format('\ntransitive dev_dependencies', log.bold)
+ ],
+ ...await Future.wait(devTransitiveRows.map(marker)),
];
final columnWidths = <int, int>{};
@@ -400,13 +440,18 @@
}
}
-_DependencyKind _kind(String name, Entrypoint entrypoint) {
+_DependencyKind _kind(
+ String name, Entrypoint entrypoint, Set<String> nonDevTransitive) {
if (entrypoint.root.dependencies.containsKey(name)) {
return _DependencyKind.direct;
} else if (entrypoint.root.devDependencies.containsKey(name)) {
return _DependencyKind.dev;
} else {
- return _DependencyKind.transitive;
+ if (nonDevTransitive.contains(name)) {
+ return _DependencyKind.transitive;
+ } else {
+ return _DependencyKind.devTransitive;
+ }
}
}
@@ -417,8 +462,11 @@
/// Direct dev dependencies.
dev,
- /// Transitive dependencies.
- transitive
+ /// Transitive dependencies of direct dependencies.
+ transitive,
+
+ /// Transitive dependencies needed only by dev_dependencies.
+ devTransitive,
}
_FormattedString _format(String value, Function(String) format, {prefix = ''}) {
diff --git a/test/outdated/goldens/circular_dependencies.txt b/test/outdated/goldens/circular_dependencies.txt
index 24034f2..582817b 100644
--- a/test/outdated/goldens/circular_dependencies.txt
+++ b/test/outdated/goldens/circular_dependencies.txt
@@ -20,6 +20,8 @@
dev_dependencies: all up-to-date
transitive dependencies: all up-to-date
+
+transitive dev_dependencies: all up-to-date
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `pub upgrade`.
@@ -31,6 +33,8 @@
dev_dependencies: all up-to-date
transitive dependencies: all up-to-date
+
+transitive dev_dependencies: all up-to-date
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `pub upgrade`.
@@ -42,6 +46,8 @@
dev_dependencies: all up-to-date
transitive dependencies: all up-to-date
+
+transitive dev_dependencies: all up-to-date
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `pub upgrade`.
@@ -53,6 +59,8 @@
dev_dependencies: all up-to-date
transitive dependencies: all up-to-date
+
+transitive dev_dependencies: all up-to-date
1 upgradable dependency is locked (in pubspec.lock) to an older version.
To update it, use `pub upgrade`.
diff --git a/test/outdated/goldens/mutually_incompatible.txt b/test/outdated/goldens/mutually_incompatible.txt
index 5aa1fcf..9bee742 100644
--- a/test/outdated/goldens/mutually_incompatible.txt
+++ b/test/outdated/goldens/mutually_incompatible.txt
@@ -29,6 +29,8 @@
transitive dependencies: all up-to-date
+transitive dev_dependencies: all up-to-date
+
Dependencies are all on the latest resolvable versions.
Newer versions, while available, are not mutually compatible.
@@ -42,6 +44,8 @@
transitive dependencies: all up-to-date
+transitive dev_dependencies: all up-to-date
+
Dependencies are all on the latest resolvable versions.
Newer versions, while available, are not mutually compatible.
@@ -55,6 +59,8 @@
transitive dependencies: all up-to-date
+transitive dev_dependencies: all up-to-date
+
Dependencies are all on the latest resolvable versions.
Newer versions, while available, are not mutually compatible.
@@ -68,6 +74,8 @@
transitive dependencies: all up-to-date
+transitive dev_dependencies: all up-to-date
+
Dependencies are all on the latest resolvable versions.
Newer versions, while available, are not mutually compatible.
diff --git a/test/outdated/goldens/newer_versions.txt b/test/outdated/goldens/newer_versions.txt
index cfc1dec..ea2f04d 100644
--- a/test/outdated/goldens/newer_versions.txt
+++ b/test/outdated/goldens/newer_versions.txt
@@ -51,6 +51,8 @@
transitive dependencies
transitive *1.2.3 *1.3.0 *1.3.0 2.0.0
transitive2 - - 1.0.0 1.0.0
+
+transitive dev_dependencies
transitive3 - - 1.0.0 1.0.0
3 upgradable dependencies are locked (in pubspec.lock) to older versions.
@@ -70,6 +72,8 @@
transitive dependencies
transitive 1.2.3 1.3.0 1.3.0 2.0.0
transitive2 - - 1.0.0 1.0.0
+
+transitive dev_dependencies
transitive3 - - 1.0.0 1.0.0
3 upgradable dependencies are locked (in pubspec.lock) to older versions.
@@ -91,6 +95,8 @@
transitive dependencies
transitive *1.2.3 *1.3.0 *1.3.0 2.0.0
transitive2 - - 1.0.0 1.0.0
+
+transitive dev_dependencies
transitive3 - - 1.0.0 1.0.0
3 upgradable dependencies are locked (in pubspec.lock) to older versions.
@@ -110,6 +116,8 @@
transitive dependencies
transitive *1.2.3 *1.3.0 *1.3.0 2.0.0
transitive2 - - 1.0.0 1.0.0
+
+transitive dev_dependencies
transitive3 - - 1.0.0 1.0.0
3 upgradable dependencies are locked (in pubspec.lock) to older versions.