diff options
Diffstat (limited to 'Tools/Scripts/webkitpy/common/system')
6 files changed, 150 insertions, 3 deletions
diff --git a/Tools/Scripts/webkitpy/common/system/executive.py b/Tools/Scripts/webkitpy/common/system/executive.py index 85a683a..02619db 100644 --- a/Tools/Scripts/webkitpy/common/system/executive.py +++ b/Tools/Scripts/webkitpy/common/system/executive.py @@ -53,6 +53,14 @@ _log = logging.getLogger("webkitpy.common.system") class ScriptError(Exception): + # This is a custom List.__str__ implementation to allow size limiting. + def _string_from_args(self, args, limit=100): + args_string = unicode(args) + # We could make this much fancier, but for now this is OK. + if len(args_string) > limit: + return args_string[:limit - 3] + "..." + return args_string + def __init__(self, message=None, script_args=None, @@ -60,7 +68,7 @@ class ScriptError(Exception): output=None, cwd=None): if not message: - message = 'Failed to run "%s"' % script_args + message = 'Failed to run "%s"' % self._string_from_args(script_args) if exit_code: message += " exit_code: %d" % exit_code if cwd: @@ -75,9 +83,9 @@ class ScriptError(Exception): def message_with_output(self, output_limit=500): if self.output: if output_limit and len(self.output) > output_limit: - return u"%s\nLast %s characters of output:\n%s" % \ + return u"%s\n\nLast %s characters of output:\n%s" % \ (self, output_limit, self.output[-output_limit:]) - return u"%s\n%s" % (self, self.output) + return u"%s\n\n%s" % (self, self.output) return unicode(self) def command_name(self): diff --git a/Tools/Scripts/webkitpy/common/system/executive_unittest.py b/Tools/Scripts/webkitpy/common/system/executive_unittest.py index b8fd82e..a43b4dc 100644 --- a/Tools/Scripts/webkitpy/common/system/executive_unittest.py +++ b/Tools/Scripts/webkitpy/common/system/executive_unittest.py @@ -37,6 +37,23 @@ from webkitpy.common.system.executive import Executive, run_command, ScriptError from webkitpy.test import cat, echo +class ScriptErrorTest(unittest.TestCase): + def test_string_from_args(self): + error = ScriptError() + self.assertEquals(error._string_from_args(None), 'None') + self.assertEquals(error._string_from_args([]), '[]') + self.assertEquals(error._string_from_args(map(str, range(30))), "['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17'...") + + def test_message_with_output(self): + error = ScriptError('My custom message!', '', -1) + self.assertEquals(error.message_with_output(), 'My custom message!') + error = ScriptError('My custom message!', '', -1, 'My output.') + self.assertEquals(error.message_with_output(), 'My custom message!\n\nMy output.') + error = ScriptError('', 'my_command!', -1, 'My output.', '/Users/username/blah') + self.assertEquals(error.message_with_output(), 'Failed to run "my_command!" exit_code: -1 cwd: /Users/username/blah\n\nMy output.') + error = ScriptError('', 'my_command!', -1, 'ab' + '1' * 499) + self.assertEquals(error.message_with_output(), 'Failed to run "my_command!" exit_code: -1\n\nLast 500 characters of output:\nb' + '1' * 499) + def never_ending_command(): """Arguments for a command that will never end (useful for testing process killing). It should be a process that is unlikely to already be running diff --git a/Tools/Scripts/webkitpy/common/system/filesystem.py b/Tools/Scripts/webkitpy/common/system/filesystem.py index 8830ea8..527b6bd 100644 --- a/Tools/Scripts/webkitpy/common/system/filesystem.py +++ b/Tools/Scripts/webkitpy/common/system/filesystem.py @@ -124,6 +124,9 @@ class FileSystem(object): if retry_timeout_sec < 0: raise e + def remove_tree(self, path, ignore_errors=False): + shutil.rmtree(path, ignore_errors) + def read_binary_file(self, path): """Return the contents of the file at the given path as a byte string.""" with file(path, 'rb') as f: diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py index c605cb2..809c4c6 100644 --- a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py +++ b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py @@ -116,3 +116,6 @@ class MockFileSystem(object): def remove(self, path): del self.files[path] + + def remove_tree(self, path, ignore_errors=False): + self.files = [file for file in self.files if not file.startswith(path)] diff --git a/Tools/Scripts/webkitpy/common/system/workspace.py b/Tools/Scripts/webkitpy/common/system/workspace.py new file mode 100644 index 0000000..3b755ad --- /dev/null +++ b/Tools/Scripts/webkitpy/common/system/workspace.py @@ -0,0 +1,61 @@ +# Copyright (c) 2010 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. + +# A home for file logic which should sit above FileSystem, but +# below more complicated objects. + +import zipfile + +class Workspace(object): + def __init__(self, filesystem, executive): + self._filesystem = filesystem + self._executive = executive # FIXME: Remove if create_zip is moved to python. + + def find_unused_filename(self, directory, name, extension, search_limit=10): + for count in range(search_limit): + if count: + target_name = "%s-%s.%s" % (name, count, extension) + else: + target_name = "%s.%s" % (name, extension) + target_path = self._filesystem.join(directory, target_name) + if not self._filesystem.exists(target_path): + return target_path + # If we can't find an unused name in search_limit tries, just give up. + return None + + def create_zip(self, zip_path, source_path, zip_class=zipfile.ZipFile): + # It's possible to create zips with Python: + # zip_file = ZipFile(zip_path, 'w') + # for root, dirs, files in os.walk(source_path): + # for path in files: + # absolute_path = os.path.join(root, path) + # zip_file.write(os.path.relpath(path, source_path)) + # However, getting the paths, encoding and compression correct could be non-trivial. + # So, for now we depend on the environment having "zip" installed (likely fails on Win32) + self._executive.run_command(['zip', '-r', zip_path, source_path]) + return zip_class(zip_path) diff --git a/Tools/Scripts/webkitpy/common/system/workspace_unittest.py b/Tools/Scripts/webkitpy/common/system/workspace_unittest.py new file mode 100644 index 0000000..e5fbb26 --- /dev/null +++ b/Tools/Scripts/webkitpy/common/system/workspace_unittest.py @@ -0,0 +1,55 @@ +# Copyright (C) 2010 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 unittest + +from webkitpy.common.system.filesystem_mock import MockFileSystem +from webkitpy.common.system.outputcapture import OutputCapture +from webkitpy.common.system.workspace import Workspace +from webkitpy.tool.mocktool import MockExecutive + + +class WorkspaceTest(unittest.TestCase): + + def test_find_unused_filename(self): + filesystem = MockFileSystem({ + "dir/foo.jpg": "", + "dir/foo-1.jpg": "", + }) + workspace = Workspace(filesystem, None) + self.assertEqual(workspace.find_unused_filename("bar", "bar", "bar"), "bar/bar.bar") + self.assertEqual(workspace.find_unused_filename("dir", "foo", "jpg"), "dir/foo-2.jpg") + + def test_create_zip(self): + workspace = Workspace(None, MockExecutive(should_log=True)) + expected_stderr = "MOCK run_command: ['zip', '-r', '/zip/path', '/source/path']\n" + class MockZipFile(object): + def __init__(self, path): + self.filename = path + archive = OutputCapture().assert_outputs(self, workspace.create_zip, ["/zip/path", "/source/path", MockZipFile], expected_stderr=expected_stderr) + self.assertEqual(archive.filename, "/zip/path") |