@@ -14,6 +14,7 @@ import 'package:build/src/internal.dart';
1414import 'package:built_collection/built_collection.dart' ;
1515import 'package:crypto/crypto.dart' ;
1616import 'package:glob/glob.dart' ;
17+ import 'package:meta/meta.dart' ;
1718import 'package:package_config/package_config.dart' ;
1819import 'package:watcher/watcher.dart' ;
1920
@@ -23,6 +24,8 @@ import '../generate/phase.dart';
2324import '../util/constants.dart' ;
2425import 'exceptions.dart' ;
2526import 'node.dart' ;
27+ import 'post_process_build_step_id.dart' ;
28+ import 'serializers.dart' ;
2629
2730part 'serialization.dart' ;
2831
@@ -46,6 +49,14 @@ class AssetGraph implements GeneratedAssetHider {
4649
4750 final BuiltMap <String , LanguageVersion ?> packageLanguageVersions;
4851
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+
4960 AssetGraph ._(
5061 this .buildPhasesDigest,
5162 this .dartVersion,
@@ -93,6 +104,10 @@ class AssetGraph implements GeneratedAssetHider {
93104
94105 List <int > serialize () => _AssetGraphSerializer (this ).serialize ();
95106
107+ @visibleForTesting
108+ Map <String , Map <PostProcessBuildStepId , Set <AssetId >>>
109+ get allPostProcessBuildStepOutputs => _postProcessBuildStepOutputs;
110+
96111 /// Checks if [id] exists in the graph.
97112 bool contains (AssetId id) =>
98113 _nodesByPackage[id.package]? .containsKey (id.path) ?? false ;
@@ -243,9 +258,6 @@ class AssetGraph implements GeneratedAssetHider {
243258 var node = get (id);
244259 if (node == null ) return removedIds;
245260 removedIds.add (id);
246- for (var anchor in node.anchorOutputs.toList ()) {
247- _removeRecursive (anchor, removedIds: removedIds);
248- }
249261 for (var output in node.primaryOutputs.toList ()) {
250262 _removeRecursive (output, removedIds: removedIds);
251263 }
@@ -290,6 +302,12 @@ class AssetGraph implements GeneratedAssetHider {
290302 if (node.type != NodeType .missingSource) {
291303 _nodesByPackage[id.package]! .remove (id.path);
292304 }
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+
293311 return removedIds;
294312 }
295313
@@ -301,6 +319,31 @@ class AssetGraph implements GeneratedAssetHider {
301319 Iterable <AssetNode > packageNodes (String package) =>
302320 _nodesByPackage[package]? .values ?? [];
303321
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+
304347 /// All the generated outputs in the graph.
305348 Iterable <AssetId > get outputs =>
306349 allNodes.where ((n) => n.type == NodeType .generated).map ((n) => n.id);
@@ -547,7 +590,7 @@ class AssetGraph implements GeneratedAssetHider {
547590 ),
548591 );
549592 } else if (phase is PostBuildPhase ) {
550- _addPostBuildPhaseAnchors (phase, allInputs);
593+ _addPostBuildActionApplications (phase, allInputs);
551594 } else {
552595 throw StateError ('Unrecognized phase type $phase ' );
553596 }
@@ -600,27 +643,21 @@ class AssetGraph implements GeneratedAssetHider {
600643 return phaseOutputs;
601644 }
602645
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 ;
609652 for (var action in phase.builderActions) {
610653 var inputs = allInputs.where ((input) => _actionMatches (action, input));
611654 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: {},
617658 );
618- add (anchor);
619- updateNode (input, (nodeBuilder) {
620- nodeBuilder.anchorOutputs.add (anchor.id);
621- });
622659 }
623- actionNum ++ ;
660+ actionNumber ++ ;
624661 }
625662 }
626663
@@ -762,11 +799,14 @@ class AssetGraph implements GeneratedAssetHider {
762799Digest computeBuilderOptionsDigest (BuilderOptions options) =>
763800 md5.convert (utf8.encode (json.encode (options.config)));
764801
765- AssetId builderOptionsIdForAction (BuildAction action, int actionNum ) {
802+ AssetId builderOptionsIdForAction (BuildAction action, int actionNumber ) {
766803 if (action is InBuildPhase ) {
767- return AssetId (action.package, 'Phase$actionNum .builderOptions' );
804+ return AssetId (action.package, 'Phase$actionNumber .builderOptions' );
768805 } 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+ );
770810 } else {
771811 throw StateError ('Unsupported action type $action ' );
772812 }
0 commit comments