Merge remote-tracking branch 'origin/cherry_pick_binstub_fix' into merge-cherry_pick_binstub_fix
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index bf82e2e..6a96ed7 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -24,7 +24,7 @@
matrix:
sdk: [dev]
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
- uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3
with:
sdk: ${{ matrix.sdk }}
@@ -52,7 +52,7 @@
sdk: [dev]
shard: [0, 1, 2, 3, 4, 5, 6]
steps:
- - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
- uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3
with:
sdk: ${{ matrix.sdk }}
diff --git a/lib/src/ascii_tree.dart b/lib/src/ascii_tree.dart
index f5c62fd..58e93f4 100644
--- a/lib/src/ascii_tree.dart
+++ b/lib/src/ascii_tree.dart
@@ -84,7 +84,7 @@
}
// Walk the map recursively and render to a string.
- return fromMap(root);
+ return fromMap(root, startingAtTop: false);
}
/// Draws a tree from a nested map. Given a map like:
@@ -108,9 +108,17 @@
/// barback
///
/// Items with no children should have an empty map as the value.
-String fromMap(Map<String, Map> map) {
+///
+/// If [startingAtTop] is `false`, the tree will be shown as:
+///
+/// |-- analyzer
+/// | '-- args
+/// | | '-- collection
+/// ' '---logging
+/// '---barback
+String fromMap(Map<String, Map> map, {bool startingAtTop = true}) {
var buffer = StringBuffer();
- _draw(buffer, '', null, map);
+ _draw(buffer, '', null, map, depth: startingAtTop ? 0 : 1);
return buffer.toString();
}
@@ -119,10 +127,11 @@
String prefix,
bool isLastChild,
String? name,
+ bool isRoot,
) {
// Print lines.
buffer.write(prefix);
- if (name != null) {
+ if (!isRoot) {
if (isLastChild) {
buffer.write(log.gray(emoji('└── ', "'-- ")));
} else {
@@ -147,15 +156,16 @@
Map<String, Map> children, {
bool showAllChildren = false,
bool isLast = false,
+ required int depth,
}) {
// Don't draw a line for the root node.
- if (name != null) _drawLine(buffer, prefix, isLast, name);
+ if (name != null) _drawLine(buffer, prefix, isLast, name, depth <= 1);
// Recurse to the children.
var childNames = ordered(children.keys);
void drawChild(bool isLastChild, String child) {
- var childPrefix = _getPrefix(name == null, isLast);
+ var childPrefix = _getPrefix(depth <= 1, isLast);
_draw(
buffer,
'$prefix$childPrefix',
@@ -163,6 +173,7 @@
children[child] as Map<String, Map>,
showAllChildren: showAllChildren,
isLast: isLastChild,
+ depth: depth + 1,
);
}
diff --git a/lib/src/command/deps.dart b/lib/src/command/deps.dart
index 404fa61..9258545 100644
--- a/lib/src/command/deps.dart
+++ b/lib/src/command/deps.dart
@@ -89,7 +89,10 @@
usageException('Cannot combine --json and --style.');
}
final visited = <String>[];
- final toVisit = [entrypoint.workspaceRoot.name];
+ final workspacePackageNames = [
+ ...entrypoint.workspaceRoot.transitiveWorkspace.map((p) => p.name),
+ ];
+ final toVisit = [...workspacePackageNames];
final packagesJson = <dynamic>[];
final graph = await entrypoint.packageGraph;
while (toVisit.isNotEmpty) {
@@ -98,14 +101,15 @@
visited.add(current);
final currentPackage =
(await entrypoint.packageGraph).packages[current]!;
- final next = (current == entrypoint.workspaceRoot.name
- ? entrypoint.workspaceRoot.immediateDependencies
+ final isRoot = workspacePackageNames.contains(currentPackage.name);
+ final next = (isRoot
+ ? currentPackage.immediateDependencies
: currentPackage.dependencies)
.keys
.toList();
final dependencyType =
entrypoint.workspaceRoot.pubspec.dependencyType(current);
- final kind = currentPackage == entrypoint.workspaceRoot
+ final kind = isRoot
? 'root'
: (dependencyType == DependencyType.direct
? 'direct'
@@ -159,8 +163,6 @@
buffer.writeln("${log.bold('${sdk.name} SDK')} ${sdk.version}");
}
- buffer.writeln(_labelPackage(entrypoint.workspaceRoot));
-
switch (argResults['style']) {
case 'compact':
await _outputCompact(buffer);
@@ -187,24 +189,32 @@
Future<void> _outputCompact(
StringBuffer buffer,
) async {
- var root = entrypoint.workspaceRoot;
- await _outputCompactPackages(
- 'dependencies',
- root.dependencies.keys,
- buffer,
- );
- if (_includeDev) {
+ var first = true;
+ for (final root in entrypoint.workspaceRoot.transitiveWorkspace) {
+ if (!first) {
+ buffer.write('\n');
+ }
+ first = false;
+
+ buffer.writeln(_labelPackage(root));
await _outputCompactPackages(
- 'dev dependencies',
- root.devDependencies.keys,
+ 'dependencies',
+ root.dependencies.keys,
+ buffer,
+ );
+ if (_includeDev) {
+ await _outputCompactPackages(
+ 'dev dependencies',
+ root.devDependencies.keys,
+ buffer,
+ );
+ }
+ await _outputCompactPackages(
+ 'dependency overrides',
+ root.dependencyOverrides.keys,
buffer,
);
}
- await _outputCompactPackages(
- 'dependency overrides',
- root.dependencyOverrides.keys,
- buffer,
- );
var transitive = await _getTransitiveDependencies();
await _outputCompactPackages('transitive dependencies', transitive, buffer);
@@ -240,20 +250,28 @@
/// For each dependency listed, *that* package's immediate dependencies are
/// shown.
Future<void> _outputList(StringBuffer buffer) async {
- var root = entrypoint.workspaceRoot;
- await _outputListSection('dependencies', root.dependencies.keys, buffer);
- if (_includeDev) {
+ var first = true;
+ for (final root in entrypoint.workspaceRoot.transitiveWorkspace) {
+ if (!first) {
+ buffer.write('\n');
+ }
+ first = false;
+
+ buffer.writeln(_labelPackage(root));
+ await _outputListSection('dependencies', root.dependencies.keys, buffer);
+ if (_includeDev) {
+ await _outputListSection(
+ 'dev dependencies',
+ root.devDependencies.keys,
+ buffer,
+ );
+ }
await _outputListSection(
- 'dev dependencies',
- root.devDependencies.keys,
+ 'dependency overrides',
+ root.dependencyOverrides.keys,
buffer,
);
}
- await _outputListSection(
- 'dependency overrides',
- root.dependencyOverrides.keys,
- buffer,
- );
var transitive = await _getTransitiveDependencies();
if (transitive.isEmpty) return;
@@ -301,57 +319,66 @@
// being added to the tree, and the parent map that will receive that
// package.
var toWalk = Queue<(Package, Map<String, Map>)>();
- var visited = <String>{entrypoint.workspaceRoot.name};
+ var visited = <String>{};
// Start with the root dependencies.
var packageTree = <String, Map>{};
+ final workspacePackageNames = [
+ ...entrypoint.workspaceRoot.transitiveWorkspace.map((p) => p.name),
+ ];
var immediateDependencies =
entrypoint.workspaceRoot.immediateDependencies.keys.toSet();
if (!_includeDev) {
immediateDependencies
.removeAll(entrypoint.workspaceRoot.devDependencies.keys);
}
- for (var name in immediateDependencies) {
+ for (var name in workspacePackageNames) {
toWalk.add((await _getPackage(name), packageTree));
}
// Do a breadth-first walk to the dependency graph.
while (toWalk.isNotEmpty) {
- var pair = toWalk.removeFirst();
- var (package, map) = pair;
+ final (package, map) = toWalk.removeFirst();
- if (visited.contains(package.name)) {
+ if (!visited.add(package.name)) {
map[log.gray('${package.name}...')] = <String, Map>{};
continue;
}
- visited.add(package.name);
-
// Populate the map with this package's dependencies.
var childMap = <String, Map>{};
map[_labelPackage(package)] = childMap;
- for (var dep in package.dependencies.values) {
- toWalk.add((await _getPackage(dep.name), childMap));
+ final isRoot = workspacePackageNames.contains(package.name);
+ final children = [
+ ...isRoot
+ ? package.immediateDependencies.keys
+ : package.dependencies.keys,
+ ];
+ if (!_includeDev) {
+ children.removeWhere(package.devDependencies.keys.contains);
+ }
+ for (var dep in children) {
+ toWalk.add((await _getPackage(dep), childMap));
}
}
-
buffer.write(tree.fromMap(packageTree));
}
String _labelPackage(Package package) =>
'${log.bold(package.name)} ${package.version}';
- /// Gets the names of the non-immediate dependencies of the root package.
+ /// Gets the names of the non-immediate dependencies of the workspace packages.
Future<Set<String>> _getTransitiveDependencies() async {
var transitive = await _getAllDependencies();
- var root = entrypoint.workspaceRoot;
- transitive.remove(root.name);
- transitive.removeAll(root.dependencies.keys);
- if (_includeDev) {
- transitive.removeAll(root.devDependencies.keys);
+ for (final root in entrypoint.workspaceRoot.transitiveWorkspace) {
+ transitive.remove(root.name);
+ transitive.removeAll(root.dependencies.keys);
+ if (_includeDev) {
+ transitive.removeAll(root.devDependencies.keys);
+ }
+ transitive.removeAll(root.dependencyOverrides.keys);
}
- transitive.removeAll(root.dependencyOverrides.keys);
return transitive;
}
@@ -361,8 +388,12 @@
return graph.packages.keys.toSet();
}
- var nonDevDependencies = entrypoint.workspaceRoot.dependencies.keys.toList()
- ..addAll(entrypoint.workspaceRoot.dependencyOverrides.keys);
+ var nonDevDependencies = [
+ for (final package in entrypoint.workspaceRoot.transitiveWorkspace) ...[
+ ...package.dependencies.keys,
+ ...package.dependencyOverrides.keys,
+ ],
+ ];
return nonDevDependencies
.expand(graph.transitiveDependencies)
.map((package) => package.name)
@@ -385,14 +416,14 @@
/// Outputs all executables reachable from [entrypoint].
Future<void> _outputExecutables(StringBuffer buffer) async {
final graph = await entrypoint.packageGraph;
- var packages = [
- entrypoint.workspaceRoot,
- ...(_includeDev
- ? entrypoint.workspaceRoot.immediateDependencies
- : entrypoint.workspaceRoot.dependencies)
- .keys
- .map((name) => graph.packages[name]!),
- ];
+ final packages = {
+ for (final p in entrypoint.workspaceRoot.transitiveWorkspace) ...[
+ graph.packages[p.name]!,
+ ...(_includeDev ? p.immediateDependencies : p.dependencies)
+ .keys
+ .map((name) => graph.packages[name]!),
+ ],
+ };
for (var package in packages) {
var executables = package.executableNames;
diff --git a/pubspec.yaml b/pubspec.yaml
index eb197db..3fe357c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -11,7 +11,7 @@
collection: ^1.18.0
convert: ^3.1.1
crypto: ^3.0.3
- frontend_server_client: ^3.2.0
+ frontend_server_client: ^4.0.0
http: ^1.1.2
http_multi_server: ^3.2.1
http_parser: ^4.0.2
diff --git a/test/ascii_tree_test.dart b/test/ascii_tree_test.dart
index b406f72..115cbc6 100644
--- a/test/ascii_tree_test.dart
+++ b/test/ascii_tree_test.dart
@@ -98,6 +98,6 @@
},
};
- ctx.expectNextSection(tree.fromMap(map));
+ ctx.expectNextSection(tree.fromMap(map, startingAtTop: false));
});
}
diff --git a/test/workspace_test.dart b/test/workspace_test.dart
index 1a98308..cfa4079 100644
--- a/test/workspace_test.dart
+++ b/test/workspace_test.dart
@@ -355,6 +355,194 @@
);
});
+ test('`pub deps` lists dependencies for all members of workspace', () async {
+ final server = await servePackages();
+ server.serve(
+ 'foo',
+ '1.0.0',
+ deps: {'transitive': '^1.0.0'},
+ contents: [
+ dir('bin', [file('foomain.dart')]),
+ ],
+ );
+ server.serve(
+ 'transitive',
+ '1.0.0',
+ contents: [
+ dir('bin', [file('transitivemain.dart')]),
+ ],
+ );
+ server.serve(
+ 'both',
+ '1.0.0',
+ contents: [
+ dir('bin', [file('bothmain.dart')]),
+ ],
+ );
+
+ await dir(appPath, [
+ libPubspec(
+ 'myapp',
+ '1.2.3',
+ extras: {
+ 'workspace': ['pkgs/a', 'pkgs/b'],
+ },
+ deps: {'both': '^1.0.0', 'b': null},
+ sdk: '^3.7.0',
+ ),
+ dir('bin', [file('myappmain.dart')]),
+ dir('pkgs', [
+ dir('a', [
+ libPubspec(
+ 'a',
+ '1.1.1',
+ deps: {'myapp': null, 'foo': '^1.0.0'},
+ devDeps: {'both': '^1.0.0'},
+ resolutionWorkspace: true,
+ ),
+ ]),
+ dir('bin', [file('amain.dart')]),
+ dir('b', [
+ libPubspec(
+ 'b',
+ '1.1.1',
+ deps: {'myapp': null, 'both': '^1.0.0'},
+ resolutionWorkspace: true,
+ ),
+ dir('bin', [file('bmain.dart')]),
+ ]),
+ ]),
+ ]).create();
+ await runPub(
+ args: ['deps'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: contains(
+ '''
+Dart SDK 3.7.0
+a 1.1.1
+├── both...
+├── foo 1.0.0
+│ └── transitive 1.0.0
+└── myapp...
+b 1.1.1
+├── both...
+└── myapp...
+myapp 1.2.3
+├── b...
+└── both 1.0.0''',
+ ),
+ );
+
+ await runPub(
+ args: ['deps', '--style=list', '--dev'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: '''
+Dart SDK 3.7.0
+myapp 1.2.3
+
+dependencies:
+- both 1.0.0
+- b 1.1.1
+ - 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:
+- myapp 1.2.3
+ - both ^1.0.0
+ - b any
+- foo 1.0.0
+ - transitive ^1.0.0
+
+dev dependencies:
+- both 1.0.0
+
+transitive dependencies:
+- transitive 1.0.0''',
+ );
+
+ await runPub(
+ args: ['deps', '--style=list', '--no-dev'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: '''
+Dart SDK 3.7.0
+myapp 1.2.3
+
+dependencies:
+- both 1.0.0
+- b 1.1.1
+ - 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:
+- myapp 1.2.3
+ - both ^1.0.0
+ - b any
+- foo 1.0.0
+ - transitive ^1.0.0
+
+transitive dependencies:
+- transitive 1.0.0''',
+ );
+ await runPub(
+ args: ['deps', '--style=compact'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: '''
+ Dart SDK 3.7.0
+myapp 1.2.3
+
+dependencies:
+- 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:
+- foo 1.0.0 [transitive]
+- myapp 1.2.3 [both b]
+
+dev dependencies:
+- both 1.0.0
+
+transitive dependencies:
+- transitive 1.0.0''',
+ );
+ await runPub(
+ args: ['deps', '--executables'],
+ environment: {'_PUB_TEST_SDK_VERSION': '3.7.0'},
+ output: '''
+myapp:myappmain
+both:bothmain
+b:bmain
+foo:foomain''',
+ );
+ });
+
test('`pub add` acts on the work package', () async {
final server = await servePackages();
server.serve('foo', '1.0.0', sdk: '^3.7.0');