4
4
5
5
import 'dart:collection' ;
6
6
7
+ import 'package:analyzer/analyzer.dart' as analyzer;
8
+ import 'package:path/path.dart' as p;
9
+
7
10
import '../ascii_tree.dart' as tree;
8
11
import '../command.dart' ;
12
+ import '../dart.dart' ;
9
13
import '../log.dart' as log;
10
14
import '../package.dart' ;
11
15
import '../utils.dart' ;
12
16
17
+ /// Returns `true` if [path] looks like a Dart entrypoint.
18
+ bool _isDartExecutable (String path) {
19
+ try {
20
+ var unit = analyzer.parseDartFile (path, parseFunctionBodies: false );
21
+ return isEntrypoint (unit);
22
+ } on analyzer.AnalyzerErrorGroup {
23
+ return false ;
24
+ }
25
+ }
26
+
13
27
/// Handles the `deps` pub command.
14
28
class DepsCommand extends PubCommand {
15
29
String get name => "deps" ;
@@ -36,6 +50,9 @@ class DepsCommand extends PubCommand {
36
50
negatable: true ,
37
51
help: "Whether to include dev dependencies." ,
38
52
defaultsTo: true );
53
+
54
+ argParser.addFlag ("executables" ,
55
+ negatable: false , help: "List all available executables." );
39
56
}
40
57
41
58
void run () {
@@ -44,18 +61,22 @@ class DepsCommand extends PubCommand {
44
61
45
62
_buffer = new StringBuffer ();
46
63
47
- _buffer.writeln (_labelPackage (entrypoint.root));
48
-
49
- switch (argResults["style" ]) {
50
- case "compact" :
51
- _outputCompact ();
52
- break ;
53
- case "list" :
54
- _outputList ();
55
- break ;
56
- case "tree" :
57
- _outputTree ();
58
- break ;
64
+ if (argResults['executables' ]) {
65
+ _outputExecutables ();
66
+ } else {
67
+ _buffer.writeln (_labelPackage (entrypoint.root));
68
+
69
+ switch (argResults["style" ]) {
70
+ case "compact" :
71
+ _outputCompact ();
72
+ break ;
73
+ case "list" :
74
+ _outputList ();
75
+ break ;
76
+ case "tree" :
77
+ _outputTree ();
78
+ break ;
79
+ }
59
80
}
60
81
61
82
log.message (_buffer);
@@ -231,4 +252,60 @@ class DepsCommand extends PubCommand {
231
252
'was generated, please run "pub get" again.' );
232
253
return null ;
233
254
}
255
+
256
+ /// Outputs all executables reachable from [entrypoint] .
257
+ void _outputExecutables () {
258
+ var packages = []
259
+ ..add (entrypoint.root)
260
+ ..addAll ((_includeDev
261
+ ? entrypoint.root.immediateDependencies
262
+ : entrypoint.root.dependencies)
263
+ .map ((dep) => entrypoint.packageGraph.packages[dep.name]));
264
+
265
+ for (var package in packages) {
266
+ var executables = _getExecutablesFor (package);
267
+ if (executables.isNotEmpty) {
268
+ _buffer.writeln (_formatExecutables (package.name, executables.toList ()));
269
+ }
270
+ }
271
+ }
272
+
273
+ /// Lists all Dart files in the `bin` directory of the [package] .
274
+ ///
275
+ /// Returns file names without extensions.
276
+ List <String > _getExecutablesFor (Package package) => package.executableIds
277
+ .where ((e) => _isDartExecutable (p.absolute (package.dir, e.path)))
278
+ .map ((e) => p.basenameWithoutExtension (e.path));
279
+
280
+ /// Returns formatted string that lists [executables] for the [packageName] .
281
+ /// Examples:
282
+ ///
283
+ /// _formatExecutables('foo', ['foo']) // -> 'foo'
284
+ /// _formatExecutables('foo', ['bar']) // -> 'foo:bar'
285
+ /// _formatExecutables('foo', ['bar', 'foo']) // -> 'foo: foo, bar'
286
+ ///
287
+ /// Note the leading space before first executable and sorting order in the
288
+ /// last example.
289
+ String _formatExecutables (String packageName, List <String > executables) {
290
+ if (executables.length == 1 ) {
291
+ // If executable matches the package name omit the name of executable in
292
+ // the output.
293
+ return executables.first != packageName
294
+ ? '${packageName }:${log .bold (executables .first )}'
295
+ : log.bold (executables.first);
296
+ }
297
+
298
+ // Sort executables to make executable that matches the package name to be
299
+ // the first in the list.
300
+ executables.sort ((e1, e2) {
301
+ if (e1 == packageName)
302
+ return - 1 ;
303
+ else if (e2 == packageName)
304
+ return 1 ;
305
+ else
306
+ return e1.compareTo (e2);
307
+ });
308
+
309
+ return '${packageName }: ${executables .map (log .bold ).join (', ' )}' ;
310
+ }
234
311
}
0 commit comments