@@ -201,8 +201,6 @@ class AssetGraph implements GeneratedAssetHider {
201
201
var existing = get (node.id);
202
202
if (existing != null ) {
203
203
if (existing.type == NodeType .missingSource) {
204
- // Don't call _removeRecursive, that recursively removes all transitive
205
- // primary outputs. We only want to remove this node.
206
204
_nodesByPackage[existing.id.package]! .remove (existing.id.path);
207
205
node = node.rebuild ((b) {
208
206
b.primaryOutputs.addAll (existing.primaryOutputs);
@@ -263,60 +261,23 @@ class AssetGraph implements GeneratedAssetHider {
263
261
);
264
262
}
265
263
266
- /// Removes the node representing [id] from the graph, and all of its
267
- /// `primaryOutput` s.
268
- ///
269
- /// Also removes all edges between all removed nodes and remaining nodes.
270
- ///
271
- /// Returns the IDs of removed asset nodes.
272
- Set <AssetId > _removeRecursive (AssetId id, {Set <AssetId >? removedIds}) {
264
+ /// Changes [id] and its transitive`primaryOutput` s to `missingSource` nodes.
265
+ void _setMissingRecursive (AssetId id, {Set <AssetId >? removedIds}) {
273
266
removedIds ?? = < AssetId > {};
274
267
var node = get (id);
275
- if (node == null ) return removedIds ;
268
+ if (node == null ) return ;
276
269
removedIds.add (id);
277
270
for (var output in node.primaryOutputs.toList ()) {
278
- _removeRecursive (output, removedIds: removedIds);
279
- }
280
- final outputs = computeOutputs ();
281
- for (var output in (outputs[node.id] ?? const < AssetId > {})) {
282
- updateNodeIfPresent (output, (nodeBuilder) {
283
- if (nodeBuilder.type == NodeType .generated) {
284
- nodeBuilder.generatedNodeState.inputs.remove (id);
285
- } else if (nodeBuilder.type == NodeType .glob) {
286
- nodeBuilder.globNodeState
287
- ..inputs.remove (id)
288
- ..results.remove (id);
289
- }
290
- });
291
- }
292
-
293
- if (node.type == NodeType .generated) {
294
- for (var input in node.generatedNodeState! .inputs) {
295
- // We may have already removed this node entirely.
296
- updateNodeIfPresent (input, (nodeBuilder) {
297
- nodeBuilder.primaryOutputs.remove (id);
298
- });
299
- }
300
- } else if (node.type == NodeType .glob) {
301
- for (var input in node.globNodeState! .inputs) {
302
- // We may have already removed this node entirely.
303
- updateNodeIfPresent (input, (nodeBuilder) {
304
- nodeBuilder.primaryOutputs.remove (id);
305
- });
306
- }
307
- }
308
-
309
- // Missing source nodes need to be kept to retain dependency tracking.
310
- if (node.type != NodeType .missingSource) {
311
- _nodesByPackage[id.package]! .remove (id.path);
271
+ _setMissingRecursive (output, removedIds: removedIds);
312
272
}
273
+ updateNode (id, (nodeBuilder) {
274
+ nodeBuilder.replace (AssetNode .missingSource (id));
275
+ });
313
276
314
277
// Remove post build action applications with removed assets as inputs.
315
278
for (final packageOutputs in _postProcessBuildStepOutputs.values) {
316
279
packageOutputs.removeWhere ((id, _) => removedIds! .contains (id.input));
317
280
}
318
-
319
- return removedIds;
320
281
}
321
282
322
283
/// Computes node outputs: the inverse of the graph described by the `inputs`
@@ -401,8 +362,12 @@ class AssetGraph implements GeneratedAssetHider {
401
362
/// Updates graph structure, invalidating and deleting any outputs that were
402
363
/// affected.
403
364
///
404
- /// Returns the list of [AssetId] s that were invalidated.
405
- Future <Set <AssetId >> updateAndInvalidate (
365
+ /// Outputs that are deleted from the filesystem are retained in the graph as
366
+ /// `missingSource` nodes.
367
+ ///
368
+ /// Returns the set of [AssetId] s that were deleted, and the set that was
369
+ /// invalidated.
370
+ Future <(Set <AssetId >, Set <AssetId >)> updateAndInvalidate (
406
371
BuildPhases buildPhases,
407
372
Map <AssetId , ChangeType > updates,
408
373
String rootPackage,
@@ -572,23 +537,22 @@ class AssetGraph implements GeneratedAssetHider {
572
537
}
573
538
}
574
539
575
- // Delete all the invalidated assets, then remove them from the graph. This
576
- // order is important because some `AssetWriter`s throw if the id is not in
577
- // the graph.
540
+ // Delete all the invalidated assets.
578
541
await Future .wait (idsToDelete.map (delete));
579
542
580
- // Remove all deleted source assets from the graph, which also recursively
581
- // removes all their primary outputs.
543
+ // Change deleted source assets and their transitive primary outputs to
544
+ // `missingSource` nodes, rather than deleting them. This allows them to
545
+ // remain referenced in `inputs` in order to trigger rebuilds if necessary.
582
546
for (final id in removeIds) {
583
547
final node = get (id);
584
548
if (node != null && node.type == NodeType .source) {
585
549
invalidateNodeAndDeps (id);
586
- _removeRecursive (id);
550
+ _setMissingRecursive (id);
587
551
}
588
552
}
589
553
590
554
_outputs = null ;
591
- return invalidatedIds;
555
+ return (idsToDelete, invalidatedIds) ;
592
556
}
593
557
594
558
/// Crawl up primary inputs to see if the original Source file matches the
@@ -713,9 +677,9 @@ class AssetGraph implements GeneratedAssetHider {
713
677
///
714
678
/// If there are existing [AssetNode.source] s or [AssetNode.missingSource] s
715
679
/// that overlap the [AssetNode.generated] s, then they will be replaced with
716
- /// [AssetNode.generated] s, and all their `primaryOutputs` will be removed
717
- /// from from the graph as well . The return value is the set of assets that
718
- /// were removed from the graph.
680
+ /// [AssetNode.generated] s, and their transitive `primaryOutputs` will be
681
+ /// changed to `missingSource` nodes . The return value is the set of assets
682
+ /// that were removed from the graph.
719
683
Set <AssetId > _addGeneratedOutputs (
720
684
Iterable <AssetId > outputs,
721
685
int phaseNumber,
@@ -745,7 +709,7 @@ class AssetGraph implements GeneratedAssetHider {
745
709
buildPhases.inBuildPhases[phaseNumber].builderLabel,
746
710
);
747
711
}
748
- _removeRecursive (output, removedIds: removed);
712
+ _setMissingRecursive (output, removedIds: removed);
749
713
}
750
714
751
715
var newNode = AssetNode .generated (
@@ -769,9 +733,16 @@ class AssetGraph implements GeneratedAssetHider {
769
733
@override
770
734
String toString () => allNodes.toList ().toString ();
771
735
772
- // TODO remove once tests are updated
773
736
void add (AssetNode node) => _add (node);
774
- Set <AssetId > remove (AssetId id) => _removeRecursive (id);
737
+
738
+ /// Removes a generated node that was output by a post process build step.
739
+ /// TODO(davidmorgan): look at removing them from the graph altogether.
740
+ void removePostProcessOutput (AssetId id) {
741
+ _nodesByPackage[id.package]! .remove (id.path);
742
+ }
743
+
744
+ void removeForTest (AssetId id) =>
745
+ _nodesByPackage[id.package]? .remove (id.path);
775
746
776
747
/// Adds [input] to all [outputs] if they track inputs.
777
748
///
0 commit comments