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