Chromium Code Reviews| Index: pkg/barback/lib/src/package_graph.dart |
| diff --git a/pkg/barback/lib/src/package_graph.dart b/pkg/barback/lib/src/package_graph.dart |
| index 6765cf38ecb9808e3d9563df0d8af75c62674bd5..ee8c15ade92fd3aa9b592e35965b2fd6b8f76c73 100644 |
| --- a/pkg/barback/lib/src/package_graph.dart |
| +++ b/pkg/barback/lib/src/package_graph.dart |
| @@ -71,53 +71,55 @@ class PackageGraph { |
| /// Creates a new [PackageGraph] that will transform assets in all packages |
| /// made available by [provider]. |
| PackageGraph(this.provider) { |
| - for (var package in provider.packages) { |
| - var cascade = new AssetCascade(this, package); |
| - // The initial result for each cascade is "success" since the cascade |
| - // doesn't start building until some source in that graph is updated. |
| - _cascadeResults[package] = new BuildResult.success(); |
| - _cascades[package] = cascade; |
| - cascade.onDirty.listen((_) { |
| - _cascadeResults[package] = null; |
| - }); |
| - |
| - cascade.onLog.listen((entry) { |
| - if (_logController.hasListener) { |
| - _logController.add(entry); |
| - } else if (entry.level != LogLevel.FINE) { |
| - // No listeners, so just print entry. |
| - var buffer = new StringBuffer(); |
| - buffer.write("[${entry.level} ${entry.transform}] "); |
| - |
| - if (entry.span != null) { |
| - buffer.write(entry.span.getLocationMessage(entry.message)); |
| - } else { |
| - buffer.write(entry.message); |
| + _inErrorZone(() { |
| + for (var package in provider.packages) { |
| + var cascade = new AssetCascade(this, package); |
| + // The initial result for each cascade is "success" since the cascade |
| + // doesn't start building until some source in that graph is updated. |
| + _cascadeResults[package] = new BuildResult.success(); |
| + _cascades[package] = cascade; |
| + cascade.onDirty.listen((_) { |
| + _cascadeResults[package] = null; |
| + }); |
| + |
| + cascade.onLog.listen((entry) { |
| + if (_logController.hasListener) { |
| + _logController.add(entry); |
| + } else if (entry.level != LogLevel.FINE) { |
| + // No listeners, so just print entry. |
| + var buffer = new StringBuffer(); |
| + buffer.write("[${entry.level} ${entry.transform}] "); |
| + |
| + if (entry.span != null) { |
| + buffer.write(entry.span.getLocationMessage(entry.message)); |
| + } else { |
| + buffer.write(entry.message); |
| + } |
| + |
| + print(buffer); |
| } |
| - |
| - print(buffer); |
| - } |
| - }); |
| - |
| - cascade.results.listen((result) { |
| - _cascadeResults[cascade.package] = result; |
| - // If any cascade hasn't yet finished, the overall build isn't finished |
| - // either. |
| - if (_cascadeResults.values.any((result) => result == null)) return; |
| - |
| - // Include all build errors for all cascades. If no cascades have |
| - // errors, the result will automatically be considered a success. |
| - _resultsController.add( |
| - new BuildResult.aggregate(_cascadeResults.values)); |
| - }, onError: (error, stackTrace) { |
| - _lastUnexpectedError = error; |
| - _lastUnexpectedErrorTrace = stackTrace; |
| - _resultsController.addError(error, stackTrace); |
| - }); |
| - } |
| - |
| - _errors = mergeStreams(_cascades.values.map((cascade) => cascade.errors), |
| - broadcast: true); |
| + }); |
| + |
| + cascade.results.listen((result) { |
| + _cascadeResults[cascade.package] = result; |
| + // If any cascade hasn't yet finished, the overall build isn't finished |
|
Bob Nystrom
2014/03/04 23:52:40
Long line.
This method is pretty big. How about b
nweiz
2014/03/05 00:11:58
Done.
|
| + // either. |
| + if (_cascadeResults.values.any((result) => result == null)) return; |
| + |
| + // Include all build errors for all cascades. If no cascades have |
| + // errors, the result will automatically be considered a success. |
| + _resultsController.add( |
| + new BuildResult.aggregate(_cascadeResults.values)); |
| + }, onError: (error, stackTrace) { |
| + _lastUnexpectedError = error; |
| + _lastUnexpectedErrorTrace = stackTrace; |
| + _resultsController.addError(error, stackTrace); |
| + }); |
| + } |
| + |
| + _errors = mergeStreams(_cascades.values.map((cascade) => cascade.errors), |
| + broadcast: true); |
| + }); |
| } |
| /// Gets the asset node identified by [id]. |
| @@ -128,9 +130,11 @@ class PackageGraph { |
| /// |
| /// If the asset cannot be found, returns null. |
| Future<AssetNode> getAssetNode(AssetId id) { |
| - var cascade = _cascades[id.package]; |
| - if (cascade != null) return cascade.getAssetNode(id); |
| - return new Future.value(null); |
| + return _inErrorZone(() { |
| + var cascade = _cascades[id.package]; |
| + if (cascade != null) return cascade.getAssetNode(id); |
| + return new Future.value(null); |
| + }); |
| } |
| /// Gets all output assets. |
| @@ -143,12 +147,12 @@ class PackageGraph { |
| /// concrete outputs, and those outputs will be returned. |
| Future<AssetSet> getAllAssets() { |
| for (var cascade in _cascades.values) { |
| - cascade.forceAllTransforms(); |
| + _inErrorZone(() => cascade.forceAllTransforms()); |
| } |
| if (_cascadeResults.values.contains(null)) { |
| // A build is still ongoing, so wait for it to complete and try again. |
| - return results.first.then((_) => getAllAssets()); |
| + return results.first.then((_) => getAllAssets()) ; |
|
Bob Nystrom
2014/03/04 23:52:40
Extra space.
nweiz
2014/03/05 00:11:58
Done.
|
| } |
| // If an unexpected error occurred, complete with that. |
| @@ -180,7 +184,7 @@ class PackageGraph { |
| groupBy(sources, (id) => id.package).forEach((package, ids) { |
| var cascade = _cascades[package]; |
| if (cascade == null) throw new ArgumentError("Unknown package $package."); |
| - cascade.updateSources(ids); |
| + _inErrorZone(() => cascade.updateSources(ids)); |
| }); |
| } |
| @@ -189,12 +193,34 @@ class PackageGraph { |
| groupBy(sources, (id) => id.package).forEach((package, ids) { |
| var cascade = _cascades[package]; |
| if (cascade == null) throw new ArgumentError("Unknown package $package."); |
| - cascade.removeSources(ids); |
| + _inErrorZone(() => cascade.removeSources(ids)); |
| }); |
| } |
| void updateTransformers(String package, |
| Iterable<Iterable<Transformer>> transformers) { |
| - _cascades[package].updateTransformers(transformers); |
| + _inErrorZone(() => _cascades[package].updateTransformers(transformers)); |
| + } |
| + |
| + /// Run [body] in an error-handling [Zone] and pipe any unexpected errors to |
| + /// the error channel of [results]. |
| + /// |
| + /// [body] can return a value or a [Future] that will be piped to the returned |
| + /// [Future]. If it throws a [BarbackException], that exception will be piped |
| + /// to the returned [Future] as well. ANy other exceptions will be piped to |
|
Bob Nystrom
2014/03/04 23:52:40
"ANy" -> "Any"
nweiz
2014/03/05 00:11:58
Done.
|
| + /// [results]. |
| + Future _inErrorZone(body()) { |
| + var completer = new Completer.sync(); |
| + runZoned(() { |
| + syncFuture(body).then(completer.complete).catchError((error, stackTrace) { |
| + if (error is! BarbackException) throw error; |
| + completer.addError(error, stackTrace); |
| + }); |
| + }, onError: (error, stackTrace) { |
| + _lastUnexpectedError = error; |
| + _lastUnexpectedErrorTrace = stackTrace; |
| + _resultsController.addError(error, stackTrace); |
| + }); |
| + return completer.future; |
| } |
| } |