Support hot reload with a prebuilt loader (#6743)
This commit is contained in:
parent
10d20c77aa
commit
fb3bf7a9d7
@ -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 {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printTrace('skipped log line: $line');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _stop() {
|
void _stop() {
|
||||||
|
@ -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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
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() {
|
|||||||
|
|
||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
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(), {
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user