@@ -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,8 @@ 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' ;
28
+ import 'serializers.dart' ;
26
29
27
30
part 'serialization.dart' ;
28
31
@@ -46,6 +49,14 @@ class AssetGraph implements GeneratedAssetHider {
46
49
47
50
final BuiltMap <String , LanguageVersion ?> packageLanguageVersions;
48
51
52
+ /// All post process build steps outputs, indexed by package then
53
+ /// [PostProcessBuildStepId] .
54
+ ///
55
+ /// Created with empty outputs at the start of the build if it's a new build
56
+ /// step; or deserialized with previous build outputs if it has run before.
57
+ final Map <String , Map <PostProcessBuildStepId , Set <AssetId >>>
58
+ _postProcessBuildStepOutputs = {};
59
+
49
60
AssetGraph ._(
50
61
this .buildPhasesDigest,
51
62
this .dartVersion,
@@ -93,6 +104,10 @@ class AssetGraph implements GeneratedAssetHider {
93
104
94
105
List <int > serialize () => _AssetGraphSerializer (this ).serialize ();
95
106
107
+ @visibleForTesting
108
+ Map <String , Map <PostProcessBuildStepId , Set <AssetId >>>
109
+ get allPostProcessBuildStepOutputs => _postProcessBuildStepOutputs;
110
+
96
111
/// Checks if [id] exists in the graph.
97
112
bool contains (AssetId id) =>
98
113
_nodesByPackage[id.package]? .containsKey (id.path) ?? false ;
@@ -243,9 +258,6 @@ class AssetGraph implements GeneratedAssetHider {
243
258
var node = get (id);
244
259
if (node == null ) return removedIds;
245
260
removedIds.add (id);
246
- for (var anchor in node.anchorOutputs.toList ()) {
247
- _removeRecursive (anchor, removedIds: removedIds);
248
- }
249
261
for (var output in node.primaryOutputs.toList ()) {
250
262
_removeRecursive (output, removedIds: removedIds);
251
263
}
@@ -290,6 +302,12 @@ class AssetGraph implements GeneratedAssetHider {
290
302
if (node.type != NodeType .missingSource) {
291
303
_nodesByPackage[id.package]! .remove (id.path);
292
304
}
305
+
306
+ // Remove post build action applications with removed assets as inputs.
307
+ for (final packageOutputs in _postProcessBuildStepOutputs.values) {
308
+ packageOutputs.removeWhere ((id, _) => removedIds! .contains (id.input));
309
+ }
310
+
293
311
return removedIds;
294
312
}
295
313
@@ -301,6 +319,31 @@ class AssetGraph implements GeneratedAssetHider {
301
319
Iterable <AssetNode > packageNodes (String package) =>
302
320
_nodesByPackage[package]? .values ?? [];
303
321
322
+ /// All the post process build steps for `package` .
323
+ Iterable <PostProcessBuildStepId > postProcessBuildStepIds ({
324
+ required String package,
325
+ }) => _postProcessBuildStepOutputs[package]? .keys ?? const [];
326
+
327
+ /// Creates or updates state for a [PostProcessBuildStepId] .
328
+ void updatePostProcessBuildStep (
329
+ PostProcessBuildStepId buildStepId, {
330
+ required Set <AssetId > outputs,
331
+ }) {
332
+ _postProcessBuildStepOutputs.putIfAbsent (
333
+ buildStepId.input.package,
334
+ () => {},
335
+ )[buildStepId] =
336
+ outputs;
337
+ }
338
+
339
+ /// Gets outputs of a [PostProcessBuildStepId] .
340
+ ///
341
+ /// These are set using [updatePostProcessBuildStep] during the build, then
342
+ /// used to clean up prior outputs in the next build.
343
+ Iterable <AssetId > postProcessBuildStepOutputs (PostProcessBuildStepId action) {
344
+ return _postProcessBuildStepOutputs[action.input.package]! [action]! ;
345
+ }
346
+
304
347
/// All the generated outputs in the graph.
305
348
Iterable <AssetId > get outputs =>
306
349
allNodes.where ((n) => n.type == NodeType .generated).map ((n) => n.id);
@@ -547,7 +590,7 @@ class AssetGraph implements GeneratedAssetHider {
547
590
),
548
591
);
549
592
} else if (phase is PostBuildPhase ) {
550
- _addPostBuildPhaseAnchors (phase, allInputs);
593
+ _addPostBuildActionApplications (phase, allInputs);
551
594
} else {
552
595
throw StateError ('Unrecognized phase type $phase ' );
553
596
}
@@ -600,27 +643,21 @@ class AssetGraph implements GeneratedAssetHider {
600
643
return phaseOutputs;
601
644
}
602
645
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 ;
646
+ /// Adds all [PostProcessBuildStepId ] s for [phase] given [allInputs] ;
647
+ void _addPostBuildActionApplications (
648
+ PostBuildPhase phase,
649
+ Set < AssetId > allInputs,
650
+ ) {
651
+ var actionNumber = 0 ;
609
652
for (var action in phase.builderActions) {
610
653
var inputs = allInputs.where ((input) => _actionMatches (action, input));
611
654
for (var input in inputs) {
612
- var buildOptionsNodeId = builderOptionsIdForAction (action, actionNum);
613
- var anchor = AssetNode .postProcessAnchorForInputAndAction (
614
- input,
615
- actionNum,
616
- buildOptionsNodeId,
655
+ updatePostProcessBuildStep (
656
+ PostProcessBuildStepId (input: input, actionNumber: actionNumber),
657
+ outputs: {},
617
658
);
618
- add (anchor);
619
- updateNode (input, (nodeBuilder) {
620
- nodeBuilder.anchorOutputs.add (anchor.id);
621
- });
622
659
}
623
- actionNum ++ ;
660
+ actionNumber ++ ;
624
661
}
625
662
}
626
663
@@ -762,11 +799,14 @@ class AssetGraph implements GeneratedAssetHider {
762
799
Digest computeBuilderOptionsDigest (BuilderOptions options) =>
763
800
md5.convert (utf8.encode (json.encode (options.config)));
764
801
765
- AssetId builderOptionsIdForAction (BuildAction action, int actionNum ) {
802
+ AssetId builderOptionsIdForAction (BuildAction action, int actionNumber ) {
766
803
if (action is InBuildPhase ) {
767
- return AssetId (action.package, 'Phase$actionNum .builderOptions' );
804
+ return AssetId (action.package, 'Phase$actionNumber .builderOptions' );
768
805
} else if (action is PostBuildAction ) {
769
- return AssetId (action.package, 'PostPhase$actionNum .builderOptions' );
806
+ return PostProcessBuildStepId .builderOptionsIdFor (
807
+ package: action.package,
808
+ actionNumber: actionNumber,
809
+ );
770
810
} else {
771
811
throw StateError ('Unsupported action type $action ' );
772
812
}
0 commit comments