blob: 9aa4fba48cad81336c0c91d573accfe576b9f2f1 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:build_runner_core/build_runner_core.dart';
import 'package:build_runner_core/src/asset_graph/graph.dart';
import 'package:build_runner_core/src/asset_graph/node.dart';
import 'package:logging/logging.dart';
import '../logging/std_io_logging.dart';
import 'base_command.dart';
class CleanCommand extends Command<int> {
@override
final argParser = ArgParser(usageLineLength: lineLength);
@override
String get name => 'clean';
@override
String get description =>
'Cleans up output from previous builds. Does not clean up --output '
'directories.';
Logger get logger => Logger(name);
@override
Future<int> run() async {
var logSubscription = Logger.root.onRecord.listen(stdIOLogListener());
await cleanFor(assetGraphPath, logger);
await logSubscription.cancel();
return 0;
}
}
Future<void> cleanFor(String assetGraphPath, Logger logger) async {
logger.warning('Deleting cache and generated source files.\n'
'This shouldn\'t be necessary for most applications, unless you have '
'made intentional edits to generated files (i.e. for testing). '
'Consider filing a bug at '
'https://github.com/dart-lang/build/issues/new if you are using this '
'to work around an apparent (and reproducible) bug.');
await logTimedAsync(logger, 'Cleaning up source outputs', () async {
var assetGraphFile = File(assetGraphPath);
if (!assetGraphFile.existsSync()) {
logger.warning('No asset graph found. '
'Skipping cleanup of generated files in source directories.');
return;
}
AssetGraph assetGraph;
try {
assetGraph = AssetGraph.deserialize(await assetGraphFile.readAsBytes());
} catch (_) {
logger.warning('Failed to deserialize AssetGraph. '
'Skipping cleanup of generated files in source directories.');
return;
}
var packageGraph = PackageGraph.forThisPackage();
await _cleanUpSourceOutputs(assetGraph, packageGraph);
});
await logTimedAsync(
logger, 'Cleaning up cache directory', _cleanUpGeneratedDirectory);
}
Future<void> _cleanUpSourceOutputs(
AssetGraph assetGraph, PackageGraph packageGraph) async {
var writer = FileBasedAssetWriter(packageGraph);
for (var id in assetGraph.outputs) {
if (id.package != packageGraph.root.name) continue;
var node = assetGraph.get(id) as GeneratedAssetNode;
if (node.wasOutput) {
// Note that this does a file.exists check in the root package and
// only tries to delete the file if it exists. This way we only
// actually delete to_source outputs, without reading in the build
// actions.
await writer.delete(id);
}
}
}
Future<void> _cleanUpGeneratedDirectory() async {
var generatedDir = Directory(cacheDir);
if (await generatedDir.exists()) {
await generatedDir.delete(recursive: true);
}
}