blob: fea22ac7c39e6938c30352fa7ef0dfb5e80d6a19 [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 'package:build_runner/src/entrypoint/options.dart';
import 'package:build_runner_core/build_runner_core.dart';
import 'package:io/io.dart';
import '../generate/build.dart';
import 'base_command.dart';
/// A command that watches the file system for updates and rebuilds as
/// appropriate.
class WatchCommand extends BuildRunnerCommand {
@override
String get invocation => '${super.invocation} [directories]';
@override
String get name => 'watch';
@override
String get description =>
'Builds the specified targets, watching the file system for updates and '
'rebuilding as appropriate.';
WatchCommand() {
argParser.addFlag(usePollingWatcherOption,
help: 'Use a polling watcher instead of the current platforms default '
'watcher implementation. This should generally only be used if '
'you are having problems with the default watcher, as it is '
'generally less efficient.');
}
@override
WatchOptions readOptions() => WatchOptions.fromParsedArgs(
argResults, argResults.rest, packageGraph.root.name, this);
@override
Future<int> run() async {
var options = readOptions();
var handler = await watch(
builderApplications,
deleteFilesByDefault: options.deleteFilesByDefault,
enableLowResourcesMode: options.enableLowResourcesMode,
configKey: options.configKey,
buildDirs: options.buildDirs,
outputSymlinksOnly: options.outputSymlinksOnly,
packageGraph: packageGraph,
trackPerformance: options.trackPerformance,
skipBuildScriptCheck: options.skipBuildScriptCheck,
verbose: options.verbose,
builderConfigOverrides: options.builderConfigOverrides,
isReleaseBuild: options.isReleaseBuild,
logPerformanceDir: options.logPerformanceDir,
directoryWatcherFactory: options.directoryWatcherFactory,
buildFilters: options.buildFilters,
);
if (handler == null) return ExitCode.config.code;
final completer = Completer<int>();
handleBuildResultsStream(handler.buildResults, completer);
return completer.future;
}
/// Listens to [buildResults], handling certain types of errors and completing
/// [completer] appropriately.
void handleBuildResultsStream(
Stream<BuildResult> buildResults, Completer<int> completer) async {
var subscription = buildResults.listen((result) {
if (completer.isCompleted) return;
if (result.status == BuildStatus.failure) {
if (result.failureType == FailureType.buildScriptChanged) {
completer.completeError(BuildScriptChangedException());
} else if (result.failureType == FailureType.buildConfigChanged) {
completer.completeError(BuildConfigChangedException());
}
}
});
await subscription.asFuture();
if (!completer.isCompleted) completer.complete(ExitCode.success.code);
}
}