Skip to content

Commit e5d317e

Browse files
authored
Split transitive dev_dependencies from other transitive dependencies (flutter#2419)
1 parent 9454d7f commit e5d317e

4 files changed

Lines changed: 88 additions & 16 deletions

File tree

lib/src/command/outdated.dart

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,28 +74,41 @@ class OutdatedCommand extends PubCommand {
7474

7575
var resolvablePubspec = _stripVersionConstraints(upgradePubspec);
7676

77-
SolveResult upgradableSolveResult;
78-
SolveResult resolvableSolveResult;
77+
List<PackageId> upgradablePackages;
78+
List<PackageId> resolvablePackages;
7979

8080
await log.warningsOnlyUnlessTerminal(
8181
() => log.spinner(
8282
'Resolving',
8383
() async {
84-
upgradableSolveResult = await resolveVersions(
84+
upgradablePackages = (await resolveVersions(
8585
SolveType.UPGRADE,
8686
cache,
8787
Package.inMemory(upgradePubspec),
88-
);
88+
))
89+
.packages;
8990

90-
resolvableSolveResult = await resolveVersions(
91+
resolvablePackages = (await resolveVersions(
9192
SolveType.UPGRADE,
9293
cache,
9394
Package.inMemory(resolvablePubspec),
94-
);
95+
))
96+
.packages;
9597
},
9698
),
9799
);
98100

101+
final currentPackages = entrypoint.lockFile.packages.values;
102+
103+
/// The set of all dependencies (direct and transitive) that are in the
104+
/// closure of the non-dev dependencies from the root in at least one of
105+
/// the current, upgradable and resolvable resolutions.
106+
final nonDevDependencies = <String>{
107+
...await nonDevDependencyClosure(entrypoint.root, currentPackages),
108+
...await nonDevDependencyClosure(entrypoint.root, upgradablePackages),
109+
...await nonDevDependencyClosure(entrypoint.root, resolvablePackages)
110+
};
111+
99112
Future<_PackageDetails> analyzeDependency(PackageRef packageRef) async {
100113
final name = packageRef.name;
101114
final current = (entrypoint.lockFile?.packages ?? {})[name]?.version;
@@ -104,10 +117,10 @@ class OutdatedCommand extends PubCommand {
104117
.map((id) => id.version)
105118
.toList()
106119
..sort(argResults['pre-releases'] ? null : Version.prioritize);
107-
final upgradable = upgradableSolveResult.packages
120+
final upgradable = upgradablePackages
108121
.firstWhere((id) => id.name == name, orElse: () => null)
109122
?.version;
110-
final resolvable = resolvableSolveResult.packages
123+
final resolvable = resolvablePackages
111124
.firstWhere((id) => id.name == name, orElse: () => null)
112125
?.version;
113126
final latest = available.last;
@@ -118,7 +131,7 @@ class OutdatedCommand extends PubCommand {
118131
await _describeVersion(name, source, description, upgradable),
119132
await _describeVersion(name, source, description, resolvable),
120133
await _describeVersion(name, source, description, latest),
121-
_kind(name, entrypoint));
134+
_kind(name, entrypoint, nonDevDependencies));
122135
}
123136

124137
final rows = <_PackageDetails>[];
@@ -135,9 +148,9 @@ class OutdatedCommand extends PubCommand {
135148
...immediateDependencies.map((d) => d.name)
136149
};
137150
for (final id in [
138-
if (includeDevDependencies) ...entrypoint.lockFile.packages.values,
139-
...upgradableSolveResult.packages,
140-
...resolvableSolveResult.packages
151+
...currentPackages,
152+
...upgradablePackages,
153+
...resolvablePackages
141154
]) {
142155
final name = id.name;
143156
if (!visited.add(name)) continue;
@@ -181,6 +194,24 @@ class OutdatedCommand extends PubCommand {
181194
.source(source)
182195
.describe(PackageId(name, source, version, description));
183196
}
197+
198+
/// Computes the closure of the graph of dependencies (not including
199+
/// dev_dependencies from [root], given the package versions in [resolution].
200+
Future<Set<String>> nonDevDependencyClosure(
201+
Package root, Iterable<PackageId> resolution) async {
202+
final mapping =
203+
Map<String, PackageId>.fromIterable(resolution, key: (id) => id.name);
204+
final visited = <String>{root.name};
205+
final toVisit = [...root.dependencies.keys];
206+
while (toVisit.isNotEmpty) {
207+
final name = toVisit.removeLast();
208+
if (!visited.add(name)) continue;
209+
final id = mapping[name];
210+
toVisit.addAll(
211+
(await cache.source(id.source).describe(id)).dependencies.keys);
212+
}
213+
return visited;
214+
}
184215
}
185216

186217
Pubspec _stripDevDependencies(Pubspec original) {
@@ -241,6 +272,8 @@ Future<void> _outputHuman(List<_PackageDetails> rows,
241272
final devRows = rows.where((row) => row.kind == _DependencyKind.dev);
242273
final transitiveRows =
243274
rows.where((row) => row.kind == _DependencyKind.transitive);
275+
final devTransitiveRows =
276+
rows.where((row) => row.kind == _DependencyKind.devTransitive);
244277

245278
final formattedRows = <List<_FormattedString>>[
246279
['Dependencies', 'Current', 'Upgradable', 'Resolvable', 'Latest']
@@ -261,6 +294,13 @@ Future<void> _outputHuman(List<_PackageDetails> rows,
261294
: _format('\ntransitive dependencies', log.bold)
262295
],
263296
...await Future.wait(transitiveRows.map(marker)),
297+
if (includeDevDependencies)
298+
[
299+
devTransitiveRows.isEmpty
300+
? _raw('\ntransitive dev_dependencies: all up-to-date')
301+
: _format('\ntransitive dev_dependencies', log.bold)
302+
],
303+
...await Future.wait(devTransitiveRows.map(marker)),
264304
];
265305

266306
final columnWidths = <int, int>{};
@@ -400,13 +440,18 @@ class _PackageDetails implements Comparable<_PackageDetails> {
400440
}
401441
}
402442

403-
_DependencyKind _kind(String name, Entrypoint entrypoint) {
443+
_DependencyKind _kind(
444+
String name, Entrypoint entrypoint, Set<String> nonDevTransitive) {
404445
if (entrypoint.root.dependencies.containsKey(name)) {
405446
return _DependencyKind.direct;
406447
} else if (entrypoint.root.devDependencies.containsKey(name)) {
407448
return _DependencyKind.dev;
408449
} else {
409-
return _DependencyKind.transitive;
450+
if (nonDevTransitive.contains(name)) {
451+
return _DependencyKind.transitive;
452+
} else {
453+
return _DependencyKind.devTransitive;
454+
}
410455
}
411456
}
412457

@@ -417,8 +462,11 @@ enum _DependencyKind {
417462
/// Direct dev dependencies.
418463
dev,
419464

420-
/// Transitive dependencies.
421-
transitive
465+
/// Transitive dependencies of direct dependencies.
466+
transitive,
467+
468+
/// Transitive dependencies needed only by dev_dependencies.
469+
devTransitive,
422470
}
423471

424472
_FormattedString _format(String value, Function(String) format, {prefix = ''}) {

test/outdated/goldens/circular_dependencies.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ foo *1.2.3 1.3.0 1.3.0 1.3.0
2020
dev_dependencies: all up-to-date
2121

2222
transitive dependencies: all up-to-date
23+
24+
transitive dev_dependencies: all up-to-date
2325
1 upgradable dependency is locked (in pubspec.lock) to an older version.
2426
To update it, use `pub upgrade`.
2527

@@ -31,6 +33,8 @@ foo 1.2.3 1.3.0 1.3.0 1.3.0
3133
dev_dependencies: all up-to-date
3234

3335
transitive dependencies: all up-to-date
36+
37+
transitive dev_dependencies: all up-to-date
3438
1 upgradable dependency is locked (in pubspec.lock) to an older version.
3539
To update it, use `pub upgrade`.
3640

@@ -42,6 +46,8 @@ foo *1.2.3 1.3.0 1.3.0 1.3.0
4246
dev_dependencies: all up-to-date
4347

4448
transitive dependencies: all up-to-date
49+
50+
transitive dev_dependencies: all up-to-date
4551
1 upgradable dependency is locked (in pubspec.lock) to an older version.
4652
To update it, use `pub upgrade`.
4753

@@ -53,6 +59,8 @@ foo *1.2.3 1.3.0 1.3.0 1.3.0
5359
dev_dependencies: all up-to-date
5460

5561
transitive dependencies: all up-to-date
62+
63+
transitive dev_dependencies: all up-to-date
5664
1 upgradable dependency is locked (in pubspec.lock) to an older version.
5765
To update it, use `pub upgrade`.
5866

test/outdated/goldens/mutually_incompatible.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ dev_dependencies: all up-to-date
2929

3030
transitive dependencies: all up-to-date
3131

32+
transitive dev_dependencies: all up-to-date
33+
3234
Dependencies are all on the latest resolvable versions.
3335
Newer versions, while available, are not mutually compatible.
3436

@@ -42,6 +44,8 @@ dev_dependencies: all up-to-date
4244

4345
transitive dependencies: all up-to-date
4446

47+
transitive dev_dependencies: all up-to-date
48+
4549
Dependencies are all on the latest resolvable versions.
4650
Newer versions, while available, are not mutually compatible.
4751

@@ -55,6 +59,8 @@ dev_dependencies: all up-to-date
5559

5660
transitive dependencies: all up-to-date
5761

62+
transitive dev_dependencies: all up-to-date
63+
5864
Dependencies are all on the latest resolvable versions.
5965
Newer versions, while available, are not mutually compatible.
6066

@@ -68,6 +74,8 @@ dev_dependencies: all up-to-date
6874

6975
transitive dependencies: all up-to-date
7076

77+
transitive dev_dependencies: all up-to-date
78+
7179
Dependencies are all on the latest resolvable versions.
7280
Newer versions, while available, are not mutually compatible.
7381

test/outdated/goldens/newer_versions.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ builder *1.2.3 *1.3.0 2.0.0 2.0.0
5151
transitive dependencies
5252
transitive *1.2.3 *1.3.0 *1.3.0 2.0.0
5353
transitive2 - - 1.0.0 1.0.0
54+
55+
transitive dev_dependencies
5456
transitive3 - - 1.0.0 1.0.0
5557

5658
3 upgradable dependencies are locked (in pubspec.lock) to older versions.
@@ -70,6 +72,8 @@ builder 1.2.3 1.3.0 2.0.0 2.0.0
7072
transitive dependencies
7173
transitive 1.2.3 1.3.0 1.3.0 2.0.0
7274
transitive2 - - 1.0.0 1.0.0
75+
76+
transitive dev_dependencies
7377
transitive3 - - 1.0.0 1.0.0
7478

7579
3 upgradable dependencies are locked (in pubspec.lock) to older versions.
@@ -91,6 +95,8 @@ builder *1.2.3 *1.3.0 2.0.0 2.0.0
9195
transitive dependencies
9296
transitive *1.2.3 *1.3.0 *1.3.0 2.0.0
9397
transitive2 - - 1.0.0 1.0.0
98+
99+
transitive dev_dependencies
94100
transitive3 - - 1.0.0 1.0.0
95101

96102
3 upgradable dependencies are locked (in pubspec.lock) to older versions.
@@ -110,6 +116,8 @@ builder *1.2.3 *1.3.0 *2.0.0 3.0.0-alpha
110116
transitive dependencies
111117
transitive *1.2.3 *1.3.0 *1.3.0 2.0.0
112118
transitive2 - - 1.0.0 1.0.0
119+
120+
transitive dev_dependencies
113121
transitive3 - - 1.0.0 1.0.0
114122

115123
3 upgradable dependencies are locked (in pubspec.lock) to older versions.

0 commit comments

Comments
 (0)