diff options
Diffstat (limited to 'Tools/Scripts/webkitpy/common')
19 files changed, 226 insertions, 52 deletions
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm.py b/Tools/Scripts/webkitpy/common/checkout/scm.py index e436402..3e8d5e5 100644 --- a/Tools/Scripts/webkitpy/common/checkout/scm.py +++ b/Tools/Scripts/webkitpy/common/checkout/scm.py @@ -134,8 +134,9 @@ def commit_error_handler(error): class AuthenticationError(Exception): - def __init__(self, server_host): + def __init__(self, server_host, prompt_for_password=False): self.server_host = server_host + self.prompt_for_password = prompt_for_password class AmbiguousCommitError(Exception): @@ -291,7 +292,7 @@ class SCM: def revert_files(self, file_paths): self._subclass_must_implement() - def commit_with_message(self, message, username=None, git_commit=None, force_squash=False, changed_files=None): + def commit_with_message(self, message, username=None, password=None, git_commit=None, force_squash=False, changed_files=None): self._subclass_must_implement() def svn_commit_log(self, svn_revision): @@ -319,8 +320,19 @@ class SCM: return [] -class SVN(SCM): - # FIXME: We should move these values to a WebKit-specific config file. +# A mixin class that represents common functionality for SVN and Git-SVN. +class SVNRepository: + def has_authorization_for_realm(self, realm, home_directory=os.getenv("HOME")): + # Assumes find and grep are installed. + if not os.path.isdir(os.path.join(home_directory, ".subversion")): + return False + find_args = ["find", ".subversion", "-type", "f", "-exec", "grep", "-q", realm, "{}", ";", "-print"] + find_output = self.run(find_args, cwd=home_directory, error_handler=Executive.ignore_error).rstrip() + return find_output and os.path.isfile(os.path.join(home_directory, find_output)) + + +class SVN(SCM, SVNRepository): + # FIXME: These belong in common.config.urls svn_server_host = "svn.webkit.org" svn_server_realm = "<http://svn.webkit.org:80> Mac OS Forge" @@ -374,14 +386,6 @@ class SVN(SCM): def commit_success_regexp(): return "^Committed revision (?P<svn_revision>\d+)\.$" - def has_authorization_for_realm(self, realm=svn_server_realm, home_directory=os.getenv("HOME")): - # Assumes find and grep are installed. - if not os.path.isdir(os.path.join(home_directory, ".subversion")): - return False - find_args = ["find", ".subversion", "-type", "f", "-exec", "grep", "-q", realm, "{}", ";", "-print"]; - find_output = self.run(find_args, cwd=home_directory, error_handler=Executive.ignore_error).rstrip() - return find_output and os.path.isfile(os.path.join(home_directory, find_output)) - @memoized def svn_version(self): return self.run(['svn', '--version', '--quiet']) @@ -556,11 +560,11 @@ class SVN(SCM): # FIXME: This should probably use cwd=self.checkout_root. self.run(['svn', 'revert'] + file_paths) - def commit_with_message(self, message, username=None, git_commit=None, force_squash=False, changed_files=None): + def commit_with_message(self, message, username=None, password=None, git_commit=None, force_squash=False, changed_files=None): # git-commit and force are not used by SVN. svn_commit_args = ["svn", "commit"] - if not username and not self.has_authorization_for_realm(): + if not username and not self.has_authorization_for_realm(self.svn_server_realm): raise AuthenticationError(self.svn_server_host) if username: svn_commit_args.extend(["--username", username]) @@ -577,8 +581,7 @@ class SVN(SCM): # Return a string which looks like a commit so that things which parse this output will succeed. return "Dry run, no commit.\nCommitted revision 0." - # FIXME: Should this use cwd=self.checkout_root? - return self.run(svn_commit_args, error_handler=commit_error_handler) + return self.run(svn_commit_args, cwd=self.checkout_root, error_handler=commit_error_handler) def svn_commit_log(self, svn_revision): svn_revision = self.strip_r_from_svn_revision(svn_revision) @@ -599,7 +602,7 @@ class SVN(SCM): # All git-specific logic should go here. -class Git(SCM): +class Git(SCM, SVNRepository): def __init__(self, cwd, executive=None): SCM.__init__(self, cwd, executive) self._check_git_architecture() @@ -834,7 +837,7 @@ class Git(SCM): if num_local_commits > 1 or (num_local_commits > 0 and not working_directory_is_clean): raise AmbiguousCommitError(num_local_commits, working_directory_is_clean) - def commit_with_message(self, message, username=None, git_commit=None, force_squash=False, changed_files=None): + def commit_with_message(self, message, username=None, password=None, git_commit=None, force_squash=False, changed_files=None): # Username is ignored during Git commits. working_directory_is_clean = self.working_directory_is_clean() @@ -844,7 +847,7 @@ class Git(SCM): if working_directory_is_clean: raise ScriptError(message="The working copy is not modified. --git-commit=HEAD.. only commits working copy changes.") self.commit_locally_with_message(message) - return self._commit_on_branch(message, 'HEAD') + return self._commit_on_branch(message, 'HEAD', username=username, password=password) # Need working directory changes to be committed so we can checkout the merge branch. if not working_directory_is_clean: @@ -852,15 +855,15 @@ class Git(SCM): # That will modify the working-copy and cause us to hit this error. # The ChangeLog modification could be made to modify the existing local commit. raise ScriptError(message="Working copy is modified. Cannot commit individual git_commits.") - return self._commit_on_branch(message, git_commit) + return self._commit_on_branch(message, git_commit, username=username, password=password) if not force_squash: self._assert_can_squash(working_directory_is_clean) self.run(['git', 'reset', '--soft', self.remote_merge_base()]) self.commit_locally_with_message(message) - return self.push_local_commits_to_server() + return self.push_local_commits_to_server(username=username, password=password) - def _commit_on_branch(self, message, git_commit): + def _commit_on_branch(self, message, git_commit, username=None, password=None): branch_ref = self.run(['git', 'symbolic-ref', 'HEAD']).strip() branch_name = branch_ref.replace('refs/heads/', '') commit_ids = self.commit_ids_from_commitish_arguments([git_commit]) @@ -889,7 +892,7 @@ class Git(SCM): self.run(['git', 'cherry-pick', '--no-commit', commit]) self.run(['git', 'commit', '-m', message]) - output = self.push_local_commits_to_server() + output = self.push_local_commits_to_server(username=username, password=password) except Exception, e: log("COMMIT FAILED: " + str(e)) output = "Commit failed." @@ -937,11 +940,15 @@ class Git(SCM): def commit_locally_with_message(self, message): self.run(['git', 'commit', '--all', '-F', '-'], input=message) - def push_local_commits_to_server(self): + def push_local_commits_to_server(self, username=None, password=None): dcommit_command = ['git', 'svn', 'dcommit'] if self.dryrun: dcommit_command.append('--dry-run') - output = self.run(dcommit_command, error_handler=commit_error_handler) + if not self.has_authorization_for_realm(SVN.svn_server_realm): + raise AuthenticationError(SVN.svn_server_host, prompt_for_password=True) + if username: + dcommit_command.extend(["--username", username]) + output = self.run(dcommit_command, error_handler=commit_error_handler, input=password) # Return a string which looks like a commit so that things which parse this output will succeed. if self.dryrun: output += "\nCommitted r0" diff --git a/Tools/Scripts/webkitpy/common/checkout/scm_unittest.py b/Tools/Scripts/webkitpy/common/checkout/scm_unittest.py index 79b354d..ab3f45a 100644 --- a/Tools/Scripts/webkitpy/common/checkout/scm_unittest.py +++ b/Tools/Scripts/webkitpy/common/checkout/scm_unittest.py @@ -650,6 +650,13 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== commit_text = self.scm.commit_with_message("yet another test commit", username) self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0') + def test_commit_in_subdir(self, username=None): + write_into_file_at_path('test_dir/test_file3', 'more test content') + os.chdir("test_dir") + commit_text = self.scm.commit_with_message("another test commit", username) + os.chdir("..") + self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6') + def test_commit_text_parsing(self): self._shared_test_commit_with_message() @@ -657,7 +664,7 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== self._shared_test_commit_with_message("dbates@webkit.org") def test_commit_without_authorization(self): - self.scm.has_authorization_for_realm = lambda: False + self.scm.has_authorization_for_realm = lambda realm: False self.assertRaises(AuthenticationError, self._shared_test_commit_with_message) def test_has_authorization_for_realm(self): @@ -667,7 +674,7 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== os.mkdir(svn_config_dir_path) fake_webkit_auth_file = os.path.join(svn_config_dir_path, "fake_webkit_auth_file") write_into_file_at_path(fake_webkit_auth_file, SVN.svn_server_realm) - self.assertTrue(scm.has_authorization_for_realm(home_directory=fake_home_dir)) + self.assertTrue(scm.has_authorization_for_realm(SVN.svn_server_realm, home_directory=fake_home_dir)) os.remove(fake_webkit_auth_file) os.rmdir(svn_config_dir_path) os.rmdir(fake_home_dir) @@ -677,7 +684,7 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA== fake_home_dir = tempfile.mkdtemp(suffix="fake_home_dir") svn_config_dir_path = os.path.join(fake_home_dir, ".subversion") os.mkdir(svn_config_dir_path) - self.assertFalse(scm.has_authorization_for_realm(home_directory=fake_home_dir)) + self.assertFalse(scm.has_authorization_for_realm(SVN.svn_server_realm, home_directory=fake_home_dir)) os.rmdir(svn_config_dir_path) os.rmdir(fake_home_dir) diff --git a/Tools/Scripts/webkitpy/common/config/build.py b/Tools/Scripts/webkitpy/common/config/build.py index 42d0721..d25d606 100644 --- a/Tools/Scripts/webkitpy/common/config/build.py +++ b/Tools/Scripts/webkitpy/common/config/build.py @@ -97,10 +97,12 @@ def _should_file_trigger_build(target_platform, file): (r"(?:^|/)GNUmakefile\.am$", ["gtk"]), (r"/\w+Chromium\w*\.(?:cpp|h|mm)$", ["chromium"]), (r"Mac\.(?:cpp|h|mm)$", ["mac"]), + (r"\.(?:vcproj|vsprops|sln)$", ["win"]), (r"\.exp(?:\.in)?$", ["mac"]), (r"\.gypi?", ["chromium"]), (r"\.order$", ["mac"]), (r"\.pr[io]$", ["qt"]), + (r"\.vcproj/", ["win"]), (r"\.xcconfig$", ["mac"]), (r"\.xcodeproj/", ["mac"]), ] diff --git a/Tools/Scripts/webkitpy/common/config/build_unittest.py b/Tools/Scripts/webkitpy/common/config/build_unittest.py index 9144874..6bd71e8 100644 --- a/Tools/Scripts/webkitpy/common/config/build_unittest.py +++ b/Tools/Scripts/webkitpy/common/config/build_unittest.py @@ -32,6 +32,7 @@ class ShouldBuildTest(unittest.TestCase): (["Websites/bugs.webkit.org/foo", "Source/WebCore/bar"], ["*"]), (["Websites/bugs.webkit.org/foo"], []), (["Source/JavaScriptCore/JavaScriptCore.xcodeproj/foo"], ["mac-leopard", "mac-snowleopard"]), + (["Source/JavaScriptCore/JavaScriptCore.vcproj/foo", "Source/WebKit2/win/WebKit2.vcproj", "Source/WebKit/win/WebKit.sln", "Tools/WebKitTestRunner/Configurations/WebKitTestRunnerCommon.vsprops"], ["win"]), (["Source/JavaScriptGlue/foo", "Source/WebCore/bar"], ["*"]), (["Source/JavaScriptGlue/foo"], ["mac-leopard", "mac-snowleopard"]), (["LayoutTests/foo"], ["*"]), diff --git a/Tools/Scripts/webkitpy/common/config/committers.py b/Tools/Scripts/webkitpy/common/config/committers.py index fd9bdbb..50506c8 100644 --- a/Tools/Scripts/webkitpy/common/config/committers.py +++ b/Tools/Scripts/webkitpy/common/config/committers.py @@ -90,7 +90,7 @@ committers_unable_to_review = [ Committer("Brett Wilson", "brettw@chromium.org", "brettx"), Committer("Cameron McCormack", "cam@webkit.org", "heycam"), Committer("Carlos Garcia Campos", ["cgarcia@igalia.com", "carlosgc@gnome.org", "carlosgc@webkit.org"], "KaL"), - Committer("Carol Szabo", "carol.szabo@nokia.com"), + Committer("Carol Szabo", "carol@webkit.org", "cszabo1"), Committer("Chang Shu", ["cshu@webkit.org", "Chang.Shu@nokia.com"], "cshu"), Committer("Chris Evans", "cevans@google.com"), Committer("Chris Petersen", "cpetersen@apple.com", "cpetersen"), @@ -129,6 +129,7 @@ committers_unable_to_review = [ Committer("Jakob Petsovits", ["jpetsovits@rim.com", "jpetso@gmx.at"], "jpetso"), Committer("Jakub Wieczorek", "jwieczorek@webkit.org", "fawek"), Committer("James Hawkins", ["jhawkins@chromium.org", "jhawkins@google.com"], "jhawkins"), + Committer("James Kozianski", ["koz@chromium.org", "koz@google.com"], "koz"), Committer("James Simonsen", "simonjam@chromium.org", "simonjam"), Committer("Jay Civelli", "jcivelli@chromium.org", "jcivelli"), Committer("Jeff Miller", "jeffm@apple.com", "jeffm"), @@ -204,8 +205,9 @@ committers_unable_to_review = [ Committer("Victor Wang", "victorw@chromium.org", "victorw"), Committer("Vitaly Repeshko", "vitalyr@chromium.org"), Committer("William Siegrist", "wsiegrist@apple.com", "wms"), + Committer("W. James MacLean", "wjmaclean@chromium.org", "wjmaclean"), Committer("Xiaomei Ji", "xji@chromium.org", "xji"), - Committer("Yael Aharon", "yael.aharon@nokia.com"), + Committer("Yael Aharon", "yael.aharon@nokia.com", "yael"), Committer("Yaar Schnitman", ["yaar@chromium.org", "yaar@google.com"]), Committer("Yong Li", ["yong.li.webkit@gmail.com", "yong.li@torchmobile.com"], "yong"), Committer("Yongjun Zhang", "yongjun.zhang@nokia.com"), diff --git a/Tools/Scripts/webkitpy/common/config/ports.py b/Tools/Scripts/webkitpy/common/config/ports.py index 9a5a269..444a4ac 100644 --- a/Tools/Scripts/webkitpy/common/config/ports.py +++ b/Tools/Scripts/webkitpy/common/config/ports.py @@ -30,6 +30,7 @@ import os import platform +import sys from webkitpy.common.system.executive import Executive @@ -43,7 +44,13 @@ class WebKitPort(object): @classmethod def script_shell_command(cls, script_name): - return [cls.script_path(script_name)] + script_path = cls.script_path(script_name) + # Win32 does not support shebang. We need to detect the interpreter ourself. + if sys.platform == 'win32': + interpreter = Executive.interpreter_for_script(script_path) + if interpreter: + return [interpreter, script_path] + return [script_path] @staticmethod def port(port_name): @@ -83,6 +90,14 @@ class WebKitPort(object): return cls.script_shell_command("update-webkit") @classmethod + def check_webkit_style_command(cls): + return cls.script_shell_command("check-webkit-style") + + @classmethod + def prepare_changelog_command(cls): + return cls.script_shell_command("prepare-ChangeLog") + + @classmethod def build_webkit_command(cls, build_style=None): command = cls.script_shell_command("build-webkit") if build_style == "debug": diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py index 8daf92e..c781dfb 100644 --- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py +++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py @@ -46,7 +46,7 @@ from webkitpy.common.config import committers from webkitpy.common.net.credentials import Credentials from webkitpy.common.system.user import User from webkitpy.thirdparty.autoinstalled.mechanize import Browser -from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup, SoupStrainer +from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup, BeautifulStoneSoup, SoupStrainer # FIXME: parse_bug_id should not be a free function. @@ -74,7 +74,9 @@ def parse_bug_id_from_changelog(message): match = re.search("^\s*" + Bugzilla.bug_url_long + "$", message, re.MULTILINE) if match: return int(match.group('bug_id')) - return None + # We weren't able to find a bug URL in the format used by prepare-ChangeLog. Fall back to the + # first bug URL found anywhere in the message. + return parse_bug_id(message) def timestamp(): return datetime.now().strftime("%Y%m%d%H%M%S") @@ -218,7 +220,8 @@ class Bugzilla(object): # script. self.browser.set_handle_robots(False) - # FIXME: Much of this should go into some sort of config module: + # FIXME: Much of this should go into some sort of config module, + # such as common.config.urls. bug_server_host = "bugs.webkit.org" bug_server_regex = "https?://%s/" % re.sub('\.', '\\.', bug_server_host) bug_server_url = "https://%s/" % bug_server_host @@ -270,7 +273,7 @@ class Bugzilla(object): def _string_contents(self, soup): # WebKit's bugzilla instance uses UTF-8. - # BeautifulSoup always returns Unicode strings, however + # BeautifulStoneSoup always returns Unicode strings, however # the .string method returns a (unicode) NavigableString. # NavigableString can confuse other parts of the code, so we # convert from NavigableString to a real unicode() object using unicode(). @@ -317,7 +320,7 @@ class Bugzilla(object): return [Bug(self._parse_bug_dictionary_from_xml(unicode(bug_xml)), self) for bug_xml in soup('bug')] def _parse_bug_dictionary_from_xml(self, page): - soup = BeautifulSoup(page) + soup = BeautifulStoneSoup(page, convertEntities=BeautifulStoneSoup.XML_ENTITIES) bug = {} bug["id"] = int(soup.find("bug_id").string) bug["title"] = self._string_contents(soup.find("short_desc")) diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py index 2e75ca9..b996b7c 100644 --- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py +++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py @@ -104,7 +104,7 @@ class BugzillaTest(unittest.TestCase): <bug> <bug_id>32585</bug_id> <creation_ts>2009-12-15 15:17 PST</creation_ts> - <short_desc>bug to test webkit-patch and commit-queue failures</short_desc> + <short_desc>bug to test webkit-patch's and commit-queue's failures</short_desc> <delta_ts>2009-12-27 21:04:50 PST</delta_ts> <reporter_accessible>1</reporter_accessible> <cclist_accessible>1</cclist_accessible> @@ -173,7 +173,7 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg== _expected_example_bug_parsing = { "id" : 32585, - "title" : u"bug to test webkit-patch and commit-queue failures", + "title" : u"bug to test webkit-patch's and commit-queue's failures", "cc_emails" : ["foo@bar.com", "example@example.com"], "reporter_email" : "eric@webkit.org", "assigned_to_email" : "webkit-unassigned@lists.webkit.org", @@ -203,7 +203,7 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg== ''' - self.assertEquals(None, parse_bug_id_from_changelog(commit_text)) + self.assertEquals(56988, parse_bug_id_from_changelog(commit_text)) commit_text = ''' 2011-03-23 Ojan Vafai <ojan@chromium.org> @@ -218,6 +218,25 @@ ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg== self.assertEquals(12345, parse_bug_id_from_changelog(commit_text)) + commit_text = ''' +2011-03-31 Adam Roben <aroben@apple.com> + + Quote the executable path we pass to ::CreateProcessW + + This will ensure that spaces in the path will be interpreted correctly. + + Fixes <http://webkit.org/b/57569> Web process sometimes fails to launch when there are + spaces in its path + + Reviewed by Steve Falkenburg. + + * UIProcess/Launcher/win/ProcessLauncherWin.cpp: + (WebKit::ProcessLauncher::launchProcess): Surround the executable path in quotes. + + ''' + + self.assertEquals(57569, parse_bug_id_from_changelog(commit_text)) + # FIXME: This should move to a central location and be shared by more unit tests. def _assert_dictionaries_equal(self, actual, expected): diff --git a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py index d23a6cc..5fdf184 100644 --- a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py +++ b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py @@ -267,7 +267,7 @@ class Build(object): class BuildBot(object): - # FIXME: This should move into some sort of webkit_config.py + # FIXME: This should move into common.config.urls. default_host = "build.webkit.org" def __init__(self, host=default_host): diff --git a/Tools/Scripts/webkitpy/common/net/credentials.py b/Tools/Scripts/webkitpy/common/net/credentials.py index 30480b3..d76405b 100644 --- a/Tools/Scripts/webkitpy/common/net/credentials.py +++ b/Tools/Scripts/webkitpy/common/net/credentials.py @@ -29,7 +29,6 @@ # # Python module for reading stored web credentials from the OS. -import getpass import os import platform import re @@ -149,7 +148,7 @@ class Credentials(object): if not username: username = User.prompt("%s login: " % self.host) if not password: - password = getpass.getpass("%s password for %s: " % (self.host, username)) + password = User.prompt_password("%s password for %s: " % (self.host, username)) self._offer_to_store_credentials_in_keyring(username, password) return (username, password) diff --git a/Tools/Scripts/webkitpy/common/net/layouttestresults.py b/Tools/Scripts/webkitpy/common/net/layouttestresults.py index 249ecc9..a0e8ae4 100644 --- a/Tools/Scripts/webkitpy/common/net/layouttestresults.py +++ b/Tools/Scripts/webkitpy/common/net/layouttestresults.py @@ -134,6 +134,19 @@ class LayoutTestResults(object): def __init__(self, test_results): self._test_results = test_results + self._failure_limit_count = None + + # FIXME: run-webkit-tests should store the --exit-after-N-failures value + # (or some indication of early exit) somewhere in the results.html/results.json + # file. Until it does, callers should set the limit to + # --exit-after-N-failures value used in that run. Consumers of LayoutTestResults + # may use that value to know if absence from the failure list means PASS. + # https://bugs.webkit.org/show_bug.cgi?id=58481 + def set_failure_limit_count(self, limit): + self._failure_limit_count = limit + + def failure_limit_count(self): + return self._failure_limit_count def test_results(self): return self._test_results diff --git a/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py b/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py index 01b91b8..d25ad02 100644 --- a/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py +++ b/Tools/Scripts/webkitpy/common/net/layouttestresults_unittest.py @@ -61,6 +61,12 @@ class LayoutTestResultsTest(unittest.TestCase): </html> """ + def test_set_failure_limit_count(self): + results = LayoutTestResults([]) + self.assertEquals(results.failure_limit_count(), None) + results.set_failure_limit_count(10) + self.assertEquals(results.failure_limit_count(), 10) + def test_parse_layout_test_results(self): failures = [test_failures.FailureMissingResult(), test_failures.FailureMissingImageHash(), test_failures.FailureMissingImage()] testname = 'fast/repaint/no-caret-repaint-in-non-content-editable-element.html' diff --git a/Tools/Scripts/webkitpy/common/net/statusserver.py b/Tools/Scripts/webkitpy/common/net/statusserver.py index abd298a..9622c89 100644 --- a/Tools/Scripts/webkitpy/common/net/statusserver.py +++ b/Tools/Scripts/webkitpy/common/net/statusserver.py @@ -25,6 +25,8 @@ # 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. +# +# This the client designed to talk to Tools/QueueStatusServer. from webkitpy.common.net.networktransaction import NetworkTransaction from webkitpy.common.system.deprecated_logging import log @@ -39,6 +41,7 @@ _log = logging.getLogger("webkitpy.common.net.statusserver") class StatusServer: + # FIXME: This should probably move to common.config.urls. default_host = "queues.webkit.org" def __init__(self, host=default_host, browser=None, bot_id=None): diff --git a/Tools/Scripts/webkitpy/common/system/executive.py b/Tools/Scripts/webkitpy/common/system/executive.py index 02619db..7d198dd 100644 --- a/Tools/Scripts/webkitpy/common/system/executive.py +++ b/Tools/Scripts/webkitpy/common/system/executive.py @@ -45,6 +45,7 @@ import sys import time from webkitpy.common.system.deprecated_logging import tee +from webkitpy.common.system.filesystem import FileSystem from webkitpy.python24 import versioning @@ -179,6 +180,22 @@ class Executive(object): # machines. return 2 + @staticmethod + def interpreter_for_script(script_path, fs=FileSystem()): + lines = fs.read_text_file(script_path).splitlines() + if not len(lines): + return None + first_line = lines[0] + if not first_line.startswith('#!'): + return None + if first_line.find('python') > -1: + return sys.executable + if first_line.find('perl') > -1: + return 'perl' + if first_line.find('ruby') > -1: + return 'ruby' + return None + def kill_process(self, pid): """Attempts to kill the given pid. Will fail silently if pid does not exist or insufficient permisssions.""" diff --git a/Tools/Scripts/webkitpy/common/system/executive_unittest.py b/Tools/Scripts/webkitpy/common/system/executive_unittest.py index 1dadc36..9a14d6b 100644 --- a/Tools/Scripts/webkitpy/common/system/executive_unittest.py +++ b/Tools/Scripts/webkitpy/common/system/executive_unittest.py @@ -34,6 +34,7 @@ import sys import unittest from webkitpy.common.system.executive import Executive, run_command, ScriptError +from webkitpy.common.system.filesystem_mock import MockFileSystem from webkitpy.test import cat, echo @@ -65,6 +66,33 @@ def never_ending_command(): class ExecutiveTest(unittest.TestCase): + def assert_interpreter_for_content(self, intepreter, content): + fs = MockFileSystem() + file_path = None + file_interpreter = None + + tempfile, temp_name = fs.open_binary_tempfile('') + tempfile.write(content) + tempfile.close() + file_interpreter = Executive.interpreter_for_script(temp_name, fs) + + self.assertEqual(file_interpreter, intepreter) + + def test_interpreter_for_script(self): + self.assert_interpreter_for_content(None, '') + self.assert_interpreter_for_content(None, 'abcd\nefgh\nijklm') + self.assert_interpreter_for_content(None, '##/usr/bin/perl') + self.assert_interpreter_for_content('perl', '#!/usr/bin/env perl') + self.assert_interpreter_for_content('perl', '#!/usr/bin/env perl\nfirst\nsecond') + self.assert_interpreter_for_content('perl', '#!/usr/bin/perl') + self.assert_interpreter_for_content('perl', '#!/usr/bin/perl -w') + self.assert_interpreter_for_content(sys.executable, '#!/usr/bin/env python') + self.assert_interpreter_for_content(sys.executable, '#!/usr/bin/env python\nfirst\nsecond') + self.assert_interpreter_for_content(sys.executable, '#!/usr/bin/python') + self.assert_interpreter_for_content('ruby', '#!/usr/bin/env ruby') + self.assert_interpreter_for_content('ruby', '#!/usr/bin/env ruby\nfirst\nsecond') + self.assert_interpreter_for_content('ruby', '#!/usr/bin/ruby') + def test_run_command_with_bad_command(self): def run_bad_command(): run_command(["foo_bar_command_blah"], error_handler=Executive.ignore_error, return_exit_code=True) diff --git a/Tools/Scripts/webkitpy/common/system/filesystem.py b/Tools/Scripts/webkitpy/common/system/filesystem.py index 1988546..58be03a 100644 --- a/Tools/Scripts/webkitpy/common/system/filesystem.py +++ b/Tools/Scripts/webkitpy/common/system/filesystem.py @@ -61,6 +61,10 @@ class FileSystem(object): """Wraps os.path.basename().""" return os.path.basename(path) + def chdir(self, path): + """Wraps os.chdir().""" + return os.chdir(path) + def copyfile(self, source, destination): """Copies the contents of the file at the given path to the destination path.""" @@ -108,6 +112,10 @@ class FileSystem(object): files.append(self.join(dirpath, filename)) return files + def getcwd(self): + """Wraps os.getcwd().""" + return os.getcwd() + def glob(self, path): """Wraps glob.glob().""" return glob.glob(path) diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py index a6d158a..3be5854 100644 --- a/Tools/Scripts/webkitpy/common/system/filesystem_mock.py +++ b/Tools/Scripts/webkitpy/common/system/filesystem_mock.py @@ -35,7 +35,7 @@ from webkitpy.common.system import ospath class MockFileSystem(object): - def __init__(self, files=None): + def __init__(self, files=None, cwd='/'): """Initializes a "mock" filesystem that can be used to completely stub out a filesystem. @@ -48,6 +48,8 @@ class MockFileSystem(object): self.written_files = {} self._sep = '/' self.current_tmpno = 0 + self.cwd = cwd + self.dirs = {} def _get_sep(self): return self._sep @@ -61,13 +63,19 @@ class MockFileSystem(object): return path.rsplit(self.sep, 1) def abspath(self, path): - if path.endswith(self.sep): - return path[:-1] - return path + if os.path.isabs(path): + return self.normpath(path) + return self.abspath(self.join(self.cwd, path)) def basename(self, path): return self._split(path)[1] + 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) @@ -117,6 +125,9 @@ class MockFileSystem(object): return files + def getcwd(self, path): + return self.cwd + def glob(self, path): # FIXME: This only handles a wildcard '*' at the end of the path. # Maybe it should handle more? @@ -134,14 +145,18 @@ class MockFileSystem(object): def isdir(self, path): if path in self.files: return False - if not path.endswith(self.sep): - path += self.sep + path = self.normpath(path) + if path in self.dirs: + return True # We need to use a copy of the keys here in order to avoid switching # to a different thread and potentially modifying the dict in # mid-iteration. files = self.files.keys()[:] - return any(f.startswith(path) for f in files) + result = any(f.startswith(path) for f in files) + if result: + self.dirs[path] = True + return result def join(self, *comps): # FIXME: might want tests for this and/or a better comment about how @@ -204,8 +219,9 @@ class MockFileSystem(object): return TemporaryDirectory(fs=self, **kwargs) def maybe_make_directory(self, *path): - # FIXME: Implement such that subsequent calls to isdir() work? - pass + norm_path = self.normpath(self.join(*path)) + if not self.isdir(norm_path): + self.dirs[norm_path] = True def move(self, source, destination): if self.files[source] is None: @@ -216,7 +232,9 @@ class MockFileSystem(object): self.written_files[source] = None def normpath(self, path): - return path + # Like join(), relies on os.path functionality but normalizes the + # path separator to the mock one. + return re.sub(re.escape(os.path.sep), self.sep, os.path.normpath(path)) def open_binary_tempfile(self, suffix=''): path = self._mktemp(suffix) diff --git a/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py b/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py index 8455d72..8d4f0cb 100644 --- a/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py +++ b/Tools/Scripts/webkitpy/common/system/filesystem_unittest.py @@ -48,6 +48,23 @@ class FileSystemTest(unittest.TestCase): self._missing_file = os.path.join(self._this_dir, 'missing_file.py') self._this_file = os.path.join(self._this_dir, 'filesystem_unittest.py') + def test_chdir(self): + fs = FileSystem() + cwd = fs.getcwd() + newdir = '/' + if sys.platform == 'win32': + newdir = 'c:\\' + fs.chdir(newdir) + self.assertEquals(fs.getcwd(), newdir) + fs.chdir(cwd) + + def test_chdir__notexists(self): + fs = FileSystem() + newdir = '/dirdoesnotexist' + if sys.platform == 'win32': + newdir = 'c:\\dirdoesnotexist' + self.assertRaises(OSError, fs.chdir, newdir) + def test_exists__true(self): fs = FileSystem() self.assertTrue(fs.exists(self._this_file)) @@ -56,6 +73,10 @@ class FileSystemTest(unittest.TestCase): fs = FileSystem() self.assertFalse(fs.exists(self._missing_file)) + def test_getcwd(self): + fs = FileSystem() + self.assertTrue(fs.exists(fs.getcwd())) + def test_isdir__true(self): fs = FileSystem() self.assertTrue(fs.isdir(self._this_dir)) diff --git a/Tools/Scripts/webkitpy/common/system/user.py b/Tools/Scripts/webkitpy/common/system/user.py index b79536c..aecb6ec 100644 --- a/Tools/Scripts/webkitpy/common/system/user.py +++ b/Tools/Scripts/webkitpy/common/system/user.py @@ -26,6 +26,7 @@ # (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 getpass import logging import os import re @@ -65,6 +66,10 @@ class User(object): return response @classmethod + def prompt_password(cls, message, repeat=1): + return cls.prompt(message, repeat=repeat, raw_input=getpass.getpass) + + @classmethod def prompt_with_list(cls, list_title, list_items, can_choose_multiple=False, raw_input=raw_input): print list_title i = 0 |