Chromium Code Reviews| Index: pkg/barback/lib/src/transform_node.dart |
| diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b29011059bfc861c06e0ab14108e8ec839f267aa |
| --- /dev/null |
| +++ b/pkg/barback/lib/src/transform_node.dart |
| @@ -0,0 +1,118 @@ |
| +// 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 barback.transform_node; |
| + |
| +import 'dart:async'; |
| + |
| +import '../barback.dart'; |
| +import '../transformer.dart'; |
| +import 'asset_graph.dart'; |
| +import 'asset_node.dart'; |
| +import 'phase.dart'; |
| + |
| +/// Describes a transform on a set of assets and its relationship to the build |
| +/// dependency graph. Keeps track of whether it's dirty and needs to be run and |
| +/// which primary asset it depends on. |
|
nweiz
2013/06/18 23:14:46
"primary asset" -> "assets"
Bob Nystrom
2013/06/20 00:23:59
Done.
|
| +class TransformNode { |
| + final Phase phase; |
| + final Transformer transformer; |
| + final AssetNode primary; |
| + var isDirty = true; |
|
nweiz
2013/06/18 23:14:46
These could use at least brief documentation.
Als
Bob Nystrom
2013/06/20 00:23:59
Done.
|
| + |
| + /// The inputs read by this transform the last time it was run. Used to |
| + /// tell if an input was removed in a later run. |
| + var inputs = new Set<AssetNode>(); |
| + |
| + /// The outputs created by this transform the last time it was run. Used to |
| + /// tell if an output was removed in a later run. |
| + var outputs = new Set<AssetId>(); |
| + |
| + TransformNode(this.phase, this.transformer, this.primary); |
| + |
| + /// Applies this transform. |
| + /// |
| + /// Returns a [TransformOutputs] describing the resulting outputs compared to |
| + /// previous runs. |
| + Future<TransformOutputs> apply() { |
| + var transform = new _Transform(this); |
| + return transformer.apply(transform).catchError((error) { |
| + // Catch all transformer errors and pipe them to the results stream. |
| + // This was a broken transformer doesn't take down the whole graph. |
|
nweiz
2013/06/18 23:14:46
"was" -> "is so"
Bob Nystrom
2013/06/20 00:23:59
Done.
|
| + phase.graph.reportError(error); |
| + |
| + // Don't allow partial results from a failed transform. |
| + transform._outputs.clear(); |
| + }).then((_) { |
| + isDirty = false; |
| + |
| + // Stop watching any inputs that were removed. |
| + for (var oldInput in inputs) { |
| + oldInput.consumers.remove(this); |
| + } |
| + |
| + // Watch any new inputs so this transform will be re-processed when an |
| + // input is modified. |
| + for (var newInput in transform._inputs) { |
| + newInput.consumers.add(this); |
| + } |
| + |
| + inputs = transform._inputs; |
| + |
| + // See which outputs are missing from the last run. |
| + var outputIds = transform._outputs.keys.toSet(); |
| + var removed = outputs.difference(outputIds); |
| + outputs = outputIds; |
| + |
| + return new TransformOutputs(transform._outputs, removed); |
| + }); |
| + } |
| +} |
| + |
| +/// The result of running a [Transform], compared to the previous time it was |
| +/// applied. |
| +class TransformOutputs { |
| + /// The outputs that are new or were modified since the last run. |
| + final Map<AssetId, Asset> updated; |
| + |
| + /// The outputs that were created by the previous run but were not generated |
| + /// by the most recent run. |
| + final Set<AssetId> removed; |
| + |
| + TransformOutputs(this.updated, this.removed); |
| +} |
| + |
| +/// A concrete implementation of [Transform]. |
| +class _Transform implements Transform { |
| + final TransformNode _node; |
| + |
| + final _inputs = new Set<AssetNode>(); |
| + final _outputs = new Map<AssetId, Asset>(); |
| + |
| + AssetId get primaryId => _node.primary.id; |
| + Future<Asset> get primaryInput => getInput(primaryId); |
| + |
| + _Transform(this._node); |
| + |
| + Future<Asset> getInput(AssetId id) { |
| + return new Future(() { |
| + var node = _node.phase.inputs[id]; |
| + // TODO(rnystrom): Need to handle passthrough where an asset from a |
| + // previous phase can be found. |
| + |
| + // Throw if the input isn't found. This ensures the transformer's apply |
| + // is exited. We'll then catch this and report it through the proper |
| + // results stream. |
| + if (node == null) throw new MissingInputException(id); |
| + |
| + // Keep track of which assets this transform depends on. |
| + _inputs.add(node); |
| + return node.asset; |
| + }); |
| + } |
| + |
| + void addOutput(AssetId id, Asset output) { |
| + _outputs[id] = output; |
| + } |
| +} |