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