OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library barback.asset_cascade; | 5 library barback.asset_cascade; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'asset.dart'; | 10 import 'asset.dart'; |
11 import 'asset_id.dart'; | 11 import 'asset_id.dart'; |
12 import 'asset_node.dart'; | 12 import 'asset_node.dart'; |
13 import 'asset_set.dart'; | 13 import 'asset_set.dart'; |
14 import 'barback_logger.dart'; | |
14 import 'build_result.dart'; | 15 import 'build_result.dart'; |
15 import 'cancelable_future.dart'; | 16 import 'cancelable_future.dart'; |
16 import 'errors.dart'; | 17 import 'errors.dart'; |
17 import 'package_graph.dart'; | 18 import 'package_graph.dart'; |
18 import 'phase.dart'; | 19 import 'phase.dart'; |
19 import 'stream_pool.dart'; | 20 import 'stream_pool.dart'; |
20 import 'transformer.dart'; | 21 import 'transformer.dart'; |
21 import 'utils.dart'; | 22 import 'utils.dart'; |
22 | 23 |
23 /// The asset cascade for an individual package. | 24 /// The asset cascade for an individual package. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 /// | 78 /// |
78 /// This may emit events when the cascade was already dirty. Events are | 79 /// This may emit events when the cascade was already dirty. Events are |
79 /// emitted synchronously to ensure that the dirty state is thoroughly | 80 /// emitted synchronously to ensure that the dirty state is thoroughly |
80 /// propagated as soon as any assets are changed. | 81 /// propagated as soon as any assets are changed. |
81 Stream get onDirty => _onDirtyPool.stream; | 82 Stream get onDirty => _onDirtyPool.stream; |
82 final _onDirtyPool = new StreamPool.broadcast(); | 83 final _onDirtyPool = new StreamPool.broadcast(); |
83 | 84 |
84 /// A controller whose stream feeds into [_onDirtyPool]. | 85 /// A controller whose stream feeds into [_onDirtyPool]. |
85 final _onDirtyController = new StreamController.broadcast(sync: true); | 86 final _onDirtyController = new StreamController.broadcast(sync: true); |
86 | 87 |
88 /// A stream that emits an event whenever any transforms in this cascade log | |
nweiz
2013/10/16 19:41:27
"log" -> "logs"
Bob Nystrom
2013/10/28 23:45:56
Done.
| |
89 /// an entry. | |
90 Stream<LogEntry> get onLog => _onLogPool.stream; | |
91 final _onLogPool = new StreamPool<LogEntry>.broadcast(); | |
92 | |
87 /// The errors that have occurred since the current build started. | 93 /// The errors that have occurred since the current build started. |
88 /// | 94 /// |
89 /// This will be empty if no build is occurring. | 95 /// This will be empty if no build is occurring. |
90 Queue<BarbackException> _accumulatedErrors; | 96 Queue<BarbackException> _accumulatedErrors; |
91 | 97 |
98 /// The number of errors that have been logged since the current build | |
99 /// started. | |
100 int _numLogErrors; | |
101 | |
92 /// A future that completes when the currently running build process finishes. | 102 /// A future that completes when the currently running build process finishes. |
93 /// | 103 /// |
94 /// If no build it in progress, is `null`. | 104 /// If no build it in progress, is `null`. |
95 Future _processDone; | 105 Future _processDone; |
96 | 106 |
97 /// Whether any source assets have been updated or removed since processing | 107 /// Whether any source assets have been updated or removed since processing |
98 /// last began. | 108 /// last began. |
99 var _newChanges = false; | 109 var _newChanges = false; |
100 | 110 |
101 /// Returns all currently-available output assets from this cascade. | 111 /// Returns all currently-available output assets from this cascade. |
102 AssetSet get availableOutputs => | 112 AssetSet get availableOutputs => |
103 new AssetSet.from(_phases.last.availableOutputs.map((node) => node.asset)); | 113 new AssetSet.from(_phases.last.availableOutputs.map((node) => node.asset)); |
104 | 114 |
105 /// Creates a new [AssetCascade]. | 115 /// Creates a new [AssetCascade]. |
106 /// | 116 /// |
107 /// It loads source assets within [package] using [provider]. | 117 /// It loads source assets within [package] using [provider]. |
108 AssetCascade(this.graph, this.package) { | 118 AssetCascade(this.graph, this.package) { |
109 _onDirtyPool.add(_onDirtyController.stream); | 119 _onDirtyPool.add(_onDirtyController.stream); |
110 _addPhase(new Phase(this, [])); | 120 _addPhase(new Phase(this, [])); |
121 | |
122 // Keep track of logged errors so we can know that the build failed. | |
123 onLog.listen((entry) { | |
124 if (entry.level == LogLevel.ERROR) _numLogErrors++; | |
125 }); | |
111 } | 126 } |
112 | 127 |
113 /// Gets the asset identified by [id]. | 128 /// Gets the asset identified by [id]. |
114 /// | 129 /// |
115 /// If [id] is for a generated or transformed asset, this will wait until it | 130 /// If [id] is for a generated or transformed asset, this will wait until it |
116 /// has been created and return it. This means that the returned asset will | 131 /// has been created and return it. This means that the returned asset will |
117 /// always be [AssetState.AVAILABLE]. | 132 /// always be [AssetState.AVAILABLE]. |
118 /// | 133 /// |
119 /// If the asset cannot be found, returns null. | 134 /// If the asset cannot be found, returns null. |
120 Future<AssetNode> getAssetNode(AssetId id) { | 135 Future<AssetNode> getAssetNode(AssetId id) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 } | 230 } |
216 | 231 |
217 void reportError(BarbackException error) { | 232 void reportError(BarbackException error) { |
218 _accumulatedErrors.add(error); | 233 _accumulatedErrors.add(error); |
219 _errorsController.add(error); | 234 _errorsController.add(error); |
220 } | 235 } |
221 | 236 |
222 /// Add [phase] to the end of [_phases] and watch its [onDirty] stream. | 237 /// Add [phase] to the end of [_phases] and watch its [onDirty] stream. |
223 void _addPhase(Phase phase) { | 238 void _addPhase(Phase phase) { |
224 _onDirtyPool.add(phase.onDirty); | 239 _onDirtyPool.add(phase.onDirty); |
240 _onLogPool.add(phase.onLog); | |
225 phase.onDirty.listen((_) { | 241 phase.onDirty.listen((_) { |
226 _newChanges = true; | 242 _newChanges = true; |
227 _waitForProcess(); | 243 _waitForProcess(); |
228 }); | 244 }); |
229 _phases.add(phase); | 245 _phases.add(phase); |
230 } | 246 } |
231 | 247 |
232 /// Starts the build process asynchronously if there is work to be done. | 248 /// Starts the build process asynchronously if there is work to be done. |
233 /// | 249 /// |
234 /// Returns a future that completes with the background processing is done. | 250 /// Returns a future that completes with the background processing is done. |
235 /// If there is no work to do, returns a future that completes immediately. | 251 /// If there is no work to do, returns a future that completes immediately. |
236 /// All errors that occur during processing will be caught (and routed to the | 252 /// All errors that occur during processing will be caught (and routed to the |
237 /// [results] stream) before they get to the returned future, so it is safe | 253 /// [results] stream) before they get to the returned future, so it is safe |
238 /// to discard it. | 254 /// to discard it. |
239 Future _waitForProcess() { | 255 Future _waitForProcess() { |
240 if (_processDone != null) return _processDone; | 256 if (_processDone != null) return _processDone; |
241 | 257 |
242 _accumulatedErrors = new Queue(); | 258 _accumulatedErrors = new Queue(); |
259 _numLogErrors = 0; | |
243 return _processDone = _process().then((_) { | 260 return _processDone = _process().then((_) { |
244 // Report the build completion. | 261 // Report the build completion. |
245 // TODO(rnystrom): Put some useful data in here. | 262 // TODO(rnystrom): Put some useful data in here. |
246 _resultsController.add(new BuildResult(_accumulatedErrors)); | 263 _resultsController.add( |
264 new BuildResult(_accumulatedErrors, _numLogErrors)); | |
247 }).catchError((error) { | 265 }).catchError((error) { |
248 // If we get here, it's an unexpected error. Runtime errors like missing | 266 // If we get here, it's an unexpected error. Runtime errors like missing |
249 // assets should be handled earlier. Errors from transformers or other | 267 // assets should be handled earlier. Errors from transformers or other |
250 // external code that barback calls into should be caught at that API | 268 // external code that barback calls into should be caught at that API |
251 // boundary. | 269 // boundary. |
252 // | 270 // |
253 // On the off chance we get here, pipe the error to the results stream | 271 // On the off chance we get here, pipe the error to the results stream |
254 // as an error. That will let applications handle it without it appearing | 272 // as an error. That will let applications handle it without it appearing |
255 // in the same path as "normal" errors that get reported. | 273 // in the same path as "normal" errors that get reported. |
256 _resultsController.addError(error); | 274 _resultsController.addError(error); |
(...skipping 23 matching lines...) Expand all Loading... | |
280 | 298 |
281 // Otherwise, everything is done. | 299 // Otherwise, everything is done. |
282 return; | 300 return; |
283 } | 301 } |
284 | 302 |
285 // Process that phase and then loop onto the next. | 303 // Process that phase and then loop onto the next. |
286 return future.then((_) => _process()); | 304 return future.then((_) => _process()); |
287 }); | 305 }); |
288 } | 306 } |
289 } | 307 } |
OLD | NEW |