@@ -16,6 +16,7 @@ import '../builder/builder.dart';
16
16
import '../builder/build_step_impl.dart' ;
17
17
import '../package_graph/package_graph.dart' ;
18
18
import 'build_result.dart' ;
19
+ import 'input_set.dart' ;
19
20
import 'phase.dart' ;
20
21
21
22
/// Runs all of the [Phases] in [phaseGroups] .
@@ -75,23 +76,71 @@ PackageGraph get _packageGraph => Zone.current[_packageGraphKey];
75
76
/// Runs the [phaseGroups] and returns a [Future<BuildResult>] which completes
76
77
/// once all [Phase] s are done.
77
78
Future <BuildResult > _runPhases (List <List <Phase >> phaseGroups) async {
78
- var outputs = [];
79
+ final allInputs = await _allInputs (phaseGroups);
80
+ final outputs = < Asset > [];
79
81
for (var group in phaseGroups) {
82
+ final groupOutputs = < Asset > [];
80
83
for (var phase in group) {
81
- var inputs = (await _reader.listAssetIds (phase.inputSets).toList ())
82
- .where (_isValidInput);
84
+ var inputs = _matchingInputs (allInputs, phase.inputSets);
83
85
for (var builder in phase.builders) {
84
86
// TODO(jakemac): Optimize, we can run all the builders in a phase
85
87
// at the same time instead of sequentially.
86
88
await for (var output in _runBuilder (builder, inputs)) {
89
+ groupOutputs.add (output);
87
90
outputs.add (output);
88
91
}
89
92
}
90
93
}
94
+ /// Once the group is done, add all outputs so they can be used in the next
95
+ /// phase.
96
+ for (var output in groupOutputs) {
97
+ allInputs.putIfAbsent (output.id.package, () => new Set <AssetId >());
98
+ allInputs[output.id.package].add (output.id);
99
+ }
91
100
}
92
101
return new BuildResult (BuildStatus .Success , BuildType .Full , outputs);
93
102
}
94
103
104
+ /// Returns a map of all the available inputs by package.
105
+ Future <Map <String , Set <AssetId >>> _allInputs (
106
+ List <List <Phase >> phaseGroups) async {
107
+ final packages = new Set <String >();
108
+ for (var group in phaseGroups) {
109
+ for (var phase in group) {
110
+ for (var inputSet in phase.inputSets) {
111
+ packages.add (inputSet.package);
112
+ }
113
+ }
114
+ }
115
+
116
+ var inputSets = packages.map ((package) => new InputSet (package));
117
+ var allInputs = await _reader.listAssetIds (inputSets).toList ();
118
+ var inputsByPackage = {};
119
+ for (var input in allInputs) {
120
+ inputsByPackage.putIfAbsent (input.package, () => new Set <AssetId >());
121
+
122
+ if (_isValidInput (input)) {
123
+ inputsByPackage[input.package].add (input);
124
+ }
125
+ }
126
+ return inputsByPackage;
127
+ }
128
+
129
+ /// Gets a list of all inputs matching [inputSets] given [allInputs] .
130
+ Set <AssetId > _matchingInputs (
131
+ Map <String , Set <AssetId >> inputsByPackage, Iterable <InputSet > inputSets) {
132
+ var inputs = new Set <AssetId >();
133
+ for (var inputSet in inputSets) {
134
+ assert (inputsByPackage.containsKey (inputSet.package));
135
+ for (var input in inputsByPackage[inputSet.package]) {
136
+ if (inputSet.globs.any ((g) => g.matches (input.path))) {
137
+ inputs.add (input);
138
+ }
139
+ }
140
+ }
141
+ return inputs;
142
+ }
143
+
95
144
/// Checks if an [input] is valid.
96
145
bool _isValidInput (AssetId input) {
97
146
var parts = path.split (input.path);
0 commit comments