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