From c9f521d49567f2603a33e5c0a9b88a0977a2a6b7 Mon Sep 17 00:00:00 2001 From: Anton Moiseev Date: Fri, 24 Jun 2016 14:21:58 +0300 Subject: [PATCH 1/2] Add "pub run --list" command to show all available executables. See #1323 --- lib/src/command/run.dart | 63 ++++++++ ...errors_if_no_executable_is_given_test.dart | 1 + .../errors_if_path_in_dependency_test.dart | 1 + test/run/list_test.dart | 134 ++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 test/run/list_test.dart diff --git a/lib/src/command/run.dart b/lib/src/command/run.dart index ec26fbfc1..26ca3026d 100644 --- a/lib/src/command/run.dart +++ b/lib/src/command/run.dart @@ -10,6 +10,8 @@ import 'package:path/path.dart' as p; import '../command.dart'; import '../executable.dart'; import '../io.dart'; +import '../log.dart' as log; +import '../package.dart'; import '../utils.dart'; /// Handles the `run` pub command. @@ -22,6 +24,8 @@ class RunCommand extends PubCommand { RunCommand() { argParser.addFlag("checked", abbr: "c", help: "Enable runtime type checks and assertions."); + argParser.addFlag('list', negatable: false, + help: 'List all available executables.'); argParser.addOption("mode", help: 'Mode to run transformers in.\n' '(defaults to "release" for dependencies, "debug" for ' @@ -29,6 +33,11 @@ class RunCommand extends PubCommand { } Future run() async { + if (argResults['list']) { + _listExecutables(); + return; + } + if (argResults.rest.isEmpty) { usageException("Must specify an executable to run."); } @@ -69,4 +78,58 @@ class RunCommand extends PubCommand { checked: argResults['checked'], mode: mode); await flushThenExit(exitCode); } + + /// Lists all executables reachable from [entrypoint]. + void _listExecutables() { + var packages = [] + ..add(entrypoint.root) + ..addAll(entrypoint.root.immediateDependencies + .map((dep) => entrypoint.packageGraph.packages[dep.name])); + + packages.forEach((Package package) { + var executables = _listExecutablesFor(package); + if (executables.isNotEmpty) { + log.message(_formatExecutables(package.name, executables.toList())); + } + }); + } + + /// Lists all Dart files in the `bin` directory of the [package]. + /// + /// Returns file names without extensions. + List _listExecutablesFor(Package package) { + return package + .listFiles(beneath: 'bin', recursive: false) + .where((executable) => p.extension(executable) == '.dart') + .map(p.basenameWithoutExtension); + } + + /// Returns formatted string that lists [executables] for the [packageName]. + /// Examples: + /// + /// _formatExecutables('foo', ['foo']) // -> 'foo' + /// _formatExecutables('foo', ['bar']) // -> 'foo:bar' + /// _formatExecutables('foo', ['bar', 'foo']) // -> 'foo: foo, bar' + /// + /// Note the leading space before first executable and sorting order in the + /// last example. + String _formatExecutables(String packageName, List executables) { + if (executables.length == 1) { + // If executable matches the package name omit the name of executable in + // the output. + return executables.first != packageName + ? '${log.bold(packageName)}:${executables.first}' + : log.bold(packageName); + } else { + // Sort executables to make executable that matches the package name to be + // the first in the list. + executables.sort((e1, e2) { + if (e1 == packageName) return -1; + else if (e2 == packageName) return 1; + else return e1.compareTo(e2); + }); + + return '${log.bold(packageName)}: ${executables.join(', ')}'; + } + } } diff --git a/test/run/errors_if_no_executable_is_given_test.dart b/test/run/errors_if_no_executable_is_given_test.dart index 661009052..694d99567 100644 --- a/test/run/errors_if_no_executable_is_given_test.dart +++ b/test/run/errors_if_no_executable_is_given_test.dart @@ -20,6 +20,7 @@ Must specify an executable to run. Usage: pub run [args...] -h, --help Print this usage information. -c, --[no-]checked Enable runtime type checks and assertions. + --list List all available executables. --mode Mode to run transformers in. (defaults to "release" for dependencies, "debug" for entrypoint) diff --git a/test/run/errors_if_path_in_dependency_test.dart b/test/run/errors_if_path_in_dependency_test.dart index 55f8cd7fd..860b50165 100644 --- a/test/run/errors_if_path_in_dependency_test.dart +++ b/test/run/errors_if_path_in_dependency_test.dart @@ -27,6 +27,7 @@ Cannot run an executable in a subdirectory of a dependency. Usage: pub run [args...] -h, --help Print this usage information. -c, --[no-]checked Enable runtime type checks and assertions. + --list List all available executables. --mode Mode to run transformers in. (defaults to "release" for dependencies, "debug" for entrypoint) diff --git a/test/run/list_test.dart b/test/run/list_test.dart new file mode 100644 index 000000000..3de918747 --- /dev/null +++ b/test/run/list_test.dart @@ -0,0 +1,134 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import '../descriptor.dart' as d; +import '../test_pub.dart'; + +main() { + integration("lists executables in entrypoint's bin", () { + d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', [ + d.file('foo.dart'), + d.file('bar.dart') + ]) + ]).create(); + + schedulePub(args: ['run', '--list'], output: 'myapp: bar, foo'); + }); + + integration("doesn't list executables in bin's sub directories", () { + d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', [ + d.file('foo.dart'), + d.dir('sub', [ + d.file('bar.dart') + ]) + ]) + ]).create(); + + schedulePub(args: ['run', '--list'], output: 'myapp:foo'); + }); + + integration('lists only Dart files', () { + d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', [ + d.file('foo.dart'), + d.file('bar.sh') + ]) + ]).create(); + + schedulePub(args: ['run', '--list'], output: 'myapp:foo'); + }); + + integration('lists executables from a dependency', () { + d.dir('foo', [ + d.libPubspec('foo', '1.0.0'), + d.dir('bin', [ + d.file('bar.dart') + ]) + ]).create(); + + d.dir(appPath, [ + d.appPubspec({ + 'foo': {'path': '../foo'} + }) + ]).create(); + + pubGet(); + schedulePub(args: ['run', '--list'], output: 'foo:bar'); + }); + + integration('lists executables only from immediate dependencies', () { + d.dir(appPath, [ + d.appPubspec({ + 'foo': {'path': '../foo'} + }) + ]).create(); + + d.dir('foo', [ + d.libPubspec('foo', '1.0.0', deps: { + 'baz': {'path': '../baz'} + }), + d.dir('bin', [ + d.file('bar.dart') + ]) + ]).create(); + + d.dir('baz', [ + d.libPubspec('baz', '1.0.0'), + d.dir('bin', [ + d.file('qux.dart') + ]) + ]).create(); + + + pubGet(); + schedulePub(args: ['run', '--list'], output: 'foo:bar'); + }); + + integration('applies formatting before printing executables', () { + d.dir(appPath, [ + d.appPubspec({ + 'foo': {'path': '../foo'}, + 'bar': {'path': '../bar'} + }), + d.dir('bin', [ + d.file('myapp.dart') + ]) + ]).create(); + + d.dir('foo', [ + d.libPubspec('foo', '1.0.0'), + d.dir('bin', [ + d.file('baz.dart'), + d.file('foo.dart') + ]) + ]).create(); + + d.dir('bar', [ + d.libPubspec('bar', '1.0.0'), + d.dir('bin', [ + d.file('qux.dart') + ]) + ]).create(); + + pubGet(); + schedulePub(args: ['run', '--list'], output: ''' +myapp +bar:qux +foo: foo, baz +'''); + }); + + integration('prints blank line when no executables found', () { + d.dir(appPath, [ + d.appPubspec() + ]).create(); + + schedulePub(args: ['run', '--list'], output: '\n'); + }); +} From 9c3d6e060add3a9a734c5b218e567acf4fa43358 Mon Sep 17 00:00:00 2001 From: Alex Khomchenko Date: Tue, 1 Aug 2017 20:46:05 -0700 Subject: [PATCH 2/2] added "pub deps --executables" command to show all available executables * removed "run --list" command * buffer is used to output executables * tests were adapted to verify --dev/--no-dev flag --- lib/src/command/deps.dart | 101 +++++++- lib/src/command/run.dart | 63 ----- test/deps/executables_test.dart | 225 ++++++++++++++++++ ...errors_if_no_executable_is_given_test.dart | 1 - .../errors_if_path_in_dependency_test.dart | 1 - test/run/list_test.dart | 134 ----------- 6 files changed, 314 insertions(+), 211 deletions(-) create mode 100644 test/deps/executables_test.dart delete mode 100644 test/run/list_test.dart diff --git a/lib/src/command/deps.dart b/lib/src/command/deps.dart index f931c5985..d8a86a794 100644 --- a/lib/src/command/deps.dart +++ b/lib/src/command/deps.dart @@ -4,12 +4,26 @@ import 'dart:collection'; +import 'package:analyzer/analyzer.dart' as analyzer; +import 'package:path/path.dart' as p; + import '../ascii_tree.dart' as tree; import '../command.dart'; +import '../dart.dart'; import '../log.dart' as log; import '../package.dart'; import '../utils.dart'; +/// Returns `true` if [path] looks like a Dart entrypoint. +bool _isDartExecutable(String path) { + try { + var unit = analyzer.parseDartFile(path, parseFunctionBodies: false); + return isEntrypoint(unit); + } on analyzer.AnalyzerErrorGroup { + return false; + } +} + /// Handles the `deps` pub command. class DepsCommand extends PubCommand { String get name => "deps"; @@ -36,6 +50,9 @@ class DepsCommand extends PubCommand { negatable: true, help: "Whether to include dev dependencies.", defaultsTo: true); + + argParser.addFlag("executables", + negatable: false, help: "List all available executables."); } void run() { @@ -44,18 +61,22 @@ class DepsCommand extends PubCommand { _buffer = new StringBuffer(); - _buffer.writeln(_labelPackage(entrypoint.root)); - - switch (argResults["style"]) { - case "compact": - _outputCompact(); - break; - case "list": - _outputList(); - break; - case "tree": - _outputTree(); - break; + if (argResults['executables']) { + _outputExecutables(); + } else { + _buffer.writeln(_labelPackage(entrypoint.root)); + + switch (argResults["style"]) { + case "compact": + _outputCompact(); + break; + case "list": + _outputList(); + break; + case "tree": + _outputTree(); + break; + } } log.message(_buffer); @@ -231,4 +252,60 @@ class DepsCommand extends PubCommand { 'was generated, please run "pub get" again.'); return null; } + + /// Outputs all executables reachable from [entrypoint]. + void _outputExecutables() { + var packages = [] + ..add(entrypoint.root) + ..addAll((_includeDev + ? entrypoint.root.immediateDependencies + : entrypoint.root.dependencies) + .map((dep) => entrypoint.packageGraph.packages[dep.name])); + + for (var package in packages) { + var executables = _getExecutablesFor(package); + if (executables.isNotEmpty) { + _buffer.writeln(_formatExecutables(package.name, executables.toList())); + } + } + } + + /// Lists all Dart files in the `bin` directory of the [package]. + /// + /// Returns file names without extensions. + List _getExecutablesFor(Package package) => package.executableIds + .where((e) => _isDartExecutable(p.absolute(package.dir, e.path))) + .map((e) => p.basenameWithoutExtension(e.path)); + + /// Returns formatted string that lists [executables] for the [packageName]. + /// Examples: + /// + /// _formatExecutables('foo', ['foo']) // -> 'foo' + /// _formatExecutables('foo', ['bar']) // -> 'foo:bar' + /// _formatExecutables('foo', ['bar', 'foo']) // -> 'foo: foo, bar' + /// + /// Note the leading space before first executable and sorting order in the + /// last example. + String _formatExecutables(String packageName, List executables) { + if (executables.length == 1) { + // If executable matches the package name omit the name of executable in + // the output. + return executables.first != packageName + ? '${packageName}:${log.bold(executables.first)}' + : log.bold(executables.first); + } + + // Sort executables to make executable that matches the package name to be + // the first in the list. + executables.sort((e1, e2) { + if (e1 == packageName) + return -1; + else if (e2 == packageName) + return 1; + else + return e1.compareTo(e2); + }); + + return '${packageName}: ${executables.map(log.bold).join(', ')}'; + } } diff --git a/lib/src/command/run.dart b/lib/src/command/run.dart index 02fa32611..5aa24c67a 100644 --- a/lib/src/command/run.dart +++ b/lib/src/command/run.dart @@ -10,8 +10,6 @@ import 'package:path/path.dart' as p; import '../command.dart'; import '../executable.dart'; import '../io.dart'; -import '../log.dart' as log; -import '../package.dart'; import '../utils.dart'; /// Handles the `run` pub command. @@ -24,8 +22,6 @@ class RunCommand extends PubCommand { RunCommand() { argParser.addFlag("checked", abbr: "c", help: "Enable runtime type checks and assertions."); - argParser.addFlag('list', negatable: false, - help: 'List all available executables.'); argParser.addOption("mode", help: 'Mode to run transformers in.\n' '(defaults to "release" for dependencies, "debug" for ' @@ -33,11 +29,6 @@ class RunCommand extends PubCommand { } Future run() async { - if (argResults['list']) { - _listExecutables(); - return; - } - if (argResults.rest.isEmpty) { usageException("Must specify an executable to run."); } @@ -78,58 +69,4 @@ class RunCommand extends PubCommand { checked: argResults['checked'], mode: mode); await flushThenExit(exitCode); } - - /// Lists all executables reachable from [entrypoint]. - void _listExecutables() { - var packages = [] - ..add(entrypoint.root) - ..addAll(entrypoint.root.immediateDependencies - .map((dep) => entrypoint.packageGraph.packages[dep.name])); - - packages.forEach((Package package) { - var executables = _listExecutablesFor(package); - if (executables.isNotEmpty) { - log.message(_formatExecutables(package.name, executables.toList())); - } - }); - } - - /// Lists all Dart files in the `bin` directory of the [package]. - /// - /// Returns file names without extensions. - List _listExecutablesFor(Package package) { - return package - .listFiles(beneath: 'bin', recursive: false) - .where((executable) => p.extension(executable) == '.dart') - .map(p.basenameWithoutExtension); - } - - /// Returns formatted string that lists [executables] for the [packageName]. - /// Examples: - /// - /// _formatExecutables('foo', ['foo']) // -> 'foo' - /// _formatExecutables('foo', ['bar']) // -> 'foo:bar' - /// _formatExecutables('foo', ['bar', 'foo']) // -> 'foo: foo, bar' - /// - /// Note the leading space before first executable and sorting order in the - /// last example. - String _formatExecutables(String packageName, List executables) { - if (executables.length == 1) { - // If executable matches the package name omit the name of executable in - // the output. - return executables.first != packageName - ? '${log.bold(packageName)}:${executables.first}' - : log.bold(packageName); - } else { - // Sort executables to make executable that matches the package name to be - // the first in the list. - executables.sort((e1, e2) { - if (e1 == packageName) return -1; - else if (e2 == packageName) return 1; - else return e1.compareTo(e2); - }); - - return '${log.bold(packageName)}: ${executables.join(', ')}'; - } - } } diff --git a/test/deps/executables_test.dart b/test/deps/executables_test.dart new file mode 100644 index 000000000..317ab4970 --- /dev/null +++ b/test/deps/executables_test.dart @@ -0,0 +1,225 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:test/test.dart'; + +import '../descriptor.dart' as d; +import '../test_pub.dart'; + +const _validMain = 'main() {}'; + +main() { + _testExecutablesOutput(output, {bool dev: true}) => () async { + await pubGet(); + await runPub( + args: ['deps', '--executables'] + ..addAll(dev ? ['--dev'] : ['--no-dev']), + output: output); + }; + + _testAllDepsOutput(output) => _testExecutablesOutput(output); + _testNonDevDepsOutput(output) => _testExecutablesOutput(output, dev: false); + + group("lists nothing when no executables found", () { + setUp(() async { + await d.dir(appPath, [d.appPubspec()]).create(); + }); + + test("all dependencies", _testAllDepsOutput('\n')); + test("non-dev dependencies", _testNonDevDepsOutput('\n')); + }); + + group("skips non-Dart executables", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', [d.file('foo.py'), d.file('bar.sh')]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('\n')); + test("non-dev dependencies", _testNonDevDepsOutput('\n')); + }); + + group("skips Dart executables which are not parsable", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', [d.file('foo.dart', 'main() {')]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('\n')); + test("non-dev dependencies", _testNonDevDepsOutput('\n')); + }); + + group("skips Dart executables without entrypoints", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec(), + d.dir( + 'bin', [d.file('foo.dart'), d.file('bar.dart', 'main(x, y, z) {}')]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('\n')); + test("non-dev dependencies", _testNonDevDepsOutput('\n')); + }); + + group("lists valid Dart executables with entrypoints", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', + [d.file('foo.dart', _validMain), d.file('bar.dart', _validMain)]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('myapp: bar, foo')); + test("non-dev dependencies", _testNonDevDepsOutput('myapp: bar, foo')); + }); + + group("skips executables in sub directories", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec(), + d.dir('bin', [ + d.file('foo.dart', _validMain), + d.dir('sub', [d.file('bar.dart', _validMain)]) + ]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('myapp:foo')); + test("non-dev dependencies", _testNonDevDepsOutput('myapp:foo')); + }); + + group("lists executables from a dependency", () { + setUp(() async { + await d.dir('foo', [ + d.libPubspec('foo', '1.0.0'), + d.dir('bin', [d.file('bar.dart', _validMain)]) + ]).create(); + + await d.dir(appPath, [ + d.appPubspec({ + 'foo': {'path': '../foo'} + }) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('foo:bar')); + test("non-dev dependencies", _testNonDevDepsOutput('foo:bar')); + }); + + group("lists executables only from immediate dependencies", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec({ + 'foo': {'path': '../foo'} + }) + ]).create(); + + await d.dir('foo', [ + d.libPubspec('foo', '1.0.0', deps: { + 'baz': {'path': '../baz'} + }), + d.dir('bin', [d.file('bar.dart', _validMain)]) + ]).create(); + + await d.dir('baz', [ + d.libPubspec('baz', '1.0.0'), + d.dir('bin', [d.file('qux.dart', _validMain)]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput('foo:bar')); + test("non-dev dependencies", _testNonDevDepsOutput('foo:bar')); + }); + + group("applies formatting before printing executables", () { + setUp(() async { + await d.dir(appPath, [ + d.appPubspec({ + 'foo': {'path': '../foo'}, + 'bar': {'path': '../bar'} + }), + d.dir('bin', [d.file('myapp.dart', _validMain)]) + ]).create(); + + await d.dir('foo', [ + d.libPubspec('foo', '1.0.0'), + d.dir('bin', + [d.file('baz.dart', _validMain), d.file('foo.dart', _validMain)]) + ]).create(); + + await d.dir('bar', [ + d.libPubspec('bar', '1.0.0'), + d.dir('bin', [d.file('qux.dart', _validMain)]) + ]).create(); + }); + + test("all dependencies", _testAllDepsOutput(''' + myapp + bar:qux + foo: foo, baz''')); + test("non-dev dependencies", _testNonDevDepsOutput(''' + myapp + bar:qux + foo: foo, baz''')); + }); + + group("dev dependencies", () { + setUp(() async { + await d.dir('foo', [ + d.libPubspec('foo', '1.0.0'), + d.dir('bin', [d.file('bar.dart', _validMain)]) + ]).create(); + + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + 'dev_dependencies': { + 'foo': {'path': '../foo'} + } + }) + ]).create(); + }); + + test("are listed if --dev flag is set", _testAllDepsOutput('foo:bar')); + test("are skipped if --no-dev flag is set", _testNonDevDepsOutput('\n')); + }); + + group("overriden dependencies executables", () { + setUp(() async { + await d.dir('foo-1.0', [ + d.libPubspec('foo', '1.0.0'), + d.dir('bin', [d.file('bar.dart', _validMain)]) + ]).create(); + + await d.dir('foo-2.0', [ + d.libPubspec('foo', '2.0.0'), + d.dir('bin', + [d.file('bar.dart', _validMain), d.file('baz.dart', _validMain)]) + ]).create(); + + await d.dir(appPath, [ + d.pubspec({ + 'name': 'myapp', + 'dependencies': { + 'foo': {'path': '../foo-1.0'} + }, + 'dependency_overrides': { + 'foo': {'path': '../foo-2.0'} + } + }) + ]).create(); + }); + + test( + 'are listed if --dev flag is set', _testAllDepsOutput('foo: bar, baz')); + test('are listed if --no-dev flag is set', + _testNonDevDepsOutput('foo: bar, baz')); + }); +} diff --git a/test/run/errors_if_no_executable_is_given_test.dart b/test/run/errors_if_no_executable_is_given_test.dart index 4f54be307..15c84669e 100644 --- a/test/run/errors_if_no_executable_is_given_test.dart +++ b/test/run/errors_if_no_executable_is_given_test.dart @@ -19,7 +19,6 @@ Must specify an executable to run. Usage: pub run [args...] -h, --help Print this usage information. -c, --[no-]checked Enable runtime type checks and assertions. - --list List all available executables. --mode Mode to run transformers in. (defaults to "release" for dependencies, "debug" for entrypoint) diff --git a/test/run/errors_if_path_in_dependency_test.dart b/test/run/errors_if_path_in_dependency_test.dart index f94bcd28a..3190f43d2 100644 --- a/test/run/errors_if_path_in_dependency_test.dart +++ b/test/run/errors_if_path_in_dependency_test.dart @@ -27,7 +27,6 @@ Cannot run an executable in a subdirectory of a dependency. Usage: pub run [args...] -h, --help Print this usage information. -c, --[no-]checked Enable runtime type checks and assertions. - --list List all available executables. --mode Mode to run transformers in. (defaults to "release" for dependencies, "debug" for entrypoint) diff --git a/test/run/list_test.dart b/test/run/list_test.dart deleted file mode 100644 index 3de918747..000000000 --- a/test/run/list_test.dart +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import '../descriptor.dart' as d; -import '../test_pub.dart'; - -main() { - integration("lists executables in entrypoint's bin", () { - d.dir(appPath, [ - d.appPubspec(), - d.dir('bin', [ - d.file('foo.dart'), - d.file('bar.dart') - ]) - ]).create(); - - schedulePub(args: ['run', '--list'], output: 'myapp: bar, foo'); - }); - - integration("doesn't list executables in bin's sub directories", () { - d.dir(appPath, [ - d.appPubspec(), - d.dir('bin', [ - d.file('foo.dart'), - d.dir('sub', [ - d.file('bar.dart') - ]) - ]) - ]).create(); - - schedulePub(args: ['run', '--list'], output: 'myapp:foo'); - }); - - integration('lists only Dart files', () { - d.dir(appPath, [ - d.appPubspec(), - d.dir('bin', [ - d.file('foo.dart'), - d.file('bar.sh') - ]) - ]).create(); - - schedulePub(args: ['run', '--list'], output: 'myapp:foo'); - }); - - integration('lists executables from a dependency', () { - d.dir('foo', [ - d.libPubspec('foo', '1.0.0'), - d.dir('bin', [ - d.file('bar.dart') - ]) - ]).create(); - - d.dir(appPath, [ - d.appPubspec({ - 'foo': {'path': '../foo'} - }) - ]).create(); - - pubGet(); - schedulePub(args: ['run', '--list'], output: 'foo:bar'); - }); - - integration('lists executables only from immediate dependencies', () { - d.dir(appPath, [ - d.appPubspec({ - 'foo': {'path': '../foo'} - }) - ]).create(); - - d.dir('foo', [ - d.libPubspec('foo', '1.0.0', deps: { - 'baz': {'path': '../baz'} - }), - d.dir('bin', [ - d.file('bar.dart') - ]) - ]).create(); - - d.dir('baz', [ - d.libPubspec('baz', '1.0.0'), - d.dir('bin', [ - d.file('qux.dart') - ]) - ]).create(); - - - pubGet(); - schedulePub(args: ['run', '--list'], output: 'foo:bar'); - }); - - integration('applies formatting before printing executables', () { - d.dir(appPath, [ - d.appPubspec({ - 'foo': {'path': '../foo'}, - 'bar': {'path': '../bar'} - }), - d.dir('bin', [ - d.file('myapp.dart') - ]) - ]).create(); - - d.dir('foo', [ - d.libPubspec('foo', '1.0.0'), - d.dir('bin', [ - d.file('baz.dart'), - d.file('foo.dart') - ]) - ]).create(); - - d.dir('bar', [ - d.libPubspec('bar', '1.0.0'), - d.dir('bin', [ - d.file('qux.dart') - ]) - ]).create(); - - pubGet(); - schedulePub(args: ['run', '--list'], output: ''' -myapp -bar:qux -foo: foo, baz -'''); - }); - - integration('prints blank line when no executables found', () { - d.dir(appPath, [ - d.appPubspec() - ]).create(); - - schedulePub(args: ['run', '--list'], output: '\n'); - }); -}