Commit f888bbed authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Refactor hot/cold/drive runners a little (#7694)

Move the drive/run common stuff to RunCommandBase, rather than the
superclass which applies to everything.

Implement --no-resident (fixes
https://github.com/flutter/flutter/issues/5448). This is particularly
useful when running flutter from scripts.

Rename RunAndStayResident to ColdRunner.
parent 56eca97a
...@@ -365,7 +365,7 @@ class AppDomain extends Domain { ...@@ -365,7 +365,7 @@ class AppDomain extends Domain {
projectAssets: projectAssets, projectAssets: projectAssets,
); );
} else { } else {
runner = new RunAndStayResident( runner = new ColdRunner(
device, device,
target: target, target: target,
debuggingOptions: options, debuggingOptions: options,
......
...@@ -45,14 +45,14 @@ import 'run.dart'; ...@@ -45,14 +45,14 @@ import 'run.dart';
/// exit code. /// exit code.
class DriveCommand extends RunCommandBase { class DriveCommand extends RunCommandBase {
DriveCommand() { DriveCommand() {
usesPubOption();
argParser.addFlag( argParser.addFlag(
'keep-app-running', 'keep-app-running',
negatable: true, negatable: true,
defaultsTo: false, defaultsTo: false,
help: help:
'Will keep the Flutter application running when done testing. By ' 'Will keep the Flutter application running when done testing.\n'
'default Flutter Driver stops the application after tests are finished.' 'By default, Flutter drive stops the application after tests are finished.\n'
'Ignored if --use-existing-app is specified.'
); );
argParser.addFlag( argParser.addFlag(
...@@ -64,8 +64,6 @@ class DriveCommand extends RunCommandBase { ...@@ -64,8 +64,6 @@ class DriveCommand extends RunCommandBase {
'already running instance. This will also cause the driver to keep ' 'already running instance. This will also cause the driver to keep '
'the application running after tests are done.' 'the application running after tests are done.'
); );
usesPortOptions();
} }
@override @override
......
...@@ -20,6 +20,7 @@ import '../runner/flutter_command.dart'; ...@@ -20,6 +20,7 @@ import '../runner/flutter_command.dart';
import 'daemon.dart'; import 'daemon.dart';
abstract class RunCommandBase extends FlutterCommand { abstract class RunCommandBase extends FlutterCommand {
// Used by run and drive commands.
RunCommandBase() { RunCommandBase() {
addBuildModeFlags(defaultToRelease: false); addBuildModeFlags(defaultToRelease: false);
argParser.addFlag('trace-startup', argParser.addFlag('trace-startup',
...@@ -29,10 +30,47 @@ abstract class RunCommandBase extends FlutterCommand { ...@@ -29,10 +30,47 @@ abstract class RunCommandBase extends FlutterCommand {
argParser.addOption('route', argParser.addOption('route',
help: 'Which route to load when running the app.'); help: 'Which route to load when running the app.');
usesTargetOption(); usesTargetOption();
usesPortOptions();
usesPubOption();
} }
bool get traceStartup => argResults['trace-startup']; bool get traceStartup => argResults['trace-startup'];
String get route => argResults['route']; String get route => argResults['route'];
void usesPortOptions() {
argParser.addOption('observatory-port',
help: 'Listen to the given port for an observatory debugger connection.\n'
'Specifying port 0 will find a random free port.\n'
'Defaults to the first available port after $kDefaultObservatoryPort.'
);
argParser.addOption('diagnostic-port',
help: 'Listen to the given port for a diagnostic connection.\n'
'Specifying port 0 will find a random free port.\n'
'Defaults to the first available port after $kDefaultDiagnosticPort.'
);
}
int get observatoryPort {
if (argResults['observatory-port'] != null) {
try {
return int.parse(argResults['observatory-port']);
} catch (error) {
throwToolExit('Invalid port for `--observatory-port`: $error');
}
}
return null;
}
int get diagnosticPort {
if (argResults['diagnostic-port'] != null) {
try {
return int.parse(argResults['diagnostic-port']);
} catch (error) {
throwToolExit('Invalid port for `--diagnostic-port`: $error');
}
}
return null;
}
} }
class RunCommand extends RunCommandBase { class RunCommand extends RunCommandBase {
...@@ -50,7 +88,6 @@ class RunCommand extends RunCommandBase { ...@@ -50,7 +88,6 @@ class RunCommand extends RunCommandBase {
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
help: 'Start in a paused mode and wait for a debugger to connect.'); help: 'Start in a paused mode and wait for a debugger to connect.');
usesPortOptions();
argParser.addFlag('build', argParser.addFlag('build',
defaultsTo: true, defaultsTo: true,
help: 'If necessary, build the app before running.'); help: 'If necessary, build the app before running.');
...@@ -73,23 +110,19 @@ class RunCommand extends RunCommandBase { ...@@ -73,23 +110,19 @@ class RunCommand extends RunCommandBase {
hide: !verboseHelp, hide: !verboseHelp,
help: 'Handle machine structured JSON command input\n' help: 'Handle machine structured JSON command input\n'
'and provide output and progress in machine friendly format.'); 'and provide output and progress in machine friendly format.');
usesPubOption(); argParser.addFlag('hot',
negatable: true,
// Option to enable hot reloading. defaultsTo: kHotReloadDefault,
argParser.addFlag( help: 'Run with support for hot reloading.');
'hot', argParser.addOption('pid-file',
negatable: true, help: 'Specify a file to write the process id to.\n'
defaultsTo: kHotReloadDefault, 'You can send SIGUSR1 to trigger a hot reload\n'
help: 'Run with support for hot reloading.' 'and SIGUSR2 to trigger a full restart.');
); argParser.addFlag('resident',
negatable: true,
// Option to write the pid to a file. defaultsTo: true,
argParser.addOption( hide: !verboseHelp,
'pid-file', help: 'Stay resident after launching the application.');
help: 'Specify a file to write the process id to.\n'
'You can send SIGUSR1 to trigger a hot reload\n'
'and SIGUSR2 to trigger a full restart.'
);
// Hidden option to enable a benchmarking mode. This will run the given // Hidden option to enable a benchmarking mode. This will run the given
// application, measure the startup time and the app restart time, write the // application, measure the startup time and the app restart time, write the
...@@ -150,6 +183,8 @@ class RunCommand extends RunCommandBase { ...@@ -150,6 +183,8 @@ class RunCommand extends RunCommandBase {
bool get runningWithPrebuiltApplication => bool get runningWithPrebuiltApplication =>
argResults['use-application-binary'] != null; argResults['use-application-binary'] != null;
bool get stayResident => argResults['resident'];
@override @override
Future<Null> verifyThenRunCommand() async { Future<Null> verifyThenRunCommand() async {
commandValidator(); commandValidator();
...@@ -226,15 +261,17 @@ class RunCommand extends RunCommandBase { ...@@ -226,15 +261,17 @@ class RunCommand extends RunCommandBase {
applicationBinary: argResults['use-application-binary'], applicationBinary: argResults['use-application-binary'],
projectRootPath: argResults['project-root'], projectRootPath: argResults['project-root'],
packagesFilePath: argResults['packages'], packagesFilePath: argResults['packages'],
projectAssets: argResults['project-assets'] projectAssets: argResults['project-assets'],
stayResident: stayResident,
); );
} else { } else {
runner = new RunAndStayResident( runner = new ColdRunner(
device, device,
target: targetFile, target: targetFile,
debuggingOptions: options, debuggingOptions: options,
traceStartup: traceStartup, traceStartup: traceStartup,
applicationBinary: argResults['use-application-binary'] applicationBinary: argResults['use-application-binary'],
stayResident: stayResident,
); );
} }
......
...@@ -46,13 +46,15 @@ class HotRunner extends ResidentRunner { ...@@ -46,13 +46,15 @@ class HotRunner extends ResidentRunner {
String projectRootPath, String projectRootPath,
String packagesFilePath, String packagesFilePath,
String projectAssets, String projectAssets,
bool stayResident,
}) : super(device, }) : super(device,
target: target, target: target,
debuggingOptions: debuggingOptions, debuggingOptions: debuggingOptions,
usesTerminalUI: usesTerminalUI, usesTerminalUI: usesTerminalUI,
projectRootPath: projectRootPath, projectRootPath: projectRootPath,
packagesFilePath: packagesFilePath, packagesFilePath: packagesFilePath,
projectAssets: projectAssets); projectAssets: projectAssets,
stayResident: stayResident);
final String applicationBinary; final String applicationBinary;
bool get prebuiltMode => applicationBinary != null; bool get prebuiltMode => applicationBinary != null;
...@@ -207,9 +209,10 @@ class HotRunner extends ResidentRunner { ...@@ -207,9 +209,10 @@ class HotRunner extends ResidentRunner {
await vmService.vm.refreshViews(); await vmService.vm.refreshViews();
printTrace('Connected to ${vmService.vm.mainView}.'); printTrace('Connected to ${vmService.vm.mainView}.');
setupTerminal(); if (stayResident) {
setupTerminal();
registerSignalHandlers(); registerSignalHandlers();
}
appStartedCompleter?.complete(); appStartedCompleter?.complete();
...@@ -232,7 +235,10 @@ class HotRunner extends ResidentRunner { ...@@ -232,7 +235,10 @@ class HotRunner extends ResidentRunner {
benchmarkOutput.writeAsStringSync(toPrettyJson(benchmarkData)); benchmarkOutput.writeAsStringSync(toPrettyJson(benchmarkData));
} }
return waitForAppToFinish(); if (stayResident)
return waitForAppToFinish();
await cleanupAtFinish();
return 0;
} }
@override @override
......
...@@ -33,6 +33,7 @@ abstract class ResidentRunner { ...@@ -33,6 +33,7 @@ abstract class ResidentRunner {
String projectRootPath, String projectRootPath,
String packagesFilePath, String packagesFilePath,
String projectAssets, String projectAssets,
this.stayResident,
}) { }) {
_mainPath = findMainDartFile(target); _mainPath = findMainDartFile(target);
_projectRootPath = projectRootPath ?? fs.currentDirectory.path; _projectRootPath = projectRootPath ?? fs.currentDirectory.path;
...@@ -48,6 +49,7 @@ abstract class ResidentRunner { ...@@ -48,6 +49,7 @@ abstract class ResidentRunner {
final String target; final String target;
final DebuggingOptions debuggingOptions; final DebuggingOptions debuggingOptions;
final bool usesTerminalUI; final bool usesTerminalUI;
final bool stayResident;
final Completer<int> _finished = new Completer<int>(); final Completer<int> _finished = new Completer<int>();
String _packagesFilePath; String _packagesFilePath;
String get packagesFilePath => _packagesFilePath; String get packagesFilePath => _packagesFilePath;
...@@ -107,6 +109,7 @@ abstract class ResidentRunner { ...@@ -107,6 +109,7 @@ abstract class ResidentRunner {
} }
void registerSignalHandlers() { void registerSignalHandlers() {
assert(stayResident);
ProcessSignal.SIGINT.watch().listen((ProcessSignal signal) async { ProcessSignal.SIGINT.watch().listen((ProcessSignal signal) async {
_resetTerminal(); _resetTerminal();
await cleanupAfterSignal(); await cleanupAfterSignal();
...@@ -243,6 +246,7 @@ abstract class ResidentRunner { ...@@ -243,6 +246,7 @@ abstract class ResidentRunner {
} }
void setupTerminal() { void setupTerminal() {
assert(stayResident);
if (usesTerminalUI) { if (usesTerminalUI) {
if (!logger.quiet) { if (!logger.quiet) {
printStatus(''); printStatus('');
......
...@@ -16,18 +16,20 @@ import 'device.dart'; ...@@ -16,18 +16,20 @@ import 'device.dart';
import 'globals.dart'; import 'globals.dart';
import 'resident_runner.dart'; import 'resident_runner.dart';
class RunAndStayResident extends ResidentRunner { class ColdRunner extends ResidentRunner {
RunAndStayResident( ColdRunner(
Device device, { Device device, {
String target, String target,
DebuggingOptions debuggingOptions, DebuggingOptions debuggingOptions,
bool usesTerminalUI: true, bool usesTerminalUI: true,
this.traceStartup: false, this.traceStartup: false,
this.applicationBinary this.applicationBinary,
bool stayResident,
}) : super(device, }) : super(device,
target: target, target: target,
debuggingOptions: debuggingOptions, debuggingOptions: debuggingOptions,
usesTerminalUI: usesTerminalUI); usesTerminalUI: usesTerminalUI,
stayResident: stayResident);
LaunchResult _result; LaunchResult _result;
final bool traceStartup; final bool traceStartup;
...@@ -147,14 +149,17 @@ class RunAndStayResident extends ResidentRunner { ...@@ -147,14 +149,17 @@ class RunAndStayResident extends ResidentRunner {
return 2; return 2;
} }
appFinished(); appFinished();
} else { } else if (stayResident) {
setupTerminal(); setupTerminal();
registerSignalHandlers(); registerSignalHandlers();
} }
appStartedCompleter?.complete(); appStartedCompleter?.complete();
return waitForAppToFinish(); if (stayResident)
return waitForAppToFinish();
await cleanupAtFinish();
return 0;
} }
@override @override
......
...@@ -63,41 +63,6 @@ abstract class FlutterCommand extends Command<Null> { ...@@ -63,41 +63,6 @@ abstract class FlutterCommand extends Command<Null> {
_usesPubOption = true; _usesPubOption = true;
} }
void usesPortOptions() {
argParser.addOption('observatory-port',
help: 'Listen to the given port for an observatory debugger connection.\n'
'Specifying port 0 will find a random free port.\n'
'Defaults to the first available port after $kDefaultObservatoryPort.'
);
argParser.addOption('diagnostic-port',
help: 'Listen to the given port for a diagnostic connection.\n'
'Specifying port 0 will find a random free port.\n'
'Defaults to the first available port after $kDefaultDiagnosticPort.'
);
}
int get observatoryPort {
if (argResults['observatory-port'] != null) {
try {
return int.parse(argResults['observatory-port']);
} catch (error) {
throwToolExit('Invalid port for `--observatory-port`: $error');
}
}
return null;
}
int get diagnosticPort {
if (argResults['diagnostic-port'] != null) {
try {
return int.parse(argResults['diagnostic-port']);
} catch (error) {
throwToolExit('Invalid port for `--diagnostic-port`: $error');
}
}
return null;
}
void addBuildModeFlags({ bool defaultToRelease: true }) { void addBuildModeFlags({ bool defaultToRelease: true }) {
defaultBuildMode = defaultToRelease ? BuildMode.release : BuildMode.debug; defaultBuildMode = defaultToRelease ? BuildMode.release : BuildMode.debug;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment