@@ -14,6 +14,7 @@ import 'package:build/src/internal.dart';
14
14
import 'package:built_collection/built_collection.dart' ;
15
15
import 'package:crypto/crypto.dart' ;
16
16
import 'package:glob/glob.dart' ;
17
+ import 'package:meta/meta.dart' ;
17
18
import 'package:package_config/package_config.dart' ;
18
19
import 'package:watcher/watcher.dart' ;
19
20
@@ -23,6 +24,7 @@ import '../generate/phase.dart';
23
24
import '../util/constants.dart' ;
24
25
import 'exceptions.dart' ;
25
26
import 'node.dart' ;
27
+ import 'post_process_build_step_id.dart' ;
26
28
27
29
part 'serialization.dart' ;
28
30
@@ -46,6 +48,14 @@ class AssetGraph implements GeneratedAssetHider {
46
48
47
49
final BuiltMap <String , LanguageVersion ?> packageLanguageVersions;
48
50
51
+ /// All post process build steps outputs, indexed by package then
52
+ /// [PostProcessBuildStepId] .
53
+ ///
54
+ /// Created with empty outputs at the start of the build if it's a new build
55
+ /// step; or deserialized with previous build outputs if it has run before.
56
+ final Map <String , Map <PostProcessBuildStepId , Set <AssetId >>>
57
+ _postProcessBuildStepOutputs = {};
58
+
49
59
AssetGraph ._(
50
60
this .buildPhasesDigest,
51
61
this .dartVersion,
@@ -93,6 +103,10 @@ class AssetGraph implements GeneratedAssetHider {
93
103
94
104
List <int > serialize () => _AssetGraphSerializer (this ).serialize ();
95
105
106
+ @visibleForTesting
107
+ Map <String , Map <PostProcessBuildStepId , Set <AssetId >>>
108
+ get allPostProcessBuildStepOutputs => _postProcessBuildStepOutputs;
109
+
96
110
/// Checks if [id] exists in the graph.
97
111
bool contains (AssetId id) =>
98
112
_nodesByPackage[id.package]? .containsKey (id.path) ?? false ;
@@ -158,6 +172,7 @@ class AssetGraph implements GeneratedAssetHider {
158
172
}
159
173
}
160
174
_nodesByPackage.putIfAbsent (node.id.package, () => {})[node.id.path] = node;
175
+
161
176
return node;
162
177
}
163
178
@@ -238,16 +253,21 @@ class AssetGraph implements GeneratedAssetHider {
238
253
/// Also removes all edges between all removed nodes and remaining nodes.
239
254
///
240
255
/// Returns the IDs of removed asset nodes.
241
- Set <AssetId > _removeRecursive (AssetId id, {Set <AssetId >? removedIds}) {
256
+ Set <AssetId > _removeRecursive (
257
+ AssetId id, {
258
+ Set <AssetId >? removedIds,
259
+ Map <AssetId , Set <AssetId >>? anchorOutputs,
260
+ }) {
242
261
removedIds ?? = < AssetId > {};
243
262
var node = get (id);
244
263
if (node == null ) return removedIds;
245
264
removedIds.add (id);
246
- for (var anchor in node.anchorOutputs.toList ()) {
247
- _removeRecursive (anchor, removedIds: removedIds);
248
- }
249
265
for (var output in node.primaryOutputs.toList ()) {
250
- _removeRecursive (output, removedIds: removedIds);
266
+ _removeRecursive (
267
+ output,
268
+ removedIds: removedIds,
269
+ anchorOutputs: anchorOutputs,
270
+ );
251
271
}
252
272
for (var output in node.outputs) {
253
273
updateNodeIfPresent (output, (nodeBuilder) {
@@ -290,6 +310,12 @@ class AssetGraph implements GeneratedAssetHider {
290
310
if (node.type != NodeType .missingSource) {
291
311
_nodesByPackage[id.package]! .remove (id.path);
292
312
}
313
+
314
+ // Remove post build action applications with removed assets as inputs.
315
+ for (final packageOutputs in _postProcessBuildStepOutputs.values) {
316
+ packageOutputs.removeWhere ((id, _) => removedIds! .contains (id.input));
317
+ }
318
+
293
319
return removedIds;
294
320
}
295
321
@@ -301,6 +327,25 @@ class AssetGraph implements GeneratedAssetHider {
301
327
Iterable <AssetNode > packageNodes (String package) =>
302
328
_nodesByPackage[package]? .values ?? [];
303
329
330
+ Iterable <PostProcessBuildStepId > postProcessBuildStepIds ({
331
+ required String package,
332
+ }) => _postProcessBuildStepOutputs[package]? .keys ?? const [];
333
+
334
+ void updatePostProcessBuildStep (
335
+ PostProcessBuildStepId buildStepId, {
336
+ required Set <AssetId > outputs,
337
+ }) {
338
+ _postProcessBuildStepOutputs.putIfAbsent (
339
+ buildStepId.input.package,
340
+ () => {},
341
+ )[buildStepId] =
342
+ outputs;
343
+ }
344
+
345
+ Iterable <AssetId > postProcessBuildStepOutputs (PostProcessBuildStepId action) {
346
+ return _postProcessBuildStepOutputs[action.input.package]! [action]! ;
347
+ }
348
+
304
349
/// All the generated outputs in the graph.
305
350
Iterable <AssetId > get outputs =>
306
351
allNodes.where ((n) => n.type == NodeType .generated).map ((n) => n.id);
@@ -547,7 +592,7 @@ class AssetGraph implements GeneratedAssetHider {
547
592
),
548
593
);
549
594
} else if (phase is PostBuildPhase ) {
550
- _addPostBuildPhaseAnchors (phase, allInputs);
595
+ _addPostBuildActionApplications (phase, allInputs);
551
596
} else {
552
597
throw StateError ('Unrecognized phase type $phase ' );
553
598
}
@@ -600,27 +645,21 @@ class AssetGraph implements GeneratedAssetHider {
600
645
return phaseOutputs;
601
646
}
602
647
603
- /// Adds all [AssetNode.postProcessAnchor ] s for [phase] given [allInputs] ;
604
- ///
605
- /// Does not return anything because [AssetNode.postProcessAnchor] s are
606
- /// synthetic and should not be treated as inputs.
607
- void _addPostBuildPhaseAnchors ( PostBuildPhase phase, Set < AssetId > allInputs ) {
608
- var actionNum = 0 ;
648
+ /// Adds all [PostProcessBuildStepId ] s for [phase] given [allInputs] ;
649
+ void _addPostBuildActionApplications (
650
+ PostBuildPhase phase,
651
+ Set < AssetId > allInputs,
652
+ ) {
653
+ var actionNumber = 0 ;
609
654
for (var action in phase.builderActions) {
610
655
var inputs = allInputs.where ((input) => _actionMatches (action, input));
611
656
for (var input in inputs) {
612
- var buildOptionsNodeId = builderOptionsIdForAction (action, actionNum);
613
- var anchor = AssetNode .postProcessAnchorForInputAndAction (
614
- input,
615
- actionNum,
616
- buildOptionsNodeId,
657
+ updatePostProcessBuildStep (
658
+ PostProcessBuildStepId (input: input, actionNumber: actionNumber),
659
+ outputs: {},
617
660
);
618
- add (anchor);
619
- updateNode (input, (nodeBuilder) {
620
- nodeBuilder.anchorOutputs.add (anchor.id);
621
- });
622
661
}
623
- actionNum ++ ;
662
+ actionNumber ++ ;
624
663
}
625
664
}
626
665
@@ -762,11 +801,14 @@ class AssetGraph implements GeneratedAssetHider {
762
801
Digest computeBuilderOptionsDigest (BuilderOptions options) =>
763
802
md5.convert (utf8.encode (json.encode (options.config)));
764
803
765
- AssetId builderOptionsIdForAction (BuildAction action, int actionNum ) {
804
+ AssetId builderOptionsIdForAction (BuildAction action, int actionNumber ) {
766
805
if (action is InBuildPhase ) {
767
- return AssetId (action.package, 'Phase$actionNum .builderOptions' );
806
+ return AssetId (action.package, 'Phase$actionNumber .builderOptions' );
768
807
} else if (action is PostBuildAction ) {
769
- return AssetId (action.package, 'PostPhase$actionNum .builderOptions' );
808
+ return PostProcessBuildStepId .builderOptionsIdFor (
809
+ package: action.package,
810
+ actionNumber: actionNumber,
811
+ );
770
812
} else {
771
813
throw StateError ('Unsupported action type $action ' );
772
814
}
0 commit comments