| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 class _Directory implements Directory { | 7 class _Directory implements Directory { |
| 8 static const CREATE_REQUEST = 0; | 8 static const CREATE_REQUEST = 0; |
| 9 static const DELETE_REQUEST = 1; | 9 static const DELETE_REQUEST = 1; |
| 10 static const EXISTS_REQUEST = 2; | 10 static const EXISTS_REQUEST = 2; |
| 11 static const CREATE_TEMP_REQUEST = 3; | 11 static const CREATE_TEMP_REQUEST = 3; |
| 12 static const LIST_START_REQUEST = 4; | 12 static const LIST_START_REQUEST = 4; |
| 13 static const LIST_NEXT_REQUEST = 5; | 13 static const LIST_NEXT_REQUEST = 5; |
| 14 static const LIST_STOP_REQUEST = 6; | 14 static const LIST_STOP_REQUEST = 6; |
| 15 static const RENAME_REQUEST = 7; | 15 static const RENAME_REQUEST = 7; |
| 16 | 16 |
| 17 _Directory(String this._path); | 17 final String path; |
| 18 SendPort _directoryService; |
| 19 |
| 20 _Directory(String this.path) { |
| 21 if (path is! String) { |
| 22 throw new ArgumentError('${Error.safeToString(path)} ' |
| 23 'is not a String'); |
| 24 } |
| 25 } |
| 26 |
| 18 _Directory.fromPath(Path path) : this(path.toNativePath()); | 27 _Directory.fromPath(Path path) : this(path.toNativePath()); |
| 19 | 28 |
| 20 external static String _current(); | 29 external static String _current(); |
| 21 external static _setCurrent(path); | 30 external static _setCurrent(path); |
| 22 external static _createTemp(String template); | 31 external static _createTemp(String template); |
| 23 external static int _exists(String path); | 32 external static int _exists(String path); |
| 24 external static _create(String path); | 33 external static _create(String path); |
| 25 external static _delete(String path, bool recursive); | 34 external static _delete(String path, bool recursive); |
| 26 external static _rename(String path, String newPath); | 35 external static _rename(String path, String newPath); |
| 27 external static List _list(String path, bool recursive, bool followLinks); | 36 external static List _list(String path, bool recursive, bool followLinks); |
| 28 external static SendPort _newServicePort(); | 37 external static SendPort _newServicePort(); |
| 29 | 38 |
| 30 static Directory get current => new _Directory(_current()); | 39 static Directory get current => new _Directory(_current()); |
| 31 | 40 |
| 32 static void set current(path) { | 41 static void set current(path) { |
| 33 if (path is Directory) path = path.path; | 42 if (path is Directory) path = path.path; |
| 34 var result = _setCurrent(path); | 43 var result = _setCurrent(path); |
| 35 if (result is ArgumentError) throw result; | 44 if (result is ArgumentError) throw result; |
| 36 if (result is OSError) { | 45 if (result is OSError) { |
| 37 throw new DirectoryException( | 46 throw new DirectoryException( |
| 38 "Setting current working directory failed", path, result); | 47 "Setting current working directory failed", path, result); |
| 39 } | 48 } |
| 40 } | 49 } |
| 41 | 50 |
| 42 Future<bool> exists() { | 51 Future<bool> exists() { |
| 43 _ensureDirectoryService(); | 52 _ensureDirectoryService(); |
| 44 List request = new List(2); | 53 List request = new List(2); |
| 45 request[0] = EXISTS_REQUEST; | 54 request[0] = EXISTS_REQUEST; |
| 46 request[1] = _path; | 55 request[1] = path; |
| 47 return _directoryService.call(request).then((response) { | 56 return _directoryService.call(request).then((response) { |
| 48 if (_isErrorResponse(response)) { | 57 if (_isErrorResponse(response)) { |
| 49 throw _exceptionOrErrorFromResponse(response, "Exists failed"); | 58 throw _exceptionOrErrorFromResponse(response, "Exists failed"); |
| 50 } | 59 } |
| 51 return response == 1; | 60 return response == 1; |
| 52 }); | 61 }); |
| 53 } | 62 } |
| 54 | 63 |
| 55 bool existsSync() { | 64 bool existsSync() { |
| 56 if (_path is !String) { | 65 var result = _exists(path); |
| 57 throw new ArgumentError(); | |
| 58 } | |
| 59 var result = _exists(_path); | |
| 60 if (result is OSError) { | 66 if (result is OSError) { |
| 61 throw new DirectoryException("Exists failed", _path, result); | 67 throw new DirectoryException("Exists failed", path, result); |
| 62 } | 68 } |
| 63 return (result == 1); | 69 return (result == 1); |
| 64 } | 70 } |
| 65 | 71 |
| 66 Future<FileStat> stat() => FileStat.stat(path); | 72 Future<FileStat> stat() => FileStat.stat(path); |
| 67 | 73 |
| 68 FileStat statSync() => FileStat.statSync(path); | 74 FileStat statSync() => FileStat.statSync(path); |
| 69 | 75 |
| 70 // Compute the index of the first directory in the list that exists. If | 76 // Compute the index of the first directory in the list that exists. If |
| 71 // none of the directories exist dirsToCreate.length is returned. | 77 // none of the directories exist dirsToCreate.length is returned. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 85 } | 91 } |
| 86 } | 92 } |
| 87 if (future == null) { | 93 if (future == null) { |
| 88 return new Future.value(notFound); | 94 return new Future.value(notFound); |
| 89 } else { | 95 } else { |
| 90 return future; | 96 return future; |
| 91 } | 97 } |
| 92 } | 98 } |
| 93 | 99 |
| 94 Future<Directory> createRecursively() { | 100 Future<Directory> createRecursively() { |
| 95 if (_path is !String) { | 101 var path = new Path(path); |
| 96 throw new ArgumentError(); | |
| 97 } | |
| 98 var path = new Path(_path); | |
| 99 var dirsToCreate = []; | 102 var dirsToCreate = []; |
| 100 var terminator = path.isAbsolute ? '/' : ''; | 103 var terminator = path.isAbsolute ? '/' : ''; |
| 101 while (path.toString() != terminator) { | 104 while (path.toString() != terminator) { |
| 102 dirsToCreate.add(new Directory.fromPath(path)); | 105 dirsToCreate.add(new Directory.fromPath(path)); |
| 103 path = path.directoryPath; | 106 path = path.directoryPath; |
| 104 } | 107 } |
| 105 return _computeExistingIndex(dirsToCreate).then((index) { | 108 return _computeExistingIndex(dirsToCreate).then((index) { |
| 106 var future; | 109 var future; |
| 107 for (var i = index - 1; i >= 0 ; i--) { | 110 for (var i = index - 1; i >= 0 ; i--) { |
| 108 if (future == null) { | 111 if (future == null) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 119 return future.then((_) => this); | 122 return future.then((_) => this); |
| 120 } | 123 } |
| 121 }); | 124 }); |
| 122 } | 125 } |
| 123 | 126 |
| 124 Future<Directory> create({recursive: false}) { | 127 Future<Directory> create({recursive: false}) { |
| 125 if (recursive) return createRecursively(); | 128 if (recursive) return createRecursively(); |
| 126 _ensureDirectoryService(); | 129 _ensureDirectoryService(); |
| 127 List request = new List(2); | 130 List request = new List(2); |
| 128 request[0] = CREATE_REQUEST; | 131 request[0] = CREATE_REQUEST; |
| 129 request[1] = _path; | 132 request[1] = path; |
| 130 return _directoryService.call(request).then((response) { | 133 return _directoryService.call(request).then((response) { |
| 131 if (_isErrorResponse(response)) { | 134 if (_isErrorResponse(response)) { |
| 132 throw _exceptionOrErrorFromResponse(response, "Creation failed"); | 135 throw _exceptionOrErrorFromResponse(response, "Creation failed"); |
| 133 } | 136 } |
| 134 return this; | 137 return this; |
| 135 }); | 138 }); |
| 136 } | 139 } |
| 137 | 140 |
| 138 void createRecursivelySync() { | 141 void createRecursivelySync() { |
| 139 var path = new Path(_path); | 142 var path = new Path(path); |
| 140 var dirsToCreate = []; | 143 var dirsToCreate = []; |
| 141 var terminator = path.isAbsolute ? '/' : ''; | 144 var terminator = path.isAbsolute ? '/' : ''; |
| 142 while (path.toString() != terminator) { | 145 while (path.toString() != terminator) { |
| 143 var dir = new Directory.fromPath(path); | 146 var dir = new Directory.fromPath(path); |
| 144 if (dir.existsSync()) break; | 147 if (dir.existsSync()) break; |
| 145 dirsToCreate.add(dir); | 148 dirsToCreate.add(dir); |
| 146 path = path.directoryPath; | 149 path = path.directoryPath; |
| 147 } | 150 } |
| 148 for (var i = dirsToCreate.length - 1; i >= 0; i--) { | 151 for (var i = dirsToCreate.length - 1; i >= 0; i--) { |
| 149 dirsToCreate[i].createSync(); | 152 dirsToCreate[i].createSync(); |
| 150 } | 153 } |
| 151 } | 154 } |
| 152 | 155 |
| 153 void createSync({recursive: false}) { | 156 void createSync({recursive: false}) { |
| 154 if (_path is !String) { | |
| 155 throw new ArgumentError(); | |
| 156 } | |
| 157 if (recursive) return createRecursivelySync(); | 157 if (recursive) return createRecursivelySync(); |
| 158 var result = _create(_path); | 158 var result = _create(path); |
| 159 if (result is OSError) { | 159 if (result is OSError) { |
| 160 throw new DirectoryException("Creation failed", _path, result); | 160 throw new DirectoryException("Creation failed", path, result); |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 | 163 |
| 164 Future<Directory> createTemp() { | 164 Future<Directory> createTemp() { |
| 165 _ensureDirectoryService(); | 165 _ensureDirectoryService(); |
| 166 List request = new List(2); | 166 List request = new List(2); |
| 167 request[0] = CREATE_TEMP_REQUEST; | 167 request[0] = CREATE_TEMP_REQUEST; |
| 168 request[1] = _path; | 168 request[1] = path; |
| 169 return _directoryService.call(request).then((response) { | 169 return _directoryService.call(request).then((response) { |
| 170 if (_isErrorResponse(response)) { | 170 if (_isErrorResponse(response)) { |
| 171 throw _exceptionOrErrorFromResponse( | 171 throw _exceptionOrErrorFromResponse( |
| 172 response, "Creation of temporary directory failed"); | 172 response, "Creation of temporary directory failed"); |
| 173 } | 173 } |
| 174 return new Directory(response); | 174 return new Directory(response); |
| 175 }); | 175 }); |
| 176 } | 176 } |
| 177 | 177 |
| 178 Directory createTempSync() { | 178 Directory createTempSync() { |
| 179 if (_path is !String) { | |
| 180 throw new ArgumentError(); | |
| 181 } | |
| 182 var result = _createTemp(path); | 179 var result = _createTemp(path); |
| 183 if (result is OSError) { | 180 if (result is OSError) { |
| 184 throw new DirectoryException("Creation of temporary directory failed", | 181 throw new DirectoryException("Creation of temporary directory failed", |
| 185 _path, | 182 path, |
| 186 result); | 183 result); |
| 187 } | 184 } |
| 188 return new Directory(result); | 185 return new Directory(result); |
| 189 } | 186 } |
| 190 | 187 |
| 191 Future<Directory> delete({recursive: false}) { | 188 Future<Directory> delete({recursive: false}) { |
| 192 _ensureDirectoryService(); | 189 _ensureDirectoryService(); |
| 193 List request = new List(3); | 190 List request = new List(3); |
| 194 request[0] = DELETE_REQUEST; | 191 request[0] = DELETE_REQUEST; |
| 195 request[1] = _path; | 192 request[1] = path; |
| 196 request[2] = recursive; | 193 request[2] = recursive; |
| 197 return _directoryService.call(request).then((response) { | 194 return _directoryService.call(request).then((response) { |
| 198 if (_isErrorResponse(response)) { | 195 if (_isErrorResponse(response)) { |
| 199 throw _exceptionOrErrorFromResponse(response, "Deletion failed"); | 196 throw _exceptionOrErrorFromResponse(response, "Deletion failed"); |
| 200 } | 197 } |
| 201 return this; | 198 return this; |
| 202 }); | 199 }); |
| 203 } | 200 } |
| 204 | 201 |
| 205 void deleteSync({recursive: false}) { | 202 void deleteSync({recursive: false}) { |
| 206 if (_path is !String) { | 203 var result = _delete(path, recursive); |
| 207 throw new ArgumentError(); | |
| 208 } | |
| 209 var result = _delete(_path, recursive); | |
| 210 if (result is OSError) { | 204 if (result is OSError) { |
| 211 throw new DirectoryException("Deletion failed", _path, result); | 205 throw new DirectoryException("Deletion failed", path, result); |
| 212 } | 206 } |
| 213 } | 207 } |
| 214 | 208 |
| 215 Future<Directory> rename(String newPath) { | 209 Future<Directory> rename(String newPath) { |
| 216 _ensureDirectoryService(); | 210 _ensureDirectoryService(); |
| 217 List request = new List(3); | 211 List request = new List(3); |
| 218 request[0] = RENAME_REQUEST; | 212 request[0] = RENAME_REQUEST; |
| 219 request[1] = _path; | 213 request[1] = path; |
| 220 request[2] = newPath; | 214 request[2] = newPath; |
| 221 return _directoryService.call(request).then((response) { | 215 return _directoryService.call(request).then((response) { |
| 222 if (_isErrorResponse(response)) { | 216 if (_isErrorResponse(response)) { |
| 223 throw _exceptionOrErrorFromResponse(response, "Rename failed"); | 217 throw _exceptionOrErrorFromResponse(response, "Rename failed"); |
| 224 } | 218 } |
| 225 return new Directory(newPath); | 219 return new Directory(newPath); |
| 226 }); | 220 }); |
| 227 } | 221 } |
| 228 | 222 |
| 229 Directory renameSync(String newPath) { | 223 Directory renameSync(String newPath) { |
| 230 if (_path is !String || newPath is !String) { | 224 if (newPath is !String) { |
| 231 throw new ArgumentError(); | 225 throw new ArgumentError(); |
| 232 } | 226 } |
| 233 var result = _rename(_path, newPath); | 227 var result = _rename(path, newPath); |
| 234 if (result is OSError) { | 228 if (result is OSError) { |
| 235 throw new DirectoryException("Rename failed", _path, result); | 229 throw new DirectoryException("Rename failed", path, result); |
| 236 } | 230 } |
| 237 return new Directory(newPath); | 231 return new Directory(newPath); |
| 238 } | 232 } |
| 239 | 233 |
| 240 static String _trimTrailingPathSeparators(String path) { | 234 static String _trimTrailingPathSeparators(String path) { |
| 241 // Don't handle argument errors here. | 235 // Don't handle argument errors here. |
| 242 if (path is! String) return path; | 236 if (path is! String) return path; |
| 243 if (Platform.operatingSystem == 'windows') { | 237 if (Platform.operatingSystem == 'windows') { |
| 244 while (path.length > 1 && | 238 while (path.length > 1 && |
| 245 (path.endsWith(Platform.pathSeparator) || | 239 (path.endsWith(Platform.pathSeparator) || |
| 246 path.endsWith('/'))) { | 240 path.endsWith('/'))) { |
| 247 path = path.substring(0, path.length - 1); | 241 path = path.substring(0, path.length - 1); |
| 248 } | 242 } |
| 249 } else { | 243 } else { |
| 250 while (path.length > 1 && path.endsWith(Platform.pathSeparator)) { | 244 while (path.length > 1 && path.endsWith(Platform.pathSeparator)) { |
| 251 path = path.substring(0, path.length - 1); | 245 path = path.substring(0, path.length - 1); |
| 252 } | 246 } |
| 253 } | 247 } |
| 254 return path; | 248 return path; |
| 255 } | 249 } |
| 256 | 250 |
| 257 Stream<FileSystemEntity> list({bool recursive: false, | 251 Stream<FileSystemEntity> list({bool recursive: false, |
| 258 bool followLinks: true}) { | 252 bool followLinks: true}) { |
| 259 return new _AsyncDirectoryLister(_trimTrailingPathSeparators(path), | 253 return new _AsyncDirectoryLister(_trimTrailingPathSeparators(path), |
| 260 recursive, | 254 recursive, |
| 261 followLinks).stream; | 255 followLinks).stream; |
| 262 } | 256 } |
| 263 | 257 |
| 264 List listSync({bool recursive: false, bool followLinks: true}) { | 258 List listSync({bool recursive: false, bool followLinks: true}) { |
| 265 if (_path is! String || recursive is! bool || followLinks is! bool) { | 259 if (recursive is! bool || followLinks is! bool) { |
| 266 throw new ArgumentError(); | 260 throw new ArgumentError(); |
| 267 } | 261 } |
| 268 return _list(_trimTrailingPathSeparators(path), recursive, followLinks); | 262 return _list(_trimTrailingPathSeparators(path), recursive, followLinks); |
| 269 } | 263 } |
| 270 | 264 |
| 271 String get path => _path; | |
| 272 | |
| 273 String toString() => "Directory: '$path'"; | 265 String toString() => "Directory: '$path'"; |
| 274 | 266 |
| 275 bool _isErrorResponse(response) { | 267 bool _isErrorResponse(response) { |
| 276 return response is List && response[0] != _SUCCESS_RESPONSE; | 268 return response is List && response[0] != _SUCCESS_RESPONSE; |
| 277 } | 269 } |
| 278 | 270 |
| 279 _exceptionOrErrorFromResponse(response, String message) { | 271 _exceptionOrErrorFromResponse(response, String message) { |
| 280 assert(_isErrorResponse(response)); | 272 assert(_isErrorResponse(response)); |
| 281 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { | 273 switch (response[_ERROR_RESPONSE_ERROR_TYPE]) { |
| 282 case _ILLEGAL_ARGUMENT_RESPONSE: | 274 case _ILLEGAL_ARGUMENT_RESPONSE: |
| 283 return new ArgumentError(); | 275 return new ArgumentError(); |
| 284 case _OSERROR_RESPONSE: | 276 case _OSERROR_RESPONSE: |
| 285 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], | 277 var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE], |
| 286 response[_OSERROR_RESPONSE_ERROR_CODE]); | 278 response[_OSERROR_RESPONSE_ERROR_CODE]); |
| 287 return new DirectoryException(message, _path, err); | 279 return new DirectoryException(message, path, err); |
| 288 default: | 280 default: |
| 289 return new Exception("Unknown error"); | 281 return new Exception("Unknown error"); |
| 290 } | 282 } |
| 291 } | 283 } |
| 292 | 284 |
| 293 void _ensureDirectoryService() { | 285 void _ensureDirectoryService() { |
| 294 if (_directoryService == null) { | 286 if (_directoryService == null) { |
| 295 _directoryService = _newServicePort(); | 287 _directoryService = _newServicePort(); |
| 296 } | 288 } |
| 297 } | 289 } |
| 298 | |
| 299 final String _path; | |
| 300 SendPort _directoryService; | |
| 301 } | 290 } |
| 302 | 291 |
| 303 class _AsyncDirectoryLister { | 292 class _AsyncDirectoryLister { |
| 304 static const int LIST_FILE = 0; | 293 static const int LIST_FILE = 0; |
| 305 static const int LIST_DIRECTORY = 1; | 294 static const int LIST_DIRECTORY = 1; |
| 306 static const int LIST_LINK = 2; | 295 static const int LIST_LINK = 2; |
| 307 static const int LIST_ERROR = 3; | 296 static const int LIST_ERROR = 3; |
| 308 static const int LIST_DONE = 4; | 297 static const int LIST_DONE = 4; |
| 309 | 298 |
| 310 static const int RESPONSE_TYPE = 0; | 299 static const int RESPONSE_TYPE = 0; |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 controller.addError( | 414 controller.addError( |
| 426 new DirectoryException("Directory listing failed", | 415 new DirectoryException("Directory listing failed", |
| 427 errorPath, | 416 errorPath, |
| 428 err)); | 417 err)); |
| 429 } else { | 418 } else { |
| 430 controller.addError( | 419 controller.addError( |
| 431 new DirectoryException("Internal error")); | 420 new DirectoryException("Internal error")); |
| 432 } | 421 } |
| 433 } | 422 } |
| 434 } | 423 } |
| OLD | NEW |