Tools/ChangeLog

112011-01-27 Dirk Pranke <dpranke@chromium.org>
22
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Clean up of the filesystem-related modules used in webkitpy.
 6 I've added relpath() to the filesystem interface, modified
 7 ospath.relpath() so that it could work with the filesystem
 8 interface, and modified the fileset* routines to use the
 9 filesystem interface consistently.
 10
 11 This patch also adds a close() routine to the fileset routines
 12 to indicate that the caller is done with the fileset. This
 13 allows zipfileset to clean up after itself when it creates
 14 tempfiles to store downloads.
 15
 16 * Scripts/webkitpy/common/system/directoryfileset.py:
 17 * Scripts/webkitpy/common/system/fileset.py:
 18 * Scripts/webkitpy/common/system/filesystem.py:
 19 * Scripts/webkitpy/common/system/filesystem_mock.py:
 20 * Scripts/webkitpy/common/system/ospath.py:
 21 * Scripts/webkitpy/common/system/zipfileset.py:
 22 * Scripts/webkitpy/common/system/zipfileset_unittest.py:
 23
 242011-01-27 Dirk Pranke <dpranke@chromium.org>
 25
326 Reviewed by Mihai Parparita.
427
528 new-run-webkit-tests: turn off pixel tests correctly by default

Tools/Scripts/webkitpy/common/system/directoryfileset.py

2121# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2222# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2323
24 from __future__ import with_statement
25 
26 import os
27 import shutil
28 
2924from webkitpy.common.system.fileset import FileSetFileHandle
3025from webkitpy.common.system.filesystem import FileSystem
31 import webkitpy.common.system.ospath as ospath
3226
3327
3428class DirectoryFileSet(object):

@@class DirectoryFileSet(object):
3630 def __init__(self, path, filesystem=None):
3731 self._path = path
3832 self._filesystem = filesystem or FileSystem()
39  if not self._path.endswith(os.path.sep):
40  self._path += os.path.sep
 33 if not self._path.endswith(self._filesystem.sep):
 34 self._path += self._filesystem.sep
4135
4236 def _full_path(self, filename):
4337 assert self._is_under(self._path, filename)

@@class DirectoryFileSet(object):
5246 return self._filesystem.files_under(self._path)
5347
5448 def _is_under(self, dir, filename):
55  return bool(ospath.relpath(self._filesystem.join(dir, filename), dir))
 49 return bool(self._filesystem.relpath(self._filesystem.join(dir, filename), dir))
5650
5751 def open(self, filename):
5852 return FileSetFileHandle(self, filename, self._filesystem)

@@class DirectoryFileSet(object):
6963 dest = self._filesystem.join(path, filename)
7064 # As filename may have slashes in it, we must ensure that the same
7165 # directory hierarchy exists at the output path.
72  self._filesystem.maybe_make_directory(os.path.split(dest)[0])
 66 self._filesystem.maybe_make_directory(self._filesystem.dirname(dest))
7367 self._filesystem.copyfile(src, dest)
7468
7569 def delete(self, filename):

Tools/Scripts/webkitpy/common/system/fileset.py

2222# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2323
2424from __future__ import with_statement
25 import os
2625
2726from webkitpy.common.system.filesystem import FileSystem
2827

@@class FileSetFileHandle(object):
3837 def __str__(self):
3938 return "%s:%s" % (self._fileset, self._filename)
4039
 40 def close(self):
 41 pass
 42
4143 def contents(self):
4244 if self._contents is None:
4345 self._contents = self._fileset.read(self._filename)

@@class FileSetFileHandle(object):
6163 return self._filename
6264
6365 def splitext(self):
64  return os.path.splitext(self.name())
 66 return self._filesystem.splitext(self.name())

Tools/Scripts/webkitpy/common/system/filesystem.py

@@import shutil
3939import tempfile
4040import time
4141
 42from webkitpy.common.system import ospath
 43
4244class FileSystem(object):
4345 """FileSystem interface for webkitpy.
4446

@@class FileSystem(object):
200202 with codecs.open(path, 'r', 'utf8') as f:
201203 return f.read()
202204
 205 def relpath(self, path, start='.'):
 206 """Returns the relative path from the starting point."""
 207 return ospath.relpath(path, start)
 208
203209 class _WindowsError(exceptions.OSError):
204210 """Fake exception for Linux and Mac."""
205211 pass

Tools/Scripts/webkitpy/common/system/filesystem_mock.py

2828
2929import errno
3030import os
31 import path
3231import re
3332
 33from webkitpy.common.system import path
 34from webkitpy.common.system import ospath
 35
3436
3537class MockFileSystem(object):
3638 def __init__(self, files=None):

@@class MockFileSystem(object):
5153 raise IOError(errno.ENOENT, path, os.strerror(errno.ENOENT))
5254
5355 def _split(self, path):
54  idx = path.rfind('/')
 56 idx = path.rfind(self.sep)
5557 return (path[0:idx], path[idx + 1:])
5658
5759 def abspath(self, path):
 60 if path.endswith(self.sep):
 61 return path[:-1]
5862 return path
5963
6064 def basename(self, path):

@@class MockFileSystem(object):
9195 if self.basename(path) in dirs_to_skip:
9296 return []
9397
94  if not path.endswith('/'):
95  path += '/'
 98 if not path.endswith(self.sep):
 99 path += self.sep
96100
97  dir_substrings = ['/' + d + '/' for d in dirs_to_skip]
 101 dir_substrings = [self.sep + d + self.sep for d in dirs_to_skip]
98102 for filename in self.files:
99103 if not filename.startswith(path):
100104 continue

@@class MockFileSystem(object):
118122 return [f for f in self.files if f == path]
119123
120124 def isabs(self, path):
121  return path.startswith('/')
 125 return path.startswith(self.sep)
122126
123127 def isfile(self, path):
124128 return path in self.files and self.files[path] is not None

@@class MockFileSystem(object):
126130 def isdir(self, path):
127131 if path in self.files:
128132 return False
129  if not path.endswith('/'):
130  path += '/'
 133 if not path.endswith(self.sep):
 134 path += self.sep
131135
132136 # We need to use a copy of the keys here in order to avoid switching
133137 # to a different thread and potentially modifying the dict in

@@class MockFileSystem(object):
136140 return any(f.startswith(path) for f in files)
137141
138142 def join(self, *comps):
139  return re.sub(re.escape(os.path.sep), '/', os.path.join(*comps))
 143 # FIXME: might want tests for this and/or a better comment about how
 144 # it works.
 145 return re.sub(re.escape(os.path.sep), self.sep, os.path.join(*comps))
140146
141147 def listdir(self, path):
142148 if not self.isdir(path):
143149 raise OSError("%s is not a directory" % path)
144150
145  if not path.endswith('/'):
146  path += '/'
 151 if not path.endswith(self.sep):
 152 path += self.sep
147153
148154 dirs = []
149155 files = []
150156 for f in self.files:
151157 if self.exists(f) and f.startswith(path):
152158 remaining = f[len(path):]
153  if '/' in remaining:
154  dir = remaining[:remaining.index('/')]
 159 if self.sep in remaining:
 160 dir = remaining[:remaining.index(self.sep)]
155161 if not dir in dirs:
156162 dirs.append(dir)
157163 else:

@@class MockFileSystem(object):
165171
166172 def _mktemp(self, suffix='', prefix='tmp', dir=None, **kwargs):
167173 if dir is None:
168  dir = '/__im_tmp'
 174 dir = self.sep + '__im_tmp'
169175 curno = self.current_tmpno
170176 self.current_tmpno += 1
171177 return self.join(dir, "%s_%u_%s" % (prefix, curno, suffix))

@@class MockFileSystem(object):
224230 self._raise_not_found(path)
225231 return self.files[path]
226232
 233 def relpath(self, path, start='.'):
 234 return ospath.relpath(path, start, self.abspath, self.sep)
 235
227236 def remove(self, path):
228237 if self.files[path] is None:
229238 self._raise_not_found(path)

@@class MockFileSystem(object):
231240 self.written_files[path] = None
232241
233242 def rmtree(self, path):
234  if not path.endswith('/'):
235  path += '/'
 243 if not path.endswith(self.sep):
 244 path += self.sep
236245
237246 for f in self.files:
238247 if f.startswith(path):

Tools/Scripts/webkitpy/common/system/ospath.py

@@import os
3232#
3333# It should behave essentially the same as os.path.relpath(), except for
3434# returning None on paths not contained in abs_start_path.
35 def relpath(path, start_path, os_path_abspath=None):
 35def relpath(path, start_path, os_path_abspath=None, sep=None):
3636 """Return a path relative to the given start path, or None.
3737
3838 Returns None if the path is not contained in the directory start_path.

@@def relpath(path, start_path, os_path_abspath=None):
4444 os_path_abspath: A replacement function for unit testing. This
4545 function should strip trailing slashes just like
4646 os.path.abspath(). Defaults to os.path.abspath.
 47 sep: Path separator. Defaults to os.path.sep
4748
4849 """
4950 if os_path_abspath is None:
5051 os_path_abspath = os.path.abspath
 52 sep = sep or os.sep
5153
5254 # Since os_path_abspath() calls os.path.normpath()--
5355 #

@@def relpath(path, start_path, os_path_abspath=None):
6769 if not rel_path:
6870 # Then the paths are the same.
6971 pass
70  elif rel_path[0] == os.sep:
 72 elif rel_path[0] == sep:
7173 # It is probably sufficient to remove just the first character
7274 # since os.path.normpath() collapses separators, but we use
7375 # lstrip() just to be sure.
74  rel_path = rel_path.lstrip(os.sep)
 76 rel_path = rel_path.lstrip(sep)
7577 else:
7678 # We are in the case typified by the following example:
7779 #

Tools/Scripts/webkitpy/common/system/zipfileset.py

@@class ZipFileSet(object):
3333 """The set of files in a zip file that resides at a URL (local or remote)"""
3434 def __init__(self, zip_url, filesystem=None, zip_factory=None):
3535 self._zip_url = zip_url
 36 self._temp_file = None
3637 self._zip_file = None
3738 self._filesystem = filesystem or FileSystem()
3839 self._zip_factory = zip_factory or self._retrieve_zip_file
3940
4041 def _retrieve_zip_file(self, zip_url):
4142 temp_file = NetworkTransaction().run(lambda: urllib.urlretrieve(zip_url)[0])
42  return zipfile.ZipFile(temp_file)
 43 return (temp_file, zipfile.ZipFile(temp_file))
4344
4445 def _load(self):
4546 if self._zip_file is None:
46  self._zip_file = self._zip_factory(self._zip_url)
 47 self._temp_file, self._zip_file = self._zip_factory(self._zip_url)
4748
4849 def open(self, filename):
4950 self._load()
5051 return FileSetFileHandle(self, filename, self._filesystem)
5152
 53 def close(self):
 54 if self._temp_file:
 55 self._filesystem.remove(self._temp_file)
 56 self._temp_file = None
 57
5258 def namelist(self):
5359 self._load()
5460 return self._zip_file.namelist()

Tools/Scripts/webkitpy/common/system/zipfileset_unittest.py

@@class ZipFileSetTest(unittest.TestCase):
6464 result = FakeZip(self._filesystem)
6565 result.add_file('some-file', 'contents')
6666 result.add_file('a/b/some-other-file', 'other contents')
67  return result
 67 return (None, result)
6868
6969 def test_open(self):
7070 file = self._zip.open('a/b/some-other-file')
7171 self.assertEquals('a/b/some-other-file', file.name())
7272 self.assertEquals('other contents', file.contents())
7373
 74 def test_close(self):
 75 zipfileset = ZipFileSet('blah', self._filesystem, self.make_fake_zip)
 76 zipfileset.close()
 77
7478 def test_read(self):
7579 self.assertEquals('contents', self._zip.read('some-file'))
7680