Better progress (#6677)
* make showElapsedTime default to true * support nested progresses * improve hot reload message * rethrow
This commit is contained in:
parent
1f1adcaa0e
commit
fcfb2a5c55
@ -241,7 +241,7 @@ class AndroidDevice extends Device {
|
|||||||
|
|
||||||
Status status = logger.startProgress('Installing ${apk.apkPath}...');
|
Status status = logger.startProgress('Installing ${apk.apkPath}...');
|
||||||
String installOut = runCheckedSync(adbCommandForDevice(<String>['install', '-r', apk.apkPath]));
|
String installOut = runCheckedSync(adbCommandForDevice(<String>['install', '-r', apk.apkPath]));
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true);
|
RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true);
|
||||||
String failure = failureExp.stringMatch(installOut);
|
String failure = failureExp.stringMatch(installOut);
|
||||||
if (failure != null) {
|
if (failure != null) {
|
||||||
|
@ -137,7 +137,7 @@ Future<int> buildGradleProject(BuildMode buildMode) async {
|
|||||||
workingDirectory: 'android',
|
workingDirectory: 'android',
|
||||||
allowReentrantFlutter: true
|
allowReentrantFlutter: true
|
||||||
);
|
);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
if (exitcode != 0)
|
if (exitcode != 0)
|
||||||
return exitcode;
|
return exitcode;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -159,7 +159,7 @@ Future<int> buildGradleProject(BuildMode buildMode) async {
|
|||||||
workingDirectory: 'android',
|
workingDirectory: 'android',
|
||||||
allowReentrantFlutter: true
|
allowReentrantFlutter: true
|
||||||
);
|
);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
|
|
||||||
if (exitcode == 0) {
|
if (exitcode == 0) {
|
||||||
File apkFile = new File(gradleAppOut);
|
File apkFile = new File(gradleAppOut);
|
||||||
|
@ -37,7 +37,7 @@ abstract class Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Status {
|
class Status {
|
||||||
void stop({ bool showElapsedTime: false }) { }
|
void stop({ bool showElapsedTime: true }) { }
|
||||||
void cancel() { }
|
void cancel() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,15 +73,17 @@ class StdoutLogger extends Logger {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Status startProgress(String message) {
|
Status startProgress(String message) {
|
||||||
_status?.cancel();
|
if (_status != null) {
|
||||||
_status = null;
|
// Ignore nested progresses; return a no-op status object.
|
||||||
|
|
||||||
if (supportsColor) {
|
|
||||||
_status = new _AnsiStatus(message);
|
|
||||||
return _status;
|
|
||||||
} else {
|
|
||||||
printStatus(message);
|
|
||||||
return new Status();
|
return new Status();
|
||||||
|
} else {
|
||||||
|
if (supportsColor) {
|
||||||
|
_status = new _AnsiStatus(message);
|
||||||
|
return _status;
|
||||||
|
} else {
|
||||||
|
printStatus(message);
|
||||||
|
return new Status();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,13 +246,13 @@ class _AnsiStatus extends Status {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void stop({ bool showElapsedTime: false }) {
|
void stop({ bool showElapsedTime: true }) {
|
||||||
if (!live)
|
if (!live)
|
||||||
return;
|
return;
|
||||||
live = false;
|
live = false;
|
||||||
|
|
||||||
if (showElapsedTime) {
|
if (showElapsedTime) {
|
||||||
print('\b\b\b\b${stopwatch.elapsedMilliseconds.toString()}ms');
|
print('\b\b\b\b\b${stopwatch.elapsedMilliseconds.toString().padLeft(3)}ms');
|
||||||
} else {
|
} else {
|
||||||
print('\b ');
|
print('\b ');
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ class MaterialFonts {
|
|||||||
Uri.parse(cache.getVersionFor(kName)), fontsDir, true
|
Uri.parse(cache.getVersionFor(kName)), fontsDir, true
|
||||||
).then((_) {
|
).then((_) {
|
||||||
cache.setStampFor(kName, cache.getVersionFor(kName));
|
cache.setStampFor(kName, cache.getVersionFor(kName));
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
}).whenComplete(() {
|
}).whenComplete(() {
|
||||||
status.cancel();
|
status.cancel();
|
||||||
});
|
});
|
||||||
@ -346,7 +346,7 @@ class FlutterEngine {
|
|||||||
String skyEnginePath = path.join(pkgDir.path, kSkyEngine);
|
String skyEnginePath = path.join(pkgDir.path, kSkyEngine);
|
||||||
buildSkyEngineSdkSummary(skyEnginePath, kSdkBundle);
|
buildSkyEngineSdkSummary(skyEnginePath, kSdkBundle);
|
||||||
} finally {
|
} finally {
|
||||||
summaryStatus.stop(showElapsedTime: true);
|
summaryStatus.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory engineDir = cache.getArtifactDirectory(kName);
|
Directory engineDir = cache.getArtifactDirectory(kName);
|
||||||
@ -389,7 +389,7 @@ class FlutterEngine {
|
|||||||
Future<Null> _downloadItem(String message, String url, Directory dest) {
|
Future<Null> _downloadItem(String message, String url, Directory dest) {
|
||||||
Status status = logger.startProgress(message);
|
Status status = logger.startProgress(message);
|
||||||
return Cache._downloadFileToCache(Uri.parse(url), dest, true).then((_) {
|
return Cache._downloadFileToCache(Uri.parse(url), dest, true).then((_) {
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
}).whenComplete(() {
|
}).whenComplete(() {
|
||||||
status.cancel();
|
status.cancel();
|
||||||
});
|
});
|
||||||
|
@ -66,7 +66,7 @@ class AnalyzeContinuously extends AnalyzeBase {
|
|||||||
analyzedPaths.clear();
|
analyzedPaths.clear();
|
||||||
analysisTimer = new Stopwatch()..start();
|
analysisTimer = new Stopwatch()..start();
|
||||||
} else {
|
} else {
|
||||||
analysisStatus?.stop(showElapsedTime: true);
|
analysisStatus?.stop();
|
||||||
analysisTimer.stop();
|
analysisTimer.stop();
|
||||||
|
|
||||||
logger.printStatus(terminal.clearScreen(), newline: false);
|
logger.printStatus(terminal.clearScreen(), newline: false);
|
||||||
|
@ -60,7 +60,7 @@ class BuildAotCommand extends BuildSubCommand {
|
|||||||
outputPath: argResults['output-dir'],
|
outputPath: argResults['output-dir'],
|
||||||
interpreter: argResults['interpreter']
|
interpreter: argResults['interpreter']
|
||||||
);
|
);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
|
|
||||||
if (outputPath == null)
|
if (outputPath == null)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -591,7 +591,7 @@ Future<int> buildAndroid(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int result = _buildApk(platform, buildMode, components, flxPath, keystore, outputFile);
|
int result = _buildApk(platform, buildMode, components, flxPath, keystore, outputFile);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
File apkFile = new File(outputFile);
|
File apkFile = new File(outputFile);
|
||||||
|
@ -78,7 +78,7 @@ class BuildIOSCommand extends BuildSubCommand {
|
|||||||
buildForDevice: !forSimulator,
|
buildForDevice: !forSimulator,
|
||||||
codesign: shouldCodesign
|
codesign: shouldCodesign
|
||||||
);
|
);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
printError('Encountered error while building for $logTarget.');
|
printError('Encountered error while building for $logTarget.');
|
||||||
|
@ -705,8 +705,14 @@ class _AppRunLogger extends Logger {
|
|||||||
@override
|
@override
|
||||||
void printTrace(String message) { }
|
void printTrace(String message) { }
|
||||||
|
|
||||||
|
Status _status;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Status startProgress(String message) {
|
Status startProgress(String message) {
|
||||||
|
// Ignore nested progresses; return a no-op status object.
|
||||||
|
if (_status != null)
|
||||||
|
return new Status();
|
||||||
|
|
||||||
int id = _nextProgressId++;
|
int id = _nextProgressId++;
|
||||||
|
|
||||||
_sendLogEvent(<String, dynamic>{
|
_sendLogEvent(<String, dynamic>{
|
||||||
@ -715,7 +721,8 @@ class _AppRunLogger extends Logger {
|
|||||||
'id': id.toString()
|
'id': id.toString()
|
||||||
});
|
});
|
||||||
|
|
||||||
return new _AppLoggerStatus(this, id);
|
_status = new _AppLoggerStatus(this, id);
|
||||||
|
return _status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void close() {
|
||||||
@ -737,12 +744,14 @@ class _AppLoggerStatus implements Status {
|
|||||||
final int id;
|
final int id;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void stop({ bool showElapsedTime: false }) {
|
void stop({ bool showElapsedTime: true }) {
|
||||||
|
logger._status = null;
|
||||||
_sendFinished();
|
_sendFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void cancel() {
|
void cancel() {
|
||||||
|
logger._status = null;
|
||||||
_sendFinished();
|
_sendFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class TestCommand extends FlutterCommand {
|
|||||||
Future<bool> _collectCoverageData(CoverageCollector collector, { bool mergeCoverageData: false }) async {
|
Future<bool> _collectCoverageData(CoverageCollector collector, { bool mergeCoverageData: false }) async {
|
||||||
Status status = logger.startProgress('Collecting coverage information...');
|
Status status = logger.startProgress('Collecting coverage information...');
|
||||||
String coverageData = await collector.finalizeCoverage();
|
String coverageData = await collector.finalizeCoverage();
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
if (coverageData == null)
|
if (coverageData == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class UpdatePackagesCommand extends FlutterCommand {
|
|||||||
new File(path.join(coverageDir, 'lcov.info'))
|
new File(path.join(coverageDir, 'lcov.info'))
|
||||||
..createSync(recursive: true)
|
..createSync(recursive: true)
|
||||||
..writeAsBytesSync(data, flush: true);
|
..writeAsBytesSync(data, flush: true);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -53,7 +53,7 @@ Future<int> pubGet({
|
|||||||
mapFunction: _filterOverrideWarnings,
|
mapFunction: _filterOverrideWarnings,
|
||||||
environment: <String, String>{ 'FLUTTER_ROOT': Cache.flutterRoot }
|
environment: <String, String>{ 'FLUTTER_ROOT': Cache.flutterRoot }
|
||||||
);
|
);
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
if (code != 0)
|
if (code != 0)
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ Future<Null> _buildUnlinkedForPackage(
|
|||||||
try {
|
try {
|
||||||
await manager.computeUnlinkedForFolder(name, libFolder);
|
await manager.computeUnlinkedForFolder(name, libFolder);
|
||||||
} finally {
|
} finally {
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,15 +339,7 @@ class HotRunner extends ResidentRunner {
|
|||||||
Future<Null> handleTerminalCommand(String code) async {
|
Future<Null> handleTerminalCommand(String code) async {
|
||||||
final String lower = code.toLowerCase();
|
final String lower = code.toLowerCase();
|
||||||
if ((lower == 'r') || (code == AnsiTerminal.KEY_F5)) {
|
if ((lower == 'r') || (code == AnsiTerminal.KEY_F5)) {
|
||||||
OperationResult result = OperationResult.ok;
|
OperationResult result = await restart(fullRestart: code == 'R');
|
||||||
// F5, restart
|
|
||||||
if ((code == 'r') || (code == AnsiTerminal.KEY_F5)) {
|
|
||||||
// lower-case 'r'
|
|
||||||
result = await _reloadSources();
|
|
||||||
} else {
|
|
||||||
// upper-case 'R'.
|
|
||||||
result = await _restartFromSources();
|
|
||||||
}
|
|
||||||
if (!result.isOk) {
|
if (!result.isOk) {
|
||||||
// TODO(johnmccutchan): Attempt to determine the number of errors that
|
// TODO(johnmccutchan): Attempt to determine the number of errors that
|
||||||
// occurred and tighten this message.
|
// occurred and tighten this message.
|
||||||
@ -396,7 +388,7 @@ class HotRunner extends ResidentRunner {
|
|||||||
bundle: bundle,
|
bundle: bundle,
|
||||||
bundleDirty: rebuildBundle,
|
bundleDirty: rebuildBundle,
|
||||||
fileFilter: _dartDependencies);
|
fileFilter: _dartDependencies);
|
||||||
devFSStatus.stop(showElapsedTime: true);
|
devFSStatus.stop();
|
||||||
// Clear the set after the sync.
|
// Clear the set after the sync.
|
||||||
_dartDependencies = null;
|
_dartDependencies = null;
|
||||||
printTrace('Synced ${getSizeAsMB(_devFS.bytes)}.');
|
printTrace('Synced ${getSizeAsMB(_devFS.bytes)}.');
|
||||||
@ -461,10 +453,10 @@ class HotRunner extends ResidentRunner {
|
|||||||
// Wait for the first frame to be rendered.
|
// Wait for the first frame to be rendered.
|
||||||
await firstFrameTimer.firstFrame();
|
await firstFrameTimer.firstFrame();
|
||||||
}
|
}
|
||||||
restartStatus.stop(showElapsedTime: true);
|
restartStatus.stop();
|
||||||
if (waitForFrame) {
|
if (waitForFrame) {
|
||||||
printStatus('Restart performed in '
|
printTrace('Restart performed in '
|
||||||
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
|
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
|
||||||
if (benchmarkMode) {
|
if (benchmarkMode) {
|
||||||
benchmarkData['hotRestartMillisecondsToFrame'] =
|
benchmarkData['hotRestartMillisecondsToFrame'] =
|
||||||
firstFrameTimer.elapsed.inMilliseconds;
|
firstFrameTimer.elapsed.inMilliseconds;
|
||||||
@ -476,25 +468,41 @@ class HotRunner extends ResidentRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns [true] if the reload was successful.
|
/// Returns [true] if the reload was successful.
|
||||||
bool _printReloadReport(Map<String, dynamic> reloadReport) {
|
bool _validateReloadReport(Map<String, dynamic> reloadReport) {
|
||||||
if (!reloadReport['success']) {
|
if (!reloadReport['success']) {
|
||||||
printError('Hot reload was rejected:');
|
printError('Hot reload was rejected:');
|
||||||
for (Map<String, dynamic> notice in reloadReport['details']['notices'])
|
for (Map<String, dynamic> notice in reloadReport['details']['notices'])
|
||||||
printError('${notice['message']}');
|
printError('${notice['message']}');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int loadedLibraryCount = reloadReport['details']['loadedLibraryCount'];
|
|
||||||
int finalLibraryCount = reloadReport['details']['finalLibraryCount'];
|
|
||||||
printStatus('Reloaded $loadedLibraryCount of $finalLibraryCount libraries.');
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) async {
|
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) async {
|
||||||
if (fullRestart) {
|
if (fullRestart) {
|
||||||
return _restartFromSources();
|
Status status = logger.startProgress('Performing full restart...');
|
||||||
|
try {
|
||||||
|
await _restartFromSources();
|
||||||
|
status.stop();
|
||||||
|
printStatus('Restart complete.');
|
||||||
|
return OperationResult.ok;
|
||||||
|
} catch (error) {
|
||||||
|
status.stop();
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return _reloadSources(pause: pauseAfterRestart);
|
Status status = logger.startProgress('Performing hot reload...');
|
||||||
|
try {
|
||||||
|
OperationResult result = await _reloadSources(pause: pauseAfterRestart);
|
||||||
|
status.stop();
|
||||||
|
if (result.isOk)
|
||||||
|
printStatus("${result.message}.");
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
status.stop();
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,24 +516,23 @@ class HotRunner extends ResidentRunner {
|
|||||||
if (!updatedDevFS)
|
if (!updatedDevFS)
|
||||||
return new OperationResult(1, 'Dart Source Error');
|
return new OperationResult(1, 'Dart Source Error');
|
||||||
}
|
}
|
||||||
Status reloadStatus = logger.startProgress('Performing hot reload...');
|
String reloadMessage;
|
||||||
try {
|
try {
|
||||||
Map<String, dynamic> reloadReport =
|
Map<String, dynamic> reloadReport =
|
||||||
await currentView.uiIsolate.reloadSources(pause: pause);
|
await currentView.uiIsolate.reloadSources(pause: pause);
|
||||||
reloadStatus.stop(showElapsedTime: true);
|
if (!_validateReloadReport(reloadReport)) {
|
||||||
if (!_printReloadReport(reloadReport)) {
|
|
||||||
// Reload failed.
|
// Reload failed.
|
||||||
flutterUsage.sendEvent('hot', 'reload-reject');
|
flutterUsage.sendEvent('hot', 'reload-reject');
|
||||||
return new OperationResult(1, 'reload rejected');
|
return new OperationResult(1, 'reload rejected');
|
||||||
} else {
|
} else {
|
||||||
flutterUsage.sendEvent('hot', 'reload');
|
flutterUsage.sendEvent('hot', 'reload');
|
||||||
|
int loadedLibraryCount = reloadReport['details']['loadedLibraryCount'];
|
||||||
|
int finalLibraryCount = reloadReport['details']['finalLibraryCount'];
|
||||||
|
reloadMessage = 'Reloaded $loadedLibraryCount of $finalLibraryCount libraries';
|
||||||
}
|
}
|
||||||
} catch (error, st) {
|
} catch (error, st) {
|
||||||
int errorCode = error['code'];
|
int errorCode = error['code'];
|
||||||
String errorMessage = error['message'];
|
String errorMessage = error['message'];
|
||||||
|
|
||||||
reloadStatus.stop(showElapsedTime: true);
|
|
||||||
|
|
||||||
if (errorCode == Isolate.kIsolateReloadBarred) {
|
if (errorCode == Isolate.kIsolateReloadBarred) {
|
||||||
printError('Unable to hot reload app due to an unrecoverable error in '
|
printError('Unable to hot reload app due to an unrecoverable error in '
|
||||||
'the source code. Please address the error and then use '
|
'the source code. Please address the error and then use '
|
||||||
@ -565,15 +572,15 @@ class HotRunner extends ResidentRunner {
|
|||||||
// When the framework is present, we can wait for the first frame
|
// When the framework is present, we can wait for the first frame
|
||||||
// event and measure reload time.
|
// event and measure reload time.
|
||||||
await firstFrameTimer.firstFrame();
|
await firstFrameTimer.firstFrame();
|
||||||
printStatus('Hot reload performed in '
|
printTrace('Hot reload performed in '
|
||||||
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
|
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
|
||||||
if (benchmarkMode) {
|
if (benchmarkMode) {
|
||||||
benchmarkData['hotReloadMillisecondsToFrame'] =
|
benchmarkData['hotReloadMillisecondsToFrame'] =
|
||||||
firstFrameTimer.elapsed.inMilliseconds;
|
firstFrameTimer.elapsed.inMilliseconds;
|
||||||
}
|
}
|
||||||
flutterUsage.sendTiming('hot', 'reload', firstFrameTimer.elapsed);
|
flutterUsage.sendTiming('hot', 'reload', firstFrameTimer.elapsed);
|
||||||
}
|
}
|
||||||
return OperationResult.ok;
|
return new OperationResult(OperationResult.ok.code, reloadMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -89,7 +89,7 @@ class RunAndStayResident extends ResidentRunner {
|
|||||||
prebuiltApplication: prebuiltMode
|
prebuiltApplication: prebuiltMode
|
||||||
);
|
);
|
||||||
|
|
||||||
status.stop(showElapsedTime: true);
|
status.stop();
|
||||||
|
|
||||||
if (result && extensionAddedEvent != null) {
|
if (result && extensionAddedEvent != null) {
|
||||||
await extensionAddedEvent;
|
await extensionAddedEvent;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user