| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library barback.asset_graph_manager; | |
| 6 | |
| 7 import 'dart:async'; | |
| 8 | |
| 9 import 'package:stack_trace/stack_trace.dart'; | |
| 10 | |
| 11 import 'asset.dart'; | |
| 12 import 'asset_provider.dart'; | |
| 13 import 'asset_graph.dart'; | |
| 14 import 'asset_id.dart'; | |
| 15 import 'errors.dart'; | |
| 16 import 'utils.dart'; | |
| 17 | |
| 18 // TODO(nweiz): come up with better names for this and AssetGraph. | |
| 19 | |
| 20 /// The asset manager for an entire application. | |
| 21 /// | |
| 22 /// This tracks each package's [AssetGraph] and routes asset requests between | |
| 23 /// them. | |
| 24 class AssetGraphManager { | |
| 25 /// The provider that exposes asset and package information. | |
| 26 final AssetProvider provider; | |
| 27 | |
| 28 /// The [AssetGraph] for each package. | |
| 29 final _graphs = <String, AssetGraph>{}; | |
| 30 | |
| 31 /// The current [BuildResult] for each package's [AssetGraph]. | |
| 32 /// | |
| 33 /// The result for a given package will be `null` if that [AssetGraph] is | |
| 34 /// actively building. | |
| 35 final _graphResults = <String, BuildResult>{}; | |
| 36 | |
| 37 /// A stream that emits a [BuildResult] each time the build is completed, | |
| 38 /// whether or not it succeeded. | |
| 39 /// | |
| 40 /// This will emit a result only once every package's [AssetGraph] has | |
| 41 /// finished building. | |
| 42 /// | |
| 43 /// If an unexpected error in barback itself occurs, it will be emitted | |
| 44 /// through this stream's error channel. | |
| 45 Stream<BuildResult> get results => _resultsController.stream; | |
| 46 final _resultsController = new StreamController<BuildResult>.broadcast(); | |
| 47 | |
| 48 /// A stream that emits any errors from the asset graph or the transformers. | |
| 49 /// | |
| 50 /// This emits errors as they're detected. If an error occurs in one part of | |
| 51 /// the asset graph, unrelated parts will continue building. | |
| 52 /// | |
| 53 /// This will not emit programming errors from barback itself. Those will be | |
| 54 /// emitted through the [results] stream's error channel. | |
| 55 Stream get errors => _errors; | |
| 56 Stream _errors; | |
| 57 | |
| 58 /// Creates a new [AssetGraphManager] that will transform assets in all | |
| 59 /// packages made available by [provider]. | |
| 60 AssetGraphManager(this.provider) { | |
| 61 for (var package in provider.packages) { | |
| 62 var graph = new AssetGraph(this, package, | |
| 63 provider.getTransformers(package)); | |
| 64 // The initial result for each graph is "success" since the graph doesn't | |
| 65 // start building until some source in that graph is updated. | |
| 66 _graphResults[package] = new BuildResult.success(); | |
| 67 _graphs[package] = graph; | |
| 68 | |
| 69 graph.results.listen((result) { | |
| 70 _graphResults[graph.package] = result; | |
| 71 // If any graph hasn't yet finished, the overall build isn't finished | |
| 72 // either. | |
| 73 if (_graphResults.values.any((result) => result == null)) return; | |
| 74 | |
| 75 // Include all build errors for all graphs. If no graphs have errors, | |
| 76 // the result will automatically be considered a success. | |
| 77 _resultsController.add(new BuildResult(flatten( | |
| 78 _graphResults.values.map((result) => result.errors)))); | |
| 79 }, onError: _resultsController.addError); | |
| 80 } | |
| 81 | |
| 82 _errors = mergeStreams(_graphs.values.map((graph) => graph.errors)); | |
| 83 } | |
| 84 | |
| 85 /// Gets the asset identified by [id]. | |
| 86 /// | |
| 87 /// If [id] is for a generated or transformed asset, this will wait until | |
| 88 /// it has been created and return it. If the asset cannot be found, throws | |
| 89 /// [AssetNotFoundException]. | |
| 90 Future<Asset> getAssetById(AssetId id) { | |
| 91 var graph = _graphs[id.package]; | |
| 92 if (graph != null) return graph.getAssetById(id); | |
| 93 return new Future.error( | |
| 94 new AssetNotFoundException(id), | |
| 95 new Trace.current().vmTrace); | |
| 96 } | |
| 97 | |
| 98 /// Adds [sources] to the graph's known set of source assets. | |
| 99 /// | |
| 100 /// Begins applying any transforms that can consume any of the sources. If a | |
| 101 /// given source is already known, it is considered modified and all | |
| 102 /// transforms that use it will be re-applied. | |
| 103 void updateSources(Iterable<AssetId> sources) { | |
| 104 groupBy(sources, (id) => id.package).forEach((package, ids) { | |
| 105 var graph = _graphs[package]; | |
| 106 if (graph == null) throw new ArgumentError("Unknown package $package."); | |
| 107 _graphResults[package] = null; | |
| 108 graph.updateSources(ids); | |
| 109 }); | |
| 110 } | |
| 111 | |
| 112 /// Removes [removed] from the graph's known set of source assets. | |
| 113 void removeSources(Iterable<AssetId> sources) { | |
| 114 groupBy(sources, (id) => id.package).forEach((package, ids) { | |
| 115 var graph = _graphs[package]; | |
| 116 if (graph == null) throw new ArgumentError("Unknown package $package."); | |
| 117 _graphResults[package] = null; | |
| 118 graph.removeSources(ids); | |
| 119 }); | |
| 120 } | |
| 121 } | |
| OLD | NEW |