Commit fb3bf7a9 authored by John McCutchan's avatar John McCutchan Committed by GitHub

Support hot reload with a prebuilt loader (#6743)

parent 10d20c77
...@@ -785,7 +785,6 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -785,7 +785,6 @@ class _AdbLogReader extends DeviceLogReader {
DateTime time = _adbTimestampToDateTime(timestamp); DateTime time = _adbTimestampToDateTime(timestamp);
if (time.isBefore(_timeOrigin)) { if (time.isBefore(_timeOrigin)) {
// Ignore log messages before the origin. // Ignore log messages before the origin.
printTrace('skipped old log line: $line');
return; return;
} }
} }
...@@ -816,7 +815,6 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -816,7 +815,6 @@ class _AdbLogReader extends DeviceLogReader {
return; return;
} }
} }
printTrace('skipped log line: $line');
} }
void _stop() { void _stop() {
......
...@@ -62,6 +62,15 @@ class RunCommand extends RunCommandBase { ...@@ -62,6 +62,15 @@ class RunCommand extends RunCommandBase {
argParser.addOption('use-application-binary', argParser.addOption('use-application-binary',
hide: !verboseHelp, hide: !verboseHelp,
help: 'Specify a pre-built application binary to use when running.'); help: 'Specify a pre-built application binary to use when running.');
argParser.addOption('snapshotter',
hide: !verboseHelp,
help: 'Specify the path to the sky_snapshot binary.');
argParser.addOption('packages',
hide: !verboseHelp,
help: 'Specify the path to the .packages file.');
argParser.addOption('project_root',
hide: !verboseHelp,
help: 'Specify the project root directory.');
argParser.addFlag('machine', argParser.addFlag('machine',
hide: !verboseHelp, hide: !verboseHelp,
help: 'Handle machine structured JSON command input\n' help: 'Handle machine structured JSON command input\n'
...@@ -138,7 +147,7 @@ class RunCommand extends RunCommandBase { ...@@ -138,7 +147,7 @@ class RunCommand extends RunCommandBase {
bool shouldUseHotMode() { bool shouldUseHotMode() {
bool hotArg = argResults['hot'] ?? false; bool hotArg = argResults['hot'] ?? false;
final bool shouldUseHotMode = hotArg && !runningWithPrebuiltApplication; final bool shouldUseHotMode = hotArg;
return (getBuildMode() == BuildMode.debug) && shouldUseHotMode; return (getBuildMode() == BuildMode.debug) && shouldUseHotMode;
} }
...@@ -220,7 +229,10 @@ class RunCommand extends RunCommandBase { ...@@ -220,7 +229,10 @@ class RunCommand extends RunCommandBase {
device, device,
target: targetFile, target: targetFile,
debuggingOptions: options, debuggingOptions: options,
benchmarkMode: argResults['benchmark'] benchmarkMode: argResults['benchmark'],
applicationBinary: argResults['use-application-binary'],
projectRootPath: argResults['project_root'],
packagesFilePath: argResults['packages'],
); );
} else { } else {
runner = new RunAndStayResident( runner = new RunAndStayResident(
......
...@@ -252,20 +252,31 @@ class DevFS { ...@@ -252,20 +252,31 @@ class DevFS {
/// Create a [DevFS] named [fsName] for the local files in [directory]. /// Create a [DevFS] named [fsName] for the local files in [directory].
DevFS(VMService serviceProtocol, DevFS(VMService serviceProtocol,
String fsName, String fsName,
this.rootDirectory) this.rootDirectory, {
String packagesFilePath
})
: _operations = new ServiceProtocolDevFSOperations(serviceProtocol), : _operations = new ServiceProtocolDevFSOperations(serviceProtocol),
_httpWriter = new _DevFSHttpWriter(fsName, serviceProtocol), _httpWriter = new _DevFSHttpWriter(fsName, serviceProtocol),
fsName = fsName; fsName = fsName {
_packagesFilePath =
packagesFilePath ?? path.join(rootDirectory.path, kPackagesFileName);
}
DevFS.operations(this._operations, DevFS.operations(this._operations,
this.fsName, this.fsName,
this.rootDirectory) this.rootDirectory, {
: _httpWriter = null; String packagesFilePath,
})
: _httpWriter = null {
_packagesFilePath =
packagesFilePath ?? path.join(rootDirectory.path, kPackagesFileName);
}
final DevFSOperations _operations; final DevFSOperations _operations;
final _DevFSHttpWriter _httpWriter; final _DevFSHttpWriter _httpWriter;
final String fsName; final String fsName;
final Directory rootDirectory; final Directory rootDirectory;
String _packagesFilePath;
final Map<String, DevFSEntry> _entries = <String, DevFSEntry>{}; final Map<String, DevFSEntry> _entries = <String, DevFSEntry>{};
final Set<DevFSEntry> _dirtyEntries = new Set<DevFSEntry>(); final Set<DevFSEntry> _dirtyEntries = new Set<DevFSEntry>();
final Set<DevFSEntry> _deletedEntries = new Set<DevFSEntry>(); final Set<DevFSEntry> _deletedEntries = new Set<DevFSEntry>();
...@@ -318,10 +329,10 @@ class DevFS { ...@@ -318,10 +329,10 @@ class DevFS {
fileFilter: fileFilter); fileFilter: fileFilter);
printTrace('Scanning package files'); printTrace('Scanning package files');
String packagesFilePath = path.join(rootDirectory.path, kPackagesFileName);
StringBuffer sb; StringBuffer sb;
if (FileSystemEntity.isFileSync(packagesFilePath)) { if (FileSystemEntity.isFileSync(_packagesFilePath)) {
PackageMap packageMap = new PackageMap(kPackagesFileName); PackageMap packageMap = new PackageMap(_packagesFilePath);
for (String packageName in packageMap.map.keys) { for (String packageName in packageMap.map.keys) {
Uri uri = packageMap.map[packageName]; Uri uri = packageMap.map[packageName];
......
...@@ -40,10 +40,12 @@ String getDevFSLoaderScript() { ...@@ -40,10 +40,12 @@ String getDevFSLoaderScript() {
class DartDependencySetBuilder { class DartDependencySetBuilder {
DartDependencySetBuilder(this.mainScriptPath, DartDependencySetBuilder(this.mainScriptPath,
this.projectRootPath); this.projectRootPath,
this.packagesFilePath);
final String mainScriptPath; final String mainScriptPath;
final String projectRootPath; final String projectRootPath;
final String packagesFilePath;
Set<String> build() { Set<String> build() {
final String skySnapshotPath = final String skySnapshotPath =
...@@ -51,7 +53,7 @@ class DartDependencySetBuilder { ...@@ -51,7 +53,7 @@ class DartDependencySetBuilder {
final List<String> args = <String>[ final List<String> args = <String>[
skySnapshotPath, skySnapshotPath,
'--packages=${path.absolute(PackageMap.globalPackagesPath)}', '--packages=$packagesFilePath',
'--print-deps', '--print-deps',
mainScriptPath mainScriptPath
]; ];
...@@ -120,16 +122,24 @@ class HotRunner extends ResidentRunner { ...@@ -120,16 +122,24 @@ class HotRunner extends ResidentRunner {
DebuggingOptions debuggingOptions, DebuggingOptions debuggingOptions,
bool usesTerminalUI: true, bool usesTerminalUI: true,
this.benchmarkMode: false, this.benchmarkMode: false,
this.applicationBinary,
String projectRootPath,
String packagesFilePath,
}) : super(device, }) : super(device,
target: target, target: target,
debuggingOptions: debuggingOptions, debuggingOptions: debuggingOptions,
usesTerminalUI: usesTerminalUI) { usesTerminalUI: usesTerminalUI) {
_projectRootPath = Directory.current.path; _projectRootPath = projectRootPath ?? Directory.current.path;
_packagesFilePath =
packagesFilePath ?? path.absolute(PackageMap.globalPackagesPath);
} }
ApplicationPackage _package; ApplicationPackage _package;
String _mainPath; String _mainPath;
String _projectRootPath; String _projectRootPath;
String _packagesFilePath;
final String applicationBinary;
bool get prebuiltMode => applicationBinary != null;
Set<String> _dartDependencies; Set<String> _dartDependencies;
int _observatoryPort; int _observatoryPort;
final AssetBundle bundle = new AssetBundle(); final AssetBundle bundle = new AssetBundle();
...@@ -144,6 +154,7 @@ class HotRunner extends ResidentRunner { ...@@ -144,6 +154,7 @@ class HotRunner extends ResidentRunner {
bool shouldBuild: true bool shouldBuild: true
}) { }) {
// Don't let uncaught errors kill the process. // Don't let uncaught errors kill the process.
assert(shouldBuild == !prebuiltMode);
return Chain.capture(() { return Chain.capture(() {
return _run( return _run(
connectionInfoCompleter: connectionInfoCompleter, connectionInfoCompleter: connectionInfoCompleter,
...@@ -162,7 +173,8 @@ class HotRunner extends ResidentRunner { ...@@ -162,7 +173,8 @@ class HotRunner extends ResidentRunner {
return true; return true;
} }
DartDependencySetBuilder dartDependencySetBuilder = DartDependencySetBuilder dartDependencySetBuilder =
new DartDependencySetBuilder(_mainPath, _projectRootPath); new DartDependencySetBuilder(
_mainPath, _projectRootPath, _packagesFilePath);
try { try {
_dartDependencies = dartDependencySetBuilder.build(); _dartDependencies = dartDependencySetBuilder.build();
} catch (error) { } catch (error) {
...@@ -188,7 +200,7 @@ class HotRunner extends ResidentRunner { ...@@ -188,7 +200,7 @@ class HotRunner extends ResidentRunner {
return 1; return 1;
} }
_package = getApplicationPackageForPlatform(device.platform); _package = getApplicationPackageForPlatform(device.platform, applicationBinary: applicationBinary);
if (_package == null) { if (_package == null) {
String message = 'No application found for ${device.platform}.'; String message = 'No application found for ${device.platform}.';
...@@ -222,15 +234,10 @@ class HotRunner extends ResidentRunner { ...@@ -222,15 +234,10 @@ class HotRunner extends ResidentRunner {
// TODO(devoncarew): Move this into the device.startApp() impls. // TODO(devoncarew): Move this into the device.startApp() impls.
if (_package != null) { if (_package != null) {
printTrace("Stopping app '${_package.name}' on ${device.name}."); printTrace("Stopping app '${_package.name}' on ${device.name}.");
// We don't wait for the stop command to complete. await device.stopApp(_package);
device.stopApp(_package);
} }
// Allow any stop commands from above to start work. if (prebuiltMode || device is AndroidDevice) {
await new Future<Duration>.delayed(Duration.ZERO);
// TODO(devoncarew): This fails for ios devices - we haven't built yet.
if (device is AndroidDevice) {
printTrace('Running install command.'); printTrace('Running install command.');
if (!(installApp(device, _package, uninstall: false))) if (!(installApp(device, _package, uninstall: false)))
return 1; return 1;
...@@ -249,7 +256,8 @@ class HotRunner extends ResidentRunner { ...@@ -249,7 +256,8 @@ class HotRunner extends ResidentRunner {
mainPath: getDevFSLoaderScript(), mainPath: getDevFSLoaderScript(),
debuggingOptions: debuggingOptions, debuggingOptions: debuggingOptions,
platformArgs: platformArgs, platformArgs: platformArgs,
route: route route: route,
prebuiltApplication: prebuiltMode
); );
LaunchResult result = await futureResult; LaunchResult result = await futureResult;
...@@ -369,7 +377,8 @@ class HotRunner extends ResidentRunner { ...@@ -369,7 +377,8 @@ class HotRunner extends ResidentRunner {
String fsName = path.basename(_projectRootPath); String fsName = path.basename(_projectRootPath);
_devFS = new DevFS(vmService, _devFS = new DevFS(vmService,
fsName, fsName,
new Directory(_projectRootPath)); new Directory(_projectRootPath),
packagesFilePath: _packagesFilePath);
return _devFS.create(); return _devFS.create();
} }
......
...@@ -73,7 +73,10 @@ void testUsingContext(String description, dynamic testMethod(), { ...@@ -73,7 +73,10 @@ void testUsingContext(String description, dynamic testMethod(), {
if (bufferLogger.errorText.isNotEmpty) if (bufferLogger.errorText.isNotEmpty)
print(bufferLogger.errorText); print(bufferLogger.errorText);
} }
throw error; // Previously the following line read "throw error;". This is bad because
// it drops the error's actual stacktrace. Use 'rethrow' to preserve
// the stacktrace.
rethrow;
} }
}, timeout: timeout); }, timeout: timeout);
......
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