Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(712)

Unified Diff: sdk/lib/vmservice/devfs.dart

Issue 2120473004: Reimplement devfs in dart. Implementation now writes to disk. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code review Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/vm_sources.gypi ('k') | sdk/lib/vmservice/vmservice.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/vmservice/devfs.dart
diff --git a/sdk/lib/vmservice/devfs.dart b/sdk/lib/vmservice/devfs.dart
new file mode 100644
index 0000000000000000000000000000000000000000..35af74822d7b27accf8b66c60175c7cdcab29576
--- /dev/null
+++ b/sdk/lib/vmservice/devfs.dart
@@ -0,0 +1,319 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart._vmservice;
+
+String _encodeDevFSDisabledError(Message message) {
+ return encodeRpcError(
+ message, kFeatureDisabled,
+ details: "DevFS is not supported by this Dart implementation");
+}
+
+String _encodeFileSystemAlreadyExistsError(Message message, String fsName) {
+ return encodeRpcError(
+ message, kFileSystemAlreadyExists,
+ details: "${message.method}: file system '${fsName}' already exists");
+}
+
+String _encodeFileSystemDoesNotExistError(Message message, String fsName) {
+ return encodeRpcError(
+ message, kFileSystemDoesNotExist,
+ details: "${message.method}: file system '${fsName}' does not exist");
+}
+
+class _FileSystem {
+ _FileSystem(this.name, this.uri);
+
+ final String name;
+ final Uri uri;
+
+ Uri resolvePath(String path) {
+ if (path.startsWith('/')) {
+ path = path.substring(1);
+ }
+ if (path.isEmpty) {
+ return null;
+ }
+ Uri pathUri;
+ try {
+ pathUri = Uri.parse(path);
+ } on FormatException catch(e) {
+ return null;
+ }
+ Uri resolvedUri = uri.resolveUri(pathUri);
+ if (!resolvedUri.toString().startsWith(uri.toString())) {
+ // Resolved uri must be within the filesystem's base uri.
+ return null;
+ }
+ return resolvedUri;
+ }
+
+ Map toMap() {
+ return {
+ 'type': 'FileSystem',
+ 'name': name,
+ 'uri': uri.toString(),
+ };
+ }
+}
+
+class DevFS {
+ DevFS();
+
+ Map<String, _FileSystem> _fsMap = {};
+
+ final Set _rpcNames = new Set.from([
+ '_listDevFS',
+ '_createDevFS',
+ '_deleteDevFS',
+ '_readDevFSFile',
+ '_writeDevFSFile',
+ '_writeDevFSFiles',
+ '_listDevFSFiles',
+ ]);
+
+ void cleanup() {
+ var deleteDir = VMServiceEmbedderHooks.deleteDir;
+ if (deleteDir == null) {
+ return;
+ }
+ var deletions = [];
+ for (var fs in _fsMap.values) {
+ deletions.add(deleteDir(fs.uri));
+ }
+ Future.wait(deletions);
+ _fsMap.clear();
+ }
+
+ bool shouldHandleMessage(Message message) {
+ return _rpcNames.contains(message.method);
+ }
+
+ Future<String> handleMessage(Message message) async {
+ switch (message.method) {
+ case '_listDevFS':
+ return _listDevFS(message);
+ case '_createDevFS':
+ return _createDevFS(message);
+ case '_deleteDevFS':
+ return _deleteDevFS(message);
+ case '_readDevFSFile':
+ return _readDevFSFile(message);
+ case '_writeDevFSFile':
+ return _writeDevFSFile(message);
+ case '_writeDevFSFiles':
+ return _writeDevFSFiles(message);
+ case '_listDevFSFiles':
+ return _listDevFSFiles(message);
+ default:
+ return encodeRpcError(
+ message, kInternalError,
+ details: 'Unexpected rpc ${message.method}');
+ }
+ }
+
+ Future<String> _listDevFS(Message message) async {
+ var result = {};
+ result['type'] = 'FileSystemList';
+ result['fsNames'] = _fsMap.keys.toList();
+ return encodeResult(message, result);
+ }
+
+ Future<String> _createDevFS(Message message) async {
+ var createTempDir = VMServiceEmbedderHooks.createTempDir;
+ if (createTempDir == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ var fsName = message.params['fsName'];
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap[fsName];
+ if (fs != null) {
+ return _encodeFileSystemAlreadyExistsError(message, fsName);
+ }
+ var tempDir = await createTempDir(fsName);
+ fs = new _FileSystem(fsName, tempDir);
+ _fsMap[fsName] = fs;
+ return encodeResult(message, fs.toMap());
+ }
+
+ Future<String> _deleteDevFS(Message message) async {
+ var deleteDir = VMServiceEmbedderHooks.deleteDir;
+ if (deleteDir == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ var fsName = message.params['fsName'];
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap.remove(fsName);
+ if (fs == null) {
+ return _encodeFileSystemDoesNotExistError(message, fsName);
+ }
+ await deleteDir(fs.uri);
+ return encodeSuccess(message);
+ }
+
+ Future<String> _readDevFSFile(Message message) async {
+ var readFile = VMServiceEmbedderHooks.readFile;
+ if (readFile == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ var fsName = message.params['fsName'];
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap[fsName];
+ if (fs == null) {
+ return _encodeFileSystemDoesNotExistError(message, fsName);
+ }
+ var path = message.params['path'];
+ if (path == null) {
+ return encodeMissingParamError(message, 'path');
+ }
+ if (path is! String) {
+ return encodeInvalidParamError(message, 'path');
+ }
+ Uri uri = fs.resolvePath(path);
+ if (uri == null) {
+ return encodeInvalidParamError(message, 'path');
+ }
+
+ try {
+ List<int> bytes = await readFile(uri);
+ var result = {
+ 'type': 'FSFile',
+ 'fileContents': BASE64.encode(bytes)
+ };
+ return encodeResult(message, result);
+ } catch (e) {
+ return encodeRpcError(
+ message, kFileDoesNotExist,
+ details: "_readDevFSFile: $e");
+ }
+ }
+
+ Future<String> _writeDevFSFile(Message message) async {
+ var writeFile = VMServiceEmbedderHooks.writeFile;
+ if (writeFile == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ var fsName = message.params['fsName'];
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap[fsName];
+ if (fs == null) {
+ return _encodeFileSystemDoesNotExistError(message, fsName);
+ }
+ var path = message.params['path'];
+ if (path == null) {
+ return encodeMissingParamError(message, 'path');
+ }
+ if (path is! String) {
+ return encodeInvalidParamError(message, 'path');
+ }
+ Uri uri = fs.resolvePath(path);
+ if (uri == null) {
+ return encodeInvalidParamError(message, 'path');
+ }
+ var fileContents = message.params['fileContents'];
+ if (fileContents == null) {
+ return encodeMissingParamError(message, 'fileContents');
+ }
+ if (fileContents is! String) {
+ return encodeInvalidParamError(message, 'fileContents');
+ }
+ List<int> decodedFileContents = BASE64.decode(fileContents);
+
+ await writeFile(uri, decodedFileContents);
+ return encodeSuccess(message);
+ }
+
+ Future<String> _writeDevFSFiles(Message message) async {
+ var writeFile = VMServiceEmbedderHooks.writeFile;
+ if (writeFile == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ var fsName = message.params['fsName'];
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap[fsName];
+ if (fs == null) {
+ return _encodeFileSystemDoesNotExistError(message, fsName);
+ }
+ var files = message.params['files'];
+ if (files == null) {
+ return encodeMissingParamError(message, 'files');
+ }
+ if (files is! List) {
+ return encodeInvalidParamError(message, 'files');
+ }
+ var uris = [];
+ for (int i = 0; i < files.length; i++) {
+ var fileInfo = files[i];
+ if (fileInfo is! List ||
+ fileInfo.length != 2 ||
+ fileInfo[0] is! String || fileInfo[1] is! String) {
+ return encodeRpcError(
+ message, kInvalidParams,
+ details: "${message.method}: invalid 'files' parameter "
+ "at index ${i}: ${fileInfo}");
+ }
+ var uri = fs.resolvePath(fileInfo[0]);
+ if (uri == null) {
+ return encodeRpcError(
+ message, kInvalidParams,
+ details: "${message.method}: invalid 'files' parameter "
+ "at index ${i}: ${fileInfo}");
+ }
+ uris.add(uri);
+ }
+ var pendingWrites = [];
+ for (int i = 0; i < uris.length; i++) {
+ List<int> decodedFileContents = BASE64.decode(files[i][1]);
+ pendingWrites.add(writeFile(uris[i], decodedFileContents));
+ }
+ await Future.wait(pendingWrites);
+ return encodeSuccess(message);
+ }
+
+ Future<String> _listDevFSFiles(Message message) async {
+ var listFiles = VMServiceEmbedderHooks.listFiles;
+ if (listFiles == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ var fsName = message.params['fsName'];
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap[fsName];
+ if (fs == null) {
+ return _encodeFileSystemDoesNotExistError(message, fsName);
+ }
+ var fileList = await listFiles(fs.uri);
+ var result = { 'type': 'FSFileList', 'files': fileList };
+ return encodeResult(message, result);
+ }
+}
« no previous file with comments | « runtime/vm/vm_sources.gypi ('k') | sdk/lib/vmservice/vmservice.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698