diff --git a/_test_common/lib/runner_asset_writer_spy.dart b/_test_common/lib/runner_asset_writer_spy.dart index 17ace2422..233b01d69 100644 --- a/_test_common/lib/runner_asset_writer_spy.dart +++ b/_test_common/lib/runner_asset_writer_spy.dart @@ -16,11 +16,14 @@ class RunnerAssetWriterSpy extends AssetWriterSpy implements RunnerAssetWriter { RunnerAssetWriterSpy(this._delegate) : super(_delegate); @override - Future delete(AssetId id) { + Future delete(AssetId id) { _assetsDeleted.add(id); return _delegate.delete(id); } + @override + Future deleteDirectory(AssetId id) => _delegate.deleteDirectory(id); + @override Future completeBuild() async {} } diff --git a/build/lib/src/state/filesystem.dart b/build/lib/src/state/filesystem.dart index 14f4352f1..6e7a1b843 100644 --- a/build/lib/src/state/filesystem.dart +++ b/build/lib/src/state/filesystem.dart @@ -41,6 +41,11 @@ abstract interface class Filesystem { /// If the file does not exist, does nothing. void deleteSync(String path); + /// Deletes a directory recursively. + /// + /// If the directory does not exist, does nothing. + Future deleteDirectory(String path); + /// Writes a file. /// /// Creates enclosing directories as needed if they don't exist. @@ -110,6 +115,14 @@ class IoFilesystem implements Filesystem { }); } + @override + Future deleteDirectory(String path) { + return _pool.withResource(() async { + final directory = Directory(path); + if (await directory.exists()) await directory.delete(recursive: true); + }); + } + @override void writeAsBytesSync( String path, @@ -191,6 +204,13 @@ class InMemoryFilesystem implements Filesystem { @override void deleteSync(String path) => _files.remove(path); + @override + Future deleteDirectory(String path) { + final prefix = '$path/'; + _files.removeWhere((filePath, _) => filePath.startsWith(prefix)); + return Future.value(); + } + @override void writeAsBytesSync(String path, List contents) { _files[path] = Uint8List.fromList(contents); diff --git a/build_runner_core/CHANGELOG.md b/build_runner_core/CHANGELOG.md index af329e7d9..9efb33976 100644 --- a/build_runner_core/CHANGELOG.md +++ b/build_runner_core/CHANGELOG.md @@ -2,6 +2,8 @@ - Breaking: refactor `OverridableEnvironment` and `IOEnvironment` into `BuildEnvironment` +- Breaking: add `deleteDirectory` to `RunnerAssetWriter`, make `delete` + return `Future`, remove deprecated `OnDelete`. - Bump the min SDK to 3.7.0. - Fix crash when running on assets ending in a dot. - Start using `package:build/src/internal.dart'. diff --git a/build_runner_core/lib/src/asset/batch.dart b/build_runner_core/lib/src/asset/batch.dart index 221bfc9e4..d4a46a5d5 100644 --- a/build_runner_core/lib/src/asset/batch.dart +++ b/build_runner_core/lib/src/asset/batch.dart @@ -154,4 +154,7 @@ final class BatchWriter extends RunnerAssetWriter { Future completeBuild() async { await _batch.completeWrites(_inner); } + + @override + Future deleteDirectory(AssetId id) => _inner.deleteDirectory(id); } diff --git a/build_runner_core/lib/src/asset/reader_writer.dart b/build_runner_core/lib/src/asset/reader_writer.dart index 04c2f1a08..9f6a5906a 100644 --- a/build_runner_core/lib/src/asset/reader_writer.dart +++ b/build_runner_core/lib/src/asset/reader_writer.dart @@ -163,6 +163,12 @@ class ReaderWriter extends AssetReader await filesystem.delete(path); } + @override + Future deleteDirectory(AssetId id) async { + final path = _pathFor(id); + await filesystem.deleteDirectory(path); + } + @override Future completeBuild() async { // TODO(davidmorgan): add back write caching, "batching". diff --git a/build_runner_core/lib/src/asset/writer.dart b/build_runner_core/lib/src/asset/writer.dart index 9fd01c714..525c71170 100644 --- a/build_runner_core/lib/src/asset/writer.dart +++ b/build_runner_core/lib/src/asset/writer.dart @@ -6,11 +6,17 @@ import 'dart:async'; import 'package:build/build.dart'; -@Deprecated('No longer used') -typedef OnDelete = void Function(AssetId id); - abstract class RunnerAssetWriter implements AssetWriter { - Future delete(AssetId id); + /// Delete [id]. + Future delete(AssetId id); + + /// Delete the directory [id] recursively. + /// + /// Usually an `AssetId` points to a file, but here its `path` is a directory. + /// + /// Delete unconditionally and recursively: if the directory does not exist, + /// do nothing. + Future deleteDirectory(AssetId id); /// Called after each completed build. /// diff --git a/build_runner_core/lib/src/asset_graph/graph_loader.dart b/build_runner_core/lib/src/asset_graph/graph_loader.dart index dac36b0a6..bb1ef078d 100644 --- a/build_runner_core/lib/src/asset_graph/graph_loader.dart +++ b/build_runner_core/lib/src/asset_graph/graph_loader.dart @@ -10,7 +10,6 @@ import 'package:build/experiments.dart'; import 'package:built_collection/built_collection.dart'; // ignore: implementation_imports import 'package:logging/logging.dart'; -import 'package:path/path.dart' as p; import '../asset/writer.dart'; import '../asset_graph/exceptions.dart'; @@ -66,7 +65,7 @@ class AssetGraphLoader { 'version mismatch or corrupted asset graph.', ); await Future.wait([ - _deleteGeneratedDir(), + writer.deleteDirectory(_generatedOutputDirectoryId), FailureReporter.cleanErrorCache(), ]); return null; @@ -109,9 +108,9 @@ class AssetGraphLoader { ); } await Future.wait([ - _deleteAssetGraph(packageGraph), + writer.delete(assetGraphId), cachedGraph.deleteOutputs(packageGraph, writer), - _deleteGeneratedDir(), + writer.deleteDirectory(_generatedOutputDirectoryId), FailureReporter.cleanErrorCache(), ]); if (_runningFromSnapshot) { @@ -124,9 +123,9 @@ class AssetGraphLoader { 'Throwing away cached asset graph due to Dart SDK update.', ); await Future.wait([ - _deleteAssetGraph(packageGraph), + writer.delete(assetGraphId), cachedGraph.deleteOutputs(packageGraph, writer), - _deleteGeneratedDir(), + writer.deleteDirectory(_generatedOutputDirectoryId), FailureReporter.cleanErrorCache(), ]); if (_runningFromSnapshot) { @@ -136,16 +135,9 @@ class AssetGraphLoader { } return cachedGraph; } -} - -Future _deleteAssetGraph(PackageGraph packageGraph) => - File(p.join(packageGraph.root.path, assetGraphPath)).delete(); -Future _deleteGeneratedDir() async { - var generatedDir = Directory(generatedOutputDirectory); - if (await generatedDir.exists()) { - await generatedDir.delete(recursive: true); - } + AssetId get _generatedOutputDirectoryId => + AssetId(packageGraph.root.name, generatedOutputDirectory); } bool get _runningFromSnapshot => !Platform.script.path.endsWith('.dart');