| OLD | NEW |
| 1 # Copyright (C) 2009 Google Inc. All rights reserved. | 1 # Copyright (C) 2009 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 import StringIO | 29 import StringIO |
| 30 import errno | 30 import errno |
| 31 import hashlib | 31 import hashlib |
| 32 import os | 32 import os |
| 33 import re | 33 import re |
| 34 | 34 |
| 35 from webkitpy.common.system import path |
| 36 |
| 35 | 37 |
| 36 class MockFileSystem(object): | 38 class MockFileSystem(object): |
| 37 sep = '/' | 39 sep = '/' |
| 38 pardir = '..' | 40 pardir = '..' |
| 39 | 41 |
| 40 def __init__(self, files=None, dirs=None, cwd='/'): | 42 def __init__(self, files=None, dirs=None, cwd='/'): |
| 41 """Initializes a "mock" filesystem that can be used to completely | 43 """Initializes a "mock" filesystem that can be used to completely |
| 42 stub out a filesystem. | 44 stub out a filesystem. |
| 43 | 45 |
| 44 Args: | 46 Args: |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 119 |
| 118 self.files[destination] = self.files[source] | 120 self.files[destination] = self.files[source] |
| 119 self.written_files[destination] = self.files[source] | 121 self.written_files[destination] = self.files[source] |
| 120 | 122 |
| 121 def dirname(self, path): | 123 def dirname(self, path): |
| 122 return self._split(path)[0] | 124 return self._split(path)[0] |
| 123 | 125 |
| 124 def exists(self, path): | 126 def exists(self, path): |
| 125 return self.isfile(path) or self.isdir(path) | 127 return self.isfile(path) or self.isdir(path) |
| 126 | 128 |
| 127 def files_under(self, path, dirs_to_skip=None, file_filter=None): | 129 def files_under(self, path, dirs_to_skip=[], file_filter=None): |
| 128 dirs_to_skip = dirs_to_skip or [] | 130 def filter_all(fs, dirpath, basename): |
| 129 | |
| 130 def filter_all(*_): | |
| 131 return True | 131 return True |
| 132 | 132 |
| 133 file_filter = file_filter or filter_all | 133 file_filter = file_filter or filter_all |
| 134 files = [] | 134 files = [] |
| 135 if self.isfile(path): | 135 if self.isfile(path): |
| 136 if file_filter(self, self.dirname(path), self.basename(path)) and se
lf.files[path] is not None: | 136 if file_filter(self, self.dirname(path), self.basename(path)) and se
lf.files[path] is not None: |
| 137 files.append(path) | 137 files.append(path) |
| 138 return files | 138 return files |
| 139 | 139 |
| 140 if self.basename(path) in dirs_to_skip: | 140 if self.basename(path) in dirs_to_skip: |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 return dirs + files | 208 return dirs + files |
| 209 | 209 |
| 210 def walk(self, top): | 210 def walk(self, top): |
| 211 sep = self.sep | 211 sep = self.sep |
| 212 if not self.isdir(top): | 212 if not self.isdir(top): |
| 213 raise OSError("%s is not a directory" % top) | 213 raise OSError("%s is not a directory" % top) |
| 214 | 214 |
| 215 if not top.endswith(sep): | 215 if not top.endswith(sep): |
| 216 top += sep | 216 top += sep |
| 217 | 217 |
| 218 directories = [] | 218 dirs = [] |
| 219 files = [] | 219 files = [] |
| 220 for f in self.files: | 220 for f in self.files: |
| 221 if self.exists(f) and f.startswith(top): | 221 if self.exists(f) and f.startswith(top): |
| 222 remaining = f[len(top):] | 222 remaining = f[len(top):] |
| 223 if sep in remaining: | 223 if sep in remaining: |
| 224 directory = remaining[:remaining.index(sep)] | 224 dir = remaining[:remaining.index(sep)] |
| 225 if directory not in directories: | 225 if not dir in dirs: |
| 226 directories.append(directory) | 226 dirs.append(dir) |
| 227 else: | 227 else: |
| 228 files.append(remaining) | 228 files.append(remaining) |
| 229 file_system_tuples = [(top[:-1], directories, files)] | 229 file_system_tuples = [(top[:-1], dirs, files)] |
| 230 for directory in directories: | 230 for dir in dirs: |
| 231 directory = top + directory | 231 dir = top + dir |
| 232 tuples_from_subdirs = self.walk(directory) | 232 tuples_from_subdirs = self.walk(dir) |
| 233 file_system_tuples += tuples_from_subdirs | 233 file_system_tuples += tuples_from_subdirs |
| 234 return file_system_tuples | 234 return file_system_tuples |
| 235 | 235 |
| 236 def mtime(self, path): | 236 def mtime(self, path): |
| 237 if self.exists(path): | 237 if self.exists(path): |
| 238 return 0 | 238 return 0 |
| 239 self._raise_not_found(path) | 239 self._raise_not_found(path) |
| 240 | 240 |
| 241 def _mktemp(self, suffix='', prefix='tmp', directory=None, **_): | 241 def _mktemp(self, suffix='', prefix='tmp', dir=None, **kwargs): |
| 242 if directory is None: | 242 if dir is None: |
| 243 directory = self.sep + '__im_tmp' | 243 dir = self.sep + '__im_tmp' |
| 244 curno = self.current_tmpno | 244 curno = self.current_tmpno |
| 245 self.current_tmpno += 1 | 245 self.current_tmpno += 1 |
| 246 self.last_tmpdir = self.join(directory, '%s_%u_%s' % (prefix, curno, suf
fix)) | 246 self.last_tmpdir = self.join(dir, '%s_%u_%s' % (prefix, curno, suffix)) |
| 247 return self.last_tmpdir | 247 return self.last_tmpdir |
| 248 | 248 |
| 249 def mkdtemp(self, **kwargs): | 249 def mkdtemp(self, **kwargs): |
| 250 class TemporaryDirectory(object): | 250 class TemporaryDirectory(object): |
| 251 | 251 |
| 252 def __init__(self, fs, **kwargs): | 252 def __init__(self, fs, **kwargs): |
| 253 self._kwargs = kwargs | 253 self._kwargs = kwargs |
| 254 self._filesystem = fs | 254 self._filesystem = fs |
| 255 self._directory_path = fs._mktemp(**kwargs) | 255 self._directory_path = fs._mktemp(**kwargs) |
| 256 fs.maybe_make_directory(self._directory_path) | 256 fs.maybe_make_directory(self._directory_path) |
| 257 | 257 |
| 258 def __str__(self): | 258 def __str__(self): |
| 259 return self._directory_path | 259 return self._directory_path |
| 260 | 260 |
| 261 def __enter__(self): | 261 def __enter__(self): |
| 262 return self._directory_path | 262 return self._directory_path |
| 263 | 263 |
| 264 def __exit__(self, *_): | 264 def __exit__(self, type, value, traceback): |
| 265 # Only self-delete if necessary. | 265 # Only self-delete if necessary. |
| 266 | 266 |
| 267 # FIXME: Should we delete non-empty directories? | 267 # FIXME: Should we delete non-empty directories? |
| 268 if self._filesystem.exists(self._directory_path): | 268 if self._filesystem.exists(self._directory_path): |
| 269 self._filesystem.rmtree(self._directory_path) | 269 self._filesystem.rmtree(self._directory_path) |
| 270 | 270 |
| 271 return TemporaryDirectory(fs=self, **kwargs) | 271 return TemporaryDirectory(fs=self, **kwargs) |
| 272 | 272 |
| 273 def maybe_make_directory(self, *path): | 273 def maybe_make_directory(self, *path): |
| 274 norm_path = self.normpath(self.join(*path)) | 274 norm_path = self.normpath(self.join(*path)) |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 | 391 |
| 392 def rmtree(self, path): | 392 def rmtree(self, path): |
| 393 path = self.normpath(path) | 393 path = self.normpath(path) |
| 394 | 394 |
| 395 for f in self.files: | 395 for f in self.files: |
| 396 # We need to add a trailing separator to path to avoid matching | 396 # We need to add a trailing separator to path to avoid matching |
| 397 # cases like path='/foo/b' and f='/foo/bar/baz'. | 397 # cases like path='/foo/b' and f='/foo/bar/baz'. |
| 398 if f == path or f.startswith(path + self.sep): | 398 if f == path or f.startswith(path + self.sep): |
| 399 self.files[f] = None | 399 self.files[f] = None |
| 400 | 400 |
| 401 self.dirs = {d for d in self.dirs if not (d == path or d.startswith(path
+ self.sep))} | 401 self.dirs = set(filter(lambda d: not (d == path or d.startswith(path + s
elf.sep)), self.dirs)) |
| 402 | 402 |
| 403 def copytree(self, source, destination): | 403 def copytree(self, source, destination): |
| 404 source = self.normpath(source) | 404 source = self.normpath(source) |
| 405 destination = self.normpath(destination) | 405 destination = self.normpath(destination) |
| 406 | 406 |
| 407 for source_file in list(self.files): | 407 for source_file in list(self.files): |
| 408 if source_file.startswith(source): | 408 if source_file.startswith(source): |
| 409 destination_path = self.join(destination, self.relpath(source_fi
le, source)) | 409 destination_path = self.join(destination, self.relpath(source_fi
le, source)) |
| 410 self.maybe_make_directory(self.dirname(destination_path)) | 410 self.maybe_make_directory(self.dirname(destination_path)) |
| 411 self.files[destination_path] = self.files[source_file] | 411 self.files[destination_path] = self.files[source_file] |
| (...skipping 15 matching lines...) Expand all Loading... |
| 427 | 427 |
| 428 def __init__(self, fs, path): | 428 def __init__(self, fs, path): |
| 429 self.fs = fs | 429 self.fs = fs |
| 430 self.path = path | 430 self.path = path |
| 431 self.closed = False | 431 self.closed = False |
| 432 self.fs.files[path] = "" | 432 self.fs.files[path] = "" |
| 433 | 433 |
| 434 def __enter__(self): | 434 def __enter__(self): |
| 435 return self | 435 return self |
| 436 | 436 |
| 437 def __exit__(self, *_): | 437 def __exit__(self, type, value, traceback): |
| 438 self.close() | 438 self.close() |
| 439 | 439 |
| 440 def close(self): | 440 def close(self): |
| 441 self.closed = True | 441 self.closed = True |
| 442 | 442 |
| 443 def write(self, string): | 443 def write(self, str): |
| 444 self.fs.files[self.path] += string | 444 self.fs.files[self.path] += str |
| 445 self.fs.written_files[self.path] = self.fs.files[self.path] | 445 self.fs.written_files[self.path] = self.fs.files[self.path] |
| 446 | 446 |
| 447 | 447 |
| 448 class WritableTextFileObject(WritableBinaryFileObject): | 448 class WritableTextFileObject(WritableBinaryFileObject): |
| 449 | 449 |
| 450 def write(self, string): | 450 def write(self, str): |
| 451 WritableBinaryFileObject.write(self, string.encode('utf-8')) | 451 WritableBinaryFileObject.write(self, str.encode('utf-8')) |
| 452 | 452 |
| 453 | 453 |
| 454 class ReadableBinaryFileObject(object): | 454 class ReadableBinaryFileObject(object): |
| 455 | 455 |
| 456 def __init__(self, fs, path, data): | 456 def __init__(self, fs, path, data): |
| 457 self.fs = fs | 457 self.fs = fs |
| 458 self.path = path | 458 self.path = path |
| 459 self.closed = False | 459 self.closed = False |
| 460 self.data = data | 460 self.data = data |
| 461 self.offset = 0 | 461 self.offset = 0 |
| 462 | 462 |
| 463 def __enter__(self): | 463 def __enter__(self): |
| 464 return self | 464 return self |
| 465 | 465 |
| 466 def __exit__(self, *_): | 466 def __exit__(self, type, value, traceback): |
| 467 self.close() | 467 self.close() |
| 468 | 468 |
| 469 def close(self): | 469 def close(self): |
| 470 self.closed = True | 470 self.closed = True |
| 471 | 471 |
| 472 def read(self, num_bytes=None): | 472 def read(self, bytes=None): |
| 473 if not num_bytes: | 473 if not bytes: |
| 474 return self.data[self.offset:] | 474 return self.data[self.offset:] |
| 475 start = self.offset | 475 start = self.offset |
| 476 self.offset += num_bytes | 476 self.offset += bytes |
| 477 return self.data[start:self.offset] | 477 return self.data[start:self.offset] |
| 478 | 478 |
| 479 | 479 |
| 480 class ReadableTextFileObject(ReadableBinaryFileObject): | 480 class ReadableTextFileObject(ReadableBinaryFileObject): |
| 481 | 481 |
| 482 def __init__(self, fs, path, data): | 482 def __init__(self, fs, path, data): |
| 483 super(ReadableTextFileObject, self).__init__(fs, path, StringIO.StringIO
(data.decode("utf-8"))) | 483 super(ReadableTextFileObject, self).__init__(fs, path, StringIO.StringIO
(data.decode("utf-8"))) |
| 484 | 484 |
| 485 def close(self): | 485 def close(self): |
| 486 self.data.close() | 486 self.data.close() |
| 487 super(ReadableTextFileObject, self).close() | 487 super(ReadableTextFileObject, self).close() |
| 488 | 488 |
| 489 def read(self, num_bytes=-1): | 489 def read(self, bytes=-1): |
| 490 return self.data.read(num_bytes) | 490 return self.data.read(bytes) |
| 491 | 491 |
| 492 def readline(self, length=None): | 492 def readline(self, length=None): |
| 493 return self.data.readline(length) | 493 return self.data.readline(length) |
| 494 | 494 |
| 495 def __iter__(self): | 495 def __iter__(self): |
| 496 return self.data.__iter__() | 496 return self.data.__iter__() |
| 497 | 497 |
| 498 def next(self): | 498 def next(self): |
| 499 return self.data.next() | 499 return self.data.next() |
| 500 | 500 |
| 501 def seek(self, offset, whence=os.SEEK_SET): | 501 def seek(self, offset, whence=os.SEEK_SET): |
| 502 self.data.seek(offset, whence) | 502 self.data.seek(offset, whence) |
| OLD | NEW |