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 |