Revert "Devfs cleanup and testing (#33374)" (#33673)
This reverts commit 445505d6f2d4a0b658385f0ef735d3a826ca49ab.
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index ec97f95..e15fb5c 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -38,25 +38,21 @@
/// or if the given time is null.
bool isModifiedAfter(DateTime time);
- /// The number of bytes in this file.
int get size;
- /// Returns the raw bytes of this file.
- List<int> contentsAsBytes();
+ Future<List<int>> contentsAsBytes();
- /// Returns a gzipped representation of the contents of this file.
- List<int> contentsAsCompressedBytes() {
- return gzip.encode(contentsAsBytes());
+ Stream<List<int>> contentsAsStream();
+
+ Stream<List<int>> contentsAsCompressedStream() {
+ return contentsAsStream().cast<List<int>>().transform<List<int>>(gzip.encoder);
}
- /// Copies the content into the provided file.
- ///
- /// Requires that the `destination` directory already exists, but the target
- /// file need not.
- void copyToFile(File destination);
+ /// Return the list of files this content depends on.
+ List<String> get fileDependencies => <String>[];
}
-/// File content to be copied to the device.
+// File content to be copied to the device.
class DevFSFileContent extends DevFSContent {
DevFSFileContent(this.file);
@@ -107,6 +103,9 @@
}
@override
+ List<String> get fileDependencies => <String>[_getFile().path];
+
+ @override
bool get isModified {
final FileStat _oldFileStat = _fileStat;
_stat();
@@ -136,12 +135,10 @@
}
@override
- List<int> contentsAsBytes() => _getFile().readAsBytesSync().cast<int>();
+ Future<List<int>> contentsAsBytes() => _getFile().readAsBytes();
@override
- void copyToFile(File destination) {
- _getFile().copySync(destination.path);
- }
+ Stream<List<int>> contentsAsStream() => _getFile().openRead();
}
/// Byte content to be copied to the device.
@@ -178,15 +175,14 @@
int get size => _bytes.length;
@override
- List<int> contentsAsBytes() => _bytes;
+ Future<List<int>> contentsAsBytes() async => _bytes;
@override
- void copyToFile(File destination) {
- destination.writeAsBytesSync(contentsAsBytes());
- }
+ Stream<List<int>> contentsAsStream() =>
+ Stream<List<int>>.fromIterable(<List<int>>[_bytes]);
}
-/// String content to be copied to the device encoded as utf8.
+/// String content to be copied to the device.
class DevFSStringContent extends DevFSByteContent {
DevFSStringContent(String string)
: _string = string,
@@ -207,29 +203,75 @@
}
}
-class DevFSOperations {
- DevFSOperations(this.vmService, this.fsName)
- : httpAddress = vmService.httpAddress;
+/// Abstract DevFS operations interface.
+abstract class DevFSOperations {
+ Future<Uri> create(String fsName);
+ Future<dynamic> destroy(String fsName);
+ Future<dynamic> writeFile(String fsName, Uri deviceUri, DevFSContent content);
+}
+
+/// An implementation of [DevFSOperations] that speaks to the
+/// vm service.
+class ServiceProtocolDevFSOperations implements DevFSOperations {
+ ServiceProtocolDevFSOperations(this.vmService);
final VMService vmService;
+
+ @override
+ Future<Uri> create(String fsName) async {
+ final Map<String, dynamic> response = await vmService.vm.createDevFS(fsName);
+ return Uri.parse(response['uri']);
+ }
+
+ @override
+ Future<dynamic> destroy(String fsName) async {
+ await vmService.vm.deleteDevFS(fsName);
+ }
+
+ @override
+ Future<dynamic> writeFile(String fsName, Uri deviceUri, DevFSContent content) async {
+ List<int> bytes;
+ try {
+ bytes = await content.contentsAsBytes();
+ } catch (e) {
+ return e;
+ }
+ final String fileContents = base64.encode(bytes);
+ try {
+ return await vmService.vm.invokeRpcRaw(
+ '_writeDevFSFile',
+ params: <String, dynamic>{
+ 'fsName': fsName,
+ 'uri': deviceUri.toString(),
+ 'fileContents': fileContents,
+ },
+ );
+ } catch (error) {
+ printTrace('DevFS: Failed to write $deviceUri: $error');
+ }
+ }
+}
+
+class DevFSException implements Exception {
+ DevFSException(this.message, [this.error, this.stackTrace]);
+ final String message;
+ final dynamic error;
+ final StackTrace stackTrace;
+}
+
+class _DevFSHttpWriter {
+ _DevFSHttpWriter(this.fsName, VMService serviceProtocol)
+ : httpAddress = serviceProtocol.httpAddress;
+
final String fsName;
final Uri httpAddress;
- final HttpClient _client = HttpClient();
static const int kMaxInFlight = 6;
int _inFlight = 0;
Map<Uri, DevFSContent> _outstanding;
Completer<void> _completer;
-
- Future<Uri> create(String fsName) async {
- final Map<String, dynamic> response = await vmService.vm.createDevFS(fsName);
- return Uri.parse(response['uri']);
- }
-
- Future<void> destroy(String fsName) async {
- await vmService.vm.deleteDevFS(fsName);
- }
+ final HttpClient _client = HttpClient();
Future<void> write(Map<Uri, DevFSContent> entries) async {
_client.maxConnectionsPerHost = kMaxInFlight;
@@ -259,9 +301,9 @@
final HttpClientRequest request = await _client.putUrl(httpAddress);
request.headers.removeAll(HttpHeaders.acceptEncodingHeader);
request.headers.add('dev_fs_name', fsName);
- request.headers.add('dev_fs_uri_b64',
- base64.encode(utf8.encode(deviceUri.toString())));
- request.add(content.contentsAsCompressedBytes());
+ request.headers.add('dev_fs_uri_b64', base64.encode(utf8.encode('$deviceUri')));
+ final Stream<List<int>> contents = content.contentsAsCompressedStream();
+ await request.addStream(contents);
final HttpClientResponse response = await request.close();
await response.drain<void>();
} catch (error, trace) {
@@ -275,14 +317,6 @@
}
}
-class DevFSException implements Exception {
- DevFSException(this.message, [this.error, this.stackTrace]);
-
- final String message;
- final dynamic error;
- final StackTrace stackTrace;
-}
-
// Basic statistics for DevFS update operation.
class UpdateFSReport {
UpdateFSReport({
@@ -319,7 +353,8 @@
this.fsName,
this.rootDirectory, {
String packagesFilePath,
- }) : _operations = DevFSOperations(serviceProtocol, fsName),
+ }) : _operations = ServiceProtocolDevFSOperations(serviceProtocol),
+ _httpWriter = _DevFSHttpWriter(fsName, serviceProtocol),
_packagesFilePath = packagesFilePath ?? fs.path.join(rootDirectory.path, kPackagesFileName);
DevFS.operations(
@@ -327,9 +362,11 @@
this.fsName,
this.rootDirectory, {
String packagesFilePath,
- }) : _packagesFilePath = packagesFilePath ?? fs.path.join(rootDirectory.path, kPackagesFileName);
+ }) : _httpWriter = null,
+ _packagesFilePath = packagesFilePath ?? fs.path.join(rootDirectory.path, kPackagesFileName);
final DevFSOperations _operations;
+ final _DevFSHttpWriter _httpWriter;
final String fsName;
final Directory rootDirectory;
String _packagesFilePath;
@@ -452,7 +489,7 @@
printTrace('Updating files');
if (dirtyEntries.isNotEmpty) {
try {
- await _operations.write(dirtyEntries);
+ await _httpWriter.write(dirtyEntries);
} on SocketException catch (socketException, stackTrace) {
printTrace('DevFS sync failed. Lost connection to device: $socketException');
throw DevFSException('Lost connection to device.', socketException, stackTrace);