summaryrefslogtreecommitdiff
path: root/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy/common/system/filesystem_mock.py')
-rw-r--r--Tools/Scripts/webkitpy/common/system/filesystem_mock.py474
1 files changed, 0 insertions, 474 deletions
diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
deleted file mode 100644
index ee0664ea0..000000000
--- a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py
+++ /dev/null
@@ -1,474 +0,0 @@
-# Copyright (C) 2009 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import StringIO
-import errno
-import hashlib
-import os
-import re
-
-from webkitpy.common.system import path
-
-
-class MockFileSystem(object):
- sep = '/'
- pardir = '..'
-
- def __init__(self, files=None, dirs=None, cwd='/'):
- """Initializes a "mock" filesystem that can be used to completely
- stub out a filesystem.
-
- Args:
- files: a dict of filenames -> file contents. A file contents
- value of None is used to indicate that the file should
- not exist.
- """
- self.files = files or {}
- self.written_files = {}
- self.last_tmpdir = None
- self.current_tmpno = 0
- self.cwd = cwd
- self.dirs = set(dirs or [])
- self.dirs.add(cwd)
- for f in self.files:
- d = self.dirname(f)
- while not d in self.dirs:
- self.dirs.add(d)
- d = self.dirname(d)
-
- def clear_written_files(self):
- # This function can be used to track what is written between steps in a test.
- self.written_files = {}
-
- def _raise_not_found(self, path):
- raise IOError(errno.ENOENT, path, os.strerror(errno.ENOENT))
-
- def _split(self, path):
- # This is not quite a full implementation of os.path.split
- # http://docs.python.org/library/os.path.html#os.path.split
- if self.sep in path:
- return path.rsplit(self.sep, 1)
- return ('', path)
-
- def abspath(self, path):
- if os.path.isabs(path):
- return self.normpath(path)
- return self.abspath(self.join(self.cwd, path))
-
- def realpath(self, path):
- return self.abspath(path)
-
- def basename(self, path):
- return self._split(path)[1]
-
- def expanduser(self, path):
- if path[0] != "~":
- return path
- parts = path.split(self.sep, 1)
- home_directory = self.sep + "Users" + self.sep + "mock"
- if len(parts) == 1:
- return home_directory
- return home_directory + self.sep + parts[1]
-
- def path_to_module(self, module_name):
- return "/mock-checkout/Tools/Scripts/" + module_name.replace('.', '/') + ".py"
-
- def chdir(self, path):
- path = self.normpath(path)
- if not self.isdir(path):
- raise OSError(errno.ENOENT, path, os.strerror(errno.ENOENT))
- self.cwd = path
-
- def copyfile(self, source, destination):
- if not self.exists(source):
- self._raise_not_found(source)
- if self.isdir(source):
- raise IOError(errno.EISDIR, source, os.strerror(errno.EISDIR))
- if self.isdir(destination):
- raise IOError(errno.EISDIR, destination, os.strerror(errno.EISDIR))
- if not self.exists(self.dirname(destination)):
- raise IOError(errno.ENOENT, destination, os.strerror(errno.ENOENT))
-
- self.files[destination] = self.files[source]
- self.written_files[destination] = self.files[source]
-
- def dirname(self, path):
- return self._split(path)[0]
-
- def exists(self, path):
- return self.isfile(path) or self.isdir(path)
-
- def files_under(self, path, dirs_to_skip=[], file_filter=None):
- def filter_all(fs, dirpath, basename):
- return True
-
- file_filter = file_filter or filter_all
- files = []
- if self.isfile(path):
- if file_filter(self, self.dirname(path), self.basename(path)) and self.files[path] is not None:
- files.append(path)
- return files
-
- if self.basename(path) in dirs_to_skip:
- return []
-
- if not path.endswith(self.sep):
- path += self.sep
-
- dir_substrings = [self.sep + d + self.sep for d in dirs_to_skip]
- for filename in self.files:
- if not filename.startswith(path):
- continue
-
- suffix = filename[len(path) - 1:]
- if any(dir_substring in suffix for dir_substring in dir_substrings):
- continue
-
- dirpath, basename = self._split(filename)
- if file_filter(self, dirpath, basename) and self.files[filename] is not None:
- files.append(filename)
-
- return files
-
- def getcwd(self):
- return self.cwd
-
- def glob(self, glob_string):
- # FIXME: This handles '*', but not '?', '[', or ']'.
- glob_string = re.escape(glob_string)
- glob_string = glob_string.replace('\\*', '[^\\/]*') + '$'
- glob_string = glob_string.replace('\\/', '/')
- path_filter = lambda path: re.match(glob_string, path)
-
- # We could use fnmatch.fnmatch, but that might not do the right thing on windows.
- existing_files = [path for path, contents in self.files.items() if contents is not None]
- return filter(path_filter, existing_files) + filter(path_filter, self.dirs)
-
- def isabs(self, path):
- return path.startswith(self.sep)
-
- def isfile(self, path):
- return path in self.files and self.files[path] is not None
-
- def isdir(self, path):
- return self.normpath(path) in self.dirs
-
- def _slow_but_correct_join(self, *comps):
- return re.sub(re.escape(os.path.sep), self.sep, os.path.join(*comps))
-
- def join(self, *comps):
- # This function is called a lot, so we optimize it; there are
- # unittests to check that we match _slow_but_correct_join(), above.
- path = ''
- sep = self.sep
- for comp in comps:
- if not comp:
- continue
- if comp[0] == sep:
- path = comp
- continue
- if path:
- path += sep
- path += comp
- if comps[-1] == '' and path:
- path += '/'
- path = path.replace(sep + sep, sep)
- return path
-
- def listdir(self, path):
- sep = self.sep
- if not self.isdir(path):
- raise OSError("%s is not a directory" % path)
-
- if not path.endswith(sep):
- path += sep
-
- dirs = []
- files = []
- for f in self.files:
- if self.exists(f) and f.startswith(path):
- remaining = f[len(path):]
- if sep in remaining:
- dir = remaining[:remaining.index(sep)]
- if not dir in dirs:
- dirs.append(dir)
- else:
- files.append(remaining)
- return dirs + files
-
- def mtime(self, path):
- if self.exists(path):
- return 0
- self._raise_not_found(path)
-
- def _mktemp(self, suffix='', prefix='tmp', dir=None, **kwargs):
- if dir is None:
- dir = self.sep + '__im_tmp'
- curno = self.current_tmpno
- self.current_tmpno += 1
- self.last_tmpdir = self.join(dir, '%s_%u_%s' % (prefix, curno, suffix))
- return self.last_tmpdir
-
- def mkdtemp(self, **kwargs):
- class TemporaryDirectory(object):
- def __init__(self, fs, **kwargs):
- self._kwargs = kwargs
- self._filesystem = fs
- self._directory_path = fs._mktemp(**kwargs)
- fs.maybe_make_directory(self._directory_path)
-
- def __str__(self):
- return self._directory_path
-
- def __enter__(self):
- return self._directory_path
-
- def __exit__(self, type, value, traceback):
- # Only self-delete if necessary.
-
- # FIXME: Should we delete non-empty directories?
- if self._filesystem.exists(self._directory_path):
- self._filesystem.rmtree(self._directory_path)
-
- return TemporaryDirectory(fs=self, **kwargs)
-
- def maybe_make_directory(self, *path):
- norm_path = self.normpath(self.join(*path))
- while norm_path and not self.isdir(norm_path):
- self.dirs.add(norm_path)
- norm_path = self.dirname(norm_path)
-
- def move(self, source, destination):
- if self.files[source] is None:
- self._raise_not_found(source)
- self.files[destination] = self.files[source]
- self.written_files[destination] = self.files[destination]
- self.files[source] = None
- self.written_files[source] = None
-
- def _slow_but_correct_normpath(self, path):
- return re.sub(re.escape(os.path.sep), self.sep, os.path.normpath(path))
-
- def normpath(self, path):
- # This function is called a lot, so we try to optimize the common cases
- # instead of always calling _slow_but_correct_normpath(), above.
- if '..' in path or '/./' in path:
- # This doesn't happen very often; don't bother trying to optimize it.
- return self._slow_but_correct_normpath(path)
- if not path:
- return '.'
- if path == '/':
- return path
- if path == '/.':
- return '/'
- if path.endswith('/.'):
- return path[:-2]
- if path.endswith('/'):
- return path[:-1]
- return path
-
- def open_binary_tempfile(self, suffix=''):
- path = self._mktemp(suffix)
- return (WritableBinaryFileObject(self, path), path)
-
- def open_binary_file_for_reading(self, path):
- if self.files[path] is None:
- self._raise_not_found(path)
- return ReadableBinaryFileObject(self, path, self.files[path])
-
- def read_binary_file(self, path):
- # Intentionally raises KeyError if we don't recognize the path.
- if self.files[path] is None:
- self._raise_not_found(path)
- return self.files[path]
-
- def write_binary_file(self, path, contents):
- # FIXME: should this assert if dirname(path) doesn't exist?
- self.maybe_make_directory(self.dirname(path))
- self.files[path] = contents
- self.written_files[path] = contents
-
- def open_text_file_for_reading(self, path):
- if self.files[path] is None:
- self._raise_not_found(path)
- return ReadableTextFileObject(self, path, self.files[path])
-
- def open_text_file_for_writing(self, path):
- return WritableTextFileObject(self, path)
-
- def read_text_file(self, path):
- return self.read_binary_file(path).decode('utf-8')
-
- def write_text_file(self, path, contents):
- return self.write_binary_file(path, contents.encode('utf-8'))
-
- def sha1(self, path):
- contents = self.read_binary_file(path)
- return hashlib.sha1(contents).hexdigest()
-
- def relpath(self, path, start='.'):
- # Since os.path.relpath() calls os.path.normpath()
- # (see http://docs.python.org/library/os.path.html#os.path.abspath )
- # it also removes trailing slashes and converts forward and backward
- # slashes to the preferred slash os.sep.
- start = self.abspath(start)
- path = self.abspath(path)
-
- if not path.lower().startswith(start.lower()):
- # path is outside the directory given by start; compute path from root
- return '../' * start.count('/') + path
-
- rel_path = path[len(start):]
-
- if not rel_path:
- # Then the paths are the same.
- pass
- elif rel_path[0] == self.sep:
- # It is probably sufficient to remove just the first character
- # since os.path.normpath() collapses separators, but we use
- # lstrip() just to be sure.
- rel_path = rel_path.lstrip(self.sep)
- else:
- # We are in the case typified by the following example:
- # path = "/tmp/foobar", start = "/tmp/foo" -> rel_path = "bar"
- # FIXME: We return a less-than-optimal result here.
- return '../' * start.count('/') + path
-
- return rel_path
-
- def remove(self, path):
- if self.files[path] is None:
- self._raise_not_found(path)
- self.files[path] = None
- self.written_files[path] = None
-
- def rmtree(self, path):
- path = self.normpath(path)
-
- for f in self.files:
- if f.startswith(path):
- self.files[f] = None
-
- self.dirs = set(filter(lambda d: not d.startswith(path), self.dirs))
-
- def copytree(self, source, destination):
- source = self.normpath(source)
- destination = self.normpath(destination)
-
- for source_file in self.files:
- if source_file.startswith(source):
- destination_path = self.join(destination, self.relpath(source_file, source))
- self.maybe_make_directory(self.dirname(destination_path))
- self.files[destination_path] = self.files[source_file]
-
- def split(self, path):
- idx = path.rfind(self.sep)
- if idx == -1:
- return ('', path)
- return (path[:idx], path[(idx + 1):])
-
- def splitext(self, path):
- idx = path.rfind('.')
- if idx == -1:
- idx = len(path)
- return (path[0:idx], path[idx:])
-
-
-class WritableBinaryFileObject(object):
- def __init__(self, fs, path):
- self.fs = fs
- self.path = path
- self.closed = False
- self.fs.files[path] = ""
-
- def __enter__(self):
- return self
-
- def __exit__(self, type, value, traceback):
- self.close()
-
- def close(self):
- self.closed = True
-
- def write(self, str):
- self.fs.files[self.path] += str
- self.fs.written_files[self.path] = self.fs.files[self.path]
-
-
-class WritableTextFileObject(WritableBinaryFileObject):
- def write(self, str):
- WritableBinaryFileObject.write(self, str.encode('utf-8'))
-
-
-class ReadableBinaryFileObject(object):
- def __init__(self, fs, path, data):
- self.fs = fs
- self.path = path
- self.closed = False
- self.data = data
- self.offset = 0
-
- def __enter__(self):
- return self
-
- def __exit__(self, type, value, traceback):
- self.close()
-
- def close(self):
- self.closed = True
-
- def read(self, bytes=None):
- if not bytes:
- return self.data[self.offset:]
- start = self.offset
- self.offset += bytes
- return self.data[start:self.offset]
-
-
-class ReadableTextFileObject(ReadableBinaryFileObject):
- def __init__(self, fs, path, data):
- super(ReadableTextFileObject, self).__init__(fs, path, StringIO.StringIO(data.decode("utf-8")))
-
- def close(self):
- self.data.close()
- super(ReadableTextFileObject, self).close()
-
- def read(self, bytes=-1):
- return self.data.read(bytes)
-
- def readline(self, length=None):
- return self.data.readline(length)
-
- def __iter__(self):
- return self.data.__iter__()
-
- def next(self):
- return self.data.next()
-
- def seek(self, offset, whence=os.SEEK_SET):
- self.data.seek(offset, whence)