Clean up pre-existing DevFS during creation (#10843)
diff --git a/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart b/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart
index 4af62da..e439d37 100644
--- a/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart
+++ b/packages/flutter_tools/lib/src/commands/fuchsia_reload.dart
@@ -143,9 +143,24 @@
return _vmServiceCache[port];
}
+ Future<bool> _checkPort(int port) async {
+ bool connected = true;
+ Socket s;
+ try {
+ s = await Socket.connect("$_address", port);
+ } catch (_) {
+ connected = false;
+ }
+ if (s != null)
+ await s.close();
+ return connected;
+ }
+
Future<List<FlutterView>> _getViews(List<int> ports) async {
final List<FlutterView> views = <FlutterView>[];
for (int port in ports) {
+ if (!await _checkPort(port))
+ continue;
final VMService vmService = _getVMService(port);
await vmService.getVM();
await vmService.waitForViews();
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index 2657e92..39b9766 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -5,6 +5,8 @@
import 'dart:async';
import 'dart:convert' show BASE64, UTF8;
+import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
+
import 'asset.dart';
import 'base/context.dart';
import 'base/file_system.dart';
@@ -185,10 +187,7 @@
@override
Future<dynamic> destroy(String fsName) async {
- await vmService.vm.invokeRpcRaw(
- '_deleteDevFS',
- params: <String, dynamic> { 'fsName': fsName },
- );
+ await vmService.vm.deleteDevFS(fsName);
}
@override
@@ -352,7 +351,16 @@
Future<Uri> create() async {
printTrace('DevFS: Creating new filesystem on the device ($_baseUri)');
- _baseUri = await _operations.create(fsName);
+ try {
+ _baseUri = await _operations.create(fsName);
+ } on rpc.RpcException catch (rpcException) {
+ // 1001 is kFileSystemAlreadyExists in //dart/runtime/vm/json_stream.h
+ if (rpcException.code != 1001)
+ rethrow;
+ printTrace('DevFS: Creating failed. Destroying and trying again');
+ await destroy();
+ _baseUri = await _operations.create(fsName);
+ }
printTrace('DevFS: Created new filesystem on the device ($_baseUri)');
return _baseUri;
}
diff --git a/packages/flutter_tools/test/devfs_test.dart b/packages/flutter_tools/test/devfs_test.dart
index 34030cc..f931e9b 100644
--- a/packages/flutter_tools/test/devfs_test.dart
+++ b/packages/flutter_tools/test/devfs_test.dart
@@ -13,6 +13,7 @@
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/vmservice.dart';
+import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
import 'package:test/test.dart';
import 'src/common.dart';
@@ -335,7 +336,34 @@
testUsingContext('delete dev file system', () async {
expect(vmService.messages, isEmpty, reason: 'prior test timeout');
await devFS.destroy();
- vmService.expectMessages(<String>['_deleteDevFS {fsName: test}']);
+ vmService.expectMessages(<String>['destroy test']);
+ expect(devFS.assetPathsToEvict, isEmpty);
+ }, overrides: <Type, Generator>{
+ FileSystem: () => fs,
+ });
+
+ testUsingContext('cleanup preexisting file system', () async {
+ // simulate workspace
+ final File file = fs.file(fs.path.join(basePath, filePath));
+ await file.parent.create(recursive: true);
+ file.writeAsBytesSync(<int>[1, 2, 3]);
+
+ // simulate package
+ await _createPackage(fs, 'somepkg', 'somefile.txt');
+
+ devFS = new DevFS(vmService, 'test', tempDir);
+ await devFS.create();
+ vmService.expectMessages(<String>['create test']);
+ expect(devFS.assetPathsToEvict, isEmpty);
+
+ // Try to create again.
+ await devFS.create();
+ vmService.expectMessages(<String>['create test', 'destroy test', 'create test']);
+ expect(devFS.assetPathsToEvict, isEmpty);
+
+ // Really destroy.
+ await devFS.destroy();
+ vmService.expectMessages(<String>['destroy test']);
expect(devFS.assetPathsToEvict, isEmpty);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
@@ -390,16 +418,30 @@
class MockVM implements VM {
final MockVMService _service;
final Uri _baseUri = Uri.parse('file:///tmp/devfs/test');
+ bool _devFSExists = false;
+
+ static const int kFileSystemAlreadyExists = 1001;
MockVM(this._service);
@override
Future<Map<String, dynamic>> createDevFS(String fsName) async {
_service.messages.add('create $fsName');
+ if (_devFSExists) {
+ throw new rpc.RpcException(kFileSystemAlreadyExists, 'File system already exists');
+ }
+ _devFSExists = true;
return <String, dynamic>{'uri': '$_baseUri'};
}
@override
+ Future<Map<String, dynamic>> deleteDevFS(String fsName) async {
+ _service.messages.add('destroy $fsName');
+ _devFSExists = false;
+ return <String, dynamic>{'type': 'Success'};
+ }
+
+ @override
Future<Map<String, dynamic>> invokeRpcRaw(String method, {
Map<String, dynamic> params: const <String, dynamic>{},
Duration timeout,