Chromium Code Reviews| Index: sdk/lib/_internal/pub/lib/src/barback.dart |
| diff --git a/sdk/lib/_internal/pub/lib/src/barback.dart b/sdk/lib/_internal/pub/lib/src/barback.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..18b010628f52f484e1d814d81c4267383029d04f |
| --- /dev/null |
| +++ b/sdk/lib/_internal/pub/lib/src/barback.dart |
| @@ -0,0 +1,104 @@ |
| +// Copyright (c) 2013, 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. |
| + |
| +library pub.barback; |
| + |
| +import 'dart:async'; |
| + |
| +import 'package:barback/barback.dart'; |
| + |
| +import 'barback/load_transformers.dart'; |
| +import 'barback/pub_package_provider.dart'; |
| +import 'barback/rewrite_import_transformer.dart'; |
| +import 'barback/server.dart'; |
| +import 'barback/watch_sources.dart'; |
| +import 'utils.dart'; |
| + |
| +/// Creates a [BarbackServer] serving on [host] and [port]. |
| +/// |
| +/// This transforms and serves all library and asset files in all packages in |
| +/// [graph]. It loads any transformer plugins defined in packages in [graph] and |
| +/// re-runs them as necessary when any input files change. |
| +Future<BarbackServer> createServer(String host, int port, PackageGraph graph) { |
| + var provider = new PubPackageProvider(graph); |
| + var barback = new Barback(provider); |
| + watchSources(graph, barback); |
|
Bob Nystrom
2013/08/27 22:12:30
I think it's cleaner to do this after the server i
nweiz
2013/08/28 20:45:23
Done.
|
| + return BarbackServer.bind(host, port, barback, graph.entrypoint.root.name) |
| + .then((server) { |
| + var completer = new Completer(); |
| + |
| + // If any errors get emitted either by barback or by the server, including |
| + // non-programmatic barback errors, they should take down the whole program. |
|
Bob Nystrom
2013/08/27 22:12:30
"non-programmatic" -> "programmatic"?
nweiz
2013/08/28 20:45:23
No, "non-programmatic" is correct. If e.g. a Trans
|
| + var subscriptions = [ |
| + server.barback.errors.listen((error) { |
| + if (error is TransformerException) error = error.error; |
| + if (!completer.isCompleted) completer.completeError(error); |
| + }), |
| + server.barback.results.listen((_) {}, onError: (error) { |
| + if (!completer.isCompleted) completer.completeError(error); |
| + }), |
| + server.results.listen((_) {}, onError: (error) { |
| + if (!completer.isCompleted) completer.completeError(error); |
| + }) |
| + ]; |
| + |
| + _loadTransformers(server, graph).then((_) { |
| + if (!completer.isCompleted) completer.complete(server); |
| + }).catchError((error) { |
| + if (!completer.isCompleted) completer.completeError(error); |
| + }); |
| + |
| + return completer.future.whenComplete(() { |
| + for (var subscription in subscriptions) { |
| + subscription.cancel(); |
| + } |
| + }); |
| + }); |
| +} |
| + |
| +/// Loads all transformers depended on by packages in [graph]. |
| +/// |
| +/// This uses [server] to serve the Dart files from which transformers are |
| +/// loaded, then adds the transformers to `server.barback`. |
| +Future _loadTransformers(BarbackServer server, PackageGraph graph) { |
| + // Add a rewrite transformer for each package, so that we can resolve |
| + // "package:" imports while loading transformers. |
| + var rewrite = new RewriteImportTransformer(); |
| + for (var package in graph.packages.values) { |
| + server.barback.updateTransformers(package.name, [[rewrite]]); |
| + } |
| + |
| + var idsToPackages = new Map<AssetId, Set<String>>(); |
|
Bob Nystrom
2013/08/27 22:12:30
Document this, maybe:
// Map each transformer to
nweiz
2013/08/28 20:45:23
Done.
|
| + for (var package in graph.packages.values) { |
| + for (var id in unionAll(package.pubspec.transformers)) { |
| + idsToPackages.putIfAbsent(id, () => new Set<String>()).add(package.name); |
| + } |
| + } |
| + var transformersForId = new Map<AssetId, Set<Transformer>>(); |
|
Bob Nystrom
2013/08/27 22:12:30
Nit: move to just above Future.wait.
nweiz
2013/08/28 20:45:23
Done.
|
| + |
| + // TODO(nweiz): support transformers that (possibly transitively) |
| + // depend on other transformers. |
| + return Future.wait(idsToPackages.keys.map((id) { |
| + return loadTransformers(server, id).then((transformers) { |
| + if (transformers.isEmpty) { |
| + var path = id.path.replaceFirst('lib/', ''); |
| + // Ensure that packages are listed in a deterministic order. |
| + var packages = idsToPackages[id].toList(); |
| + packages.sort(); |
| + throw new ApplicationException( |
| + "No transformers were defined in package:${id.package}/$path,\n" |
| + "required by ${packages.join(', ')}."); |
| + } |
| + |
| + transformersForId[id] = transformers; |
| + }); |
| + })).then((_) { |
| + for (var package in graph.packages.values) { |
| + var phases = package.pubspec.transformers.map((phase) { |
| + return unionAll(phase.map((id) => transformersForId[id])); |
| + }); |
| + server.barback.updateTransformers(package.name, phases); |
| + } |
| + }); |
| +} |