mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[ Widget Preview ] Fix crash when widget_preview_scaffold/.dart_tool doesn't exist (#178662)
If the `.dart_tool/widget_preview_scaffold/.dart_tool/` directory wasn't created during the initial run of `flutter widget-preview start` due to the command being interrupted or `pub` being disabled, `flutter widget-preview start` would crash due to the `package_config.json` logic walking up the directory structure looking for the nearest `package_config.json`. This would point to the parent project's `package_config.json`, which would not be compatible with the widget preview scaffold project. Fixes https://github.com/flutter/flutter/issues/178660 and https://github.com/flutter/flutter/issues/177655
This commit is contained in:
parent
4cf8eb9bea
commit
cc14ef5290
@ -318,8 +318,9 @@ final class WidgetPreviewStartCommand extends WidgetPreviewSubCommandBase with C
|
||||
// after we generate the scaffold project as invoking the getter triggers
|
||||
// lazy initialization of the preview scaffold's FlutterManifest before
|
||||
// the scaffold project's pubspec has been generated.
|
||||
final FlutterProject widgetPreviewScaffoldProject = rootProject.widgetPreviewScaffoldProject;
|
||||
_previewCodeGenerator = PreviewCodeGenerator(
|
||||
widgetPreviewScaffoldProject: rootProject.widgetPreviewScaffoldProject,
|
||||
widgetPreviewScaffoldProject: widgetPreviewScaffoldProject,
|
||||
fs: fs,
|
||||
);
|
||||
|
||||
@ -333,6 +334,12 @@ final class WidgetPreviewStartCommand extends WidgetPreviewSubCommandBase with C
|
||||
await _previewPubspecBuilder.populatePreviewPubspec(rootProject: rootProject);
|
||||
}
|
||||
|
||||
if (!widgetPreviewScaffoldProject.dartTool.existsSync()) {
|
||||
await _previewPubspecBuilder.generatePackageConfig(
|
||||
widgetPreviewScaffoldProject: widgetPreviewScaffoldProject,
|
||||
);
|
||||
}
|
||||
|
||||
shutdownHooks.addShutdownHook(() async {
|
||||
await _widgetPreviewApp?.exitApp();
|
||||
await _previewDetector.dispose();
|
||||
@ -343,7 +350,7 @@ final class WidgetPreviewStartCommand extends WidgetPreviewSubCommandBase with C
|
||||
|
||||
await configureDtd();
|
||||
final int result = await runPreviewEnvironment(
|
||||
widgetPreviewScaffoldProject: rootProject.widgetPreviewScaffoldProject,
|
||||
widgetPreviewScaffoldProject: widgetPreviewScaffoldProject,
|
||||
);
|
||||
if (result != 0) {
|
||||
throwToolExit('Failed to launch the widget previewer.', exitCode: result);
|
||||
|
||||
@ -91,6 +91,8 @@ class PreviewPubspecBuilder {
|
||||
);
|
||||
}
|
||||
|
||||
PubOutputMode get _outputMode => verbose ? PubOutputMode.all : PubOutputMode.failuresOnly;
|
||||
|
||||
Future<void> populatePreviewPubspec({
|
||||
required FlutterProject rootProject,
|
||||
String? updatedPubspecPath,
|
||||
@ -126,7 +128,6 @@ class PreviewPubspecBuilder {
|
||||
}),
|
||||
};
|
||||
|
||||
final PubOutputMode outputMode = verbose ? PubOutputMode.all : PubOutputMode.failuresOnly;
|
||||
await pub.interactively(
|
||||
<String>[
|
||||
pubAdd,
|
||||
@ -146,7 +147,7 @@ class PreviewPubspecBuilder {
|
||||
context: PubContext.pubAdd,
|
||||
command: pubAdd,
|
||||
touchesPackageConfig: true,
|
||||
outputMode: outputMode,
|
||||
outputMode: _outputMode,
|
||||
);
|
||||
|
||||
// Adds dependencies required by the widget preview scaffolding.
|
||||
@ -161,18 +162,22 @@ class PreviewPubspecBuilder {
|
||||
context: PubContext.pubAdd,
|
||||
command: pubAdd,
|
||||
touchesPackageConfig: true,
|
||||
outputMode: outputMode,
|
||||
outputMode: _outputMode,
|
||||
);
|
||||
|
||||
await generatePackageConfig(widgetPreviewScaffoldProject: widgetPreviewScaffoldProject);
|
||||
previewManifest.updatePubspecHash(updatedPubspecPath: updatedPubspecPath);
|
||||
}
|
||||
|
||||
/// Generates `widget_preview_scaffold/.dart_tool/package_config.json`.
|
||||
Future<void> generatePackageConfig({required FlutterProject widgetPreviewScaffoldProject}) async {
|
||||
// Generate package_config.json.
|
||||
await pub.get(
|
||||
context: PubContext.create,
|
||||
project: widgetPreviewScaffoldProject,
|
||||
offline: offline,
|
||||
outputMode: outputMode,
|
||||
outputMode: _outputMode,
|
||||
);
|
||||
|
||||
previewManifest.updatePubspecHash(updatedPubspecPath: updatedPubspecPath);
|
||||
}
|
||||
|
||||
void onPubspecChangeDetected(String path) {
|
||||
|
||||
@ -7,6 +7,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:dtd/dtd.dart';
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file_testing/file_testing.dart';
|
||||
import 'package:flutter_tools/src/base/io.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/commands/widget_preview.dart';
|
||||
@ -125,6 +126,36 @@ void main() {
|
||||
await runWidgetPreview(expectedMessages: firstLaunchMessagesWebServer, useWebServer: true);
|
||||
});
|
||||
|
||||
testWithoutContext('runs flutter pub get in widget_preview_scaffold if '
|
||||
"widget_preview_scaffold/.dart_tool doesn't exist", () async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/178660
|
||||
// Generate the widget preview scaffold, but don't bother launching it.
|
||||
processManager.runSync(<String>[
|
||||
flutterBin,
|
||||
'widget-preview',
|
||||
'start',
|
||||
'--no-${WidgetPreviewStartCommand.kLaunchPreviewer}',
|
||||
], workingDirectory: tempDir.path);
|
||||
|
||||
// Ensure widget_preview_scaffold/.dart_tool/package_config.json exists.
|
||||
final Directory widgetPreviewScaffoldDartTool = tempDir
|
||||
.childDirectory('.dart_tool')
|
||||
.childDirectory('widget_preview_scaffold')
|
||||
.childDirectory('.dart_tool');
|
||||
expect(widgetPreviewScaffoldDartTool, exists);
|
||||
expect(widgetPreviewScaffoldDartTool.childFile('package_config.json'), exists);
|
||||
|
||||
// Delete widget_preview_scaffold/.dart_tool/. This simulates an interrupted
|
||||
// flutter widget-preview start where 'flutter pub get' wasn't run after
|
||||
// the widget_preview_scaffold project was created.
|
||||
widgetPreviewScaffoldDartTool.deleteSync(recursive: true);
|
||||
|
||||
// Ensure we don't crash due to the package_config.json lookup pointing to
|
||||
// the parent project's package_config.json due to
|
||||
// widget_preview_scaffold/.dart_tool/package_config.json not existing.
|
||||
await runWidgetPreview(expectedMessages: subsequentLaunchMessagesWeb);
|
||||
});
|
||||
|
||||
testWithoutContext('does not recreate project on subsequent runs', () async {
|
||||
// The first run of 'flutter widget-preview start' should generate a new preview scaffold
|
||||
await runWidgetPreview(expectedMessages: firstLaunchMessagesWeb);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user