summaryrefslogtreecommitdiff
path: root/Tools/Scripts/webkitpy/common
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
commitcd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch)
tree8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Tools/Scripts/webkitpy/common
parentd11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff)
downloadqtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Tools/Scripts/webkitpy/common')
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/checkout.py19
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/checkout_mock.py2
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py15
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/git.py5
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/scm.py1
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py10
-rw-r--r--Tools/Scripts/webkitpy/common/checkout/scm/svn.py6
-rw-r--r--Tools/Scripts/webkitpy/common/config/build.py1
-rw-r--r--Tools/Scripts/webkitpy/common/config/build_unittest.py3
-rw-r--r--Tools/Scripts/webkitpy/common/config/committers.py23
-rw-r--r--Tools/Scripts/webkitpy/common/config/committers_unittest.py7
-rw-r--r--Tools/Scripts/webkitpy/common/config/ports.py33
-rw-r--r--Tools/Scripts/webkitpy/common/config/ports_mock.py4
-rw-r--r--Tools/Scripts/webkitpy/common/config/ports_unittest.py6
-rwxr-xr-xTools/Scripts/webkitpy/common/config/watchlist24
-rw-r--r--Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py70
-rw-r--r--Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py93
-rw-r--r--Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py4
-rw-r--r--Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py183
-rw-r--r--Tools/Scripts/webkitpy/common/net/file_uploader.py34
-rw-r--r--Tools/Scripts/webkitpy/common/system/executive.py23
-rw-r--r--Tools/Scripts/webkitpy/common/system/executive_mock.py8
-rw-r--r--Tools/Scripts/webkitpy/common/system/executive_unittest.py42
-rw-r--r--Tools/Scripts/webkitpy/common/system/fileutils.py33
-rw-r--r--Tools/Scripts/webkitpy/common/system/platforminfo_mock.py8
-rw-r--r--Tools/Scripts/webkitpy/common/system/systemhost_mock.py6
26 files changed, 389 insertions, 274 deletions
diff --git a/Tools/Scripts/webkitpy/common/checkout/checkout.py b/Tools/Scripts/webkitpy/common/checkout/checkout.py
index 08abe6cd8..8f450249c 100644
--- a/Tools/Scripts/webkitpy/common/checkout/checkout.py
+++ b/Tools/Scripts/webkitpy/common/checkout/checkout.py
@@ -1,9 +1,9 @@
# 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
@@ -13,7 +13,7 @@
# * 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
@@ -121,13 +121,13 @@ class Checkout(object):
def modified_non_changelogs(self, git_commit, changed_files=None):
return self._modified_files_matching_predicate(git_commit, lambda path: not self.is_path_to_changelog(path), changed_files=changed_files)
- def commit_message_for_this_commit(self, git_commit, changed_files=None):
+ def commit_message_for_this_commit(self, git_commit, changed_files=None, return_stderr=False):
changelog_paths = self.modified_changelogs(git_commit, changed_files)
if not len(changelog_paths):
raise ScriptError(message="Found no modified ChangeLogs, cannot create a commit message.\n"
"All changes require a ChangeLog. See:\n %s" % urls.contribution_guidelines)
- message_text = self._scm.run([self._scm.script_path('commit-log-editor'), '--print-log'] + changelog_paths, return_stderr=False)
+ message_text = self._scm.run([self._scm.script_path('commit-log-editor'), '--print-log'] + changelog_paths, return_stderr=return_stderr)
return CommitMessage(message_text.splitlines())
def recent_commit_infos_for_files(self, paths):
@@ -150,16 +150,15 @@ class Checkout(object):
def chromium_deps(self):
return DEPS(self._scm.absolute_path(self._filesystem.join("Source", "WebKit", "chromium", "DEPS")))
- def apply_patch(self, patch, force=False):
+ def apply_patch(self, patch):
# It's possible that the patch was not made from the root directory.
# We should detect and handle that case.
# FIXME: Move _scm.script_path here once we get rid of all the dependencies.
- args = [self._scm.script_path('svn-apply')]
+ # --force (continue after errors) is the common case, so we always use it.
+ args = [self._scm.script_path('svn-apply'), "--force"]
if patch.reviewer():
args += ['--reviewer', patch.reviewer().full_name]
- if force:
- args.append('--force')
- self._executive.run_command(args, input=patch.contents())
+ self._executive.run_command(args, input=patch.contents(), cwd=self._scm.checkout_root)
def apply_reverse_diff(self, revision):
self._scm.apply_reverse_diff(revision)
diff --git a/Tools/Scripts/webkitpy/common/checkout/checkout_mock.py b/Tools/Scripts/webkitpy/common/checkout/checkout_mock.py
index 039db1f6a..25b05c33a 100644
--- a/Tools/Scripts/webkitpy/common/checkout/checkout_mock.py
+++ b/Tools/Scripts/webkitpy/common/checkout/checkout_mock.py
@@ -84,7 +84,7 @@ class MockCheckout(object):
def chromium_deps(self):
return MockDEPS()
- def apply_patch(self, patch, force=False):
+ def apply_patch(self, patch):
pass
def apply_reverse_diffs(self, revision):
diff --git a/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py b/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py
index 962364b6c..3b0943247 100644
--- a/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/checkout_unittest.py
@@ -42,6 +42,7 @@ from webkitpy.common.system.executive import Executive, ScriptError
from webkitpy.common.system.filesystem import FileSystem # FIXME: This should not be needed.
from webkitpy.common.system.filesystem_mock import MockFileSystem
from webkitpy.common.system.executive_mock import MockExecutive
+from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.thirdparty.mock import Mock
@@ -139,7 +140,9 @@ Second part of this complicated change by me, Tor Arne Vestb\u00f8!
checkout = Checkout(mock_scm)
checkout.modified_changelogs = lambda git_commit, changed_files=None: self.changelogs
- commit_message = checkout.commit_message_for_this_commit(git_commit=None)
+ commit_message = checkout.commit_message_for_this_commit(git_commit=None, return_stderr=True)
+ # Throw away the first line - a warning about unknown VCS root.
+ commit_message.message_lines = commit_message.message_lines[1:]
self.assertEqual(commit_message.message(), self.expected_commit_message)
@@ -250,3 +253,13 @@ class CheckoutTest(unittest.TestCase):
checkout = self._make_checkout()
checkout._scm.checkout_root = "/foo/bar"
self.assertEqual(checkout.chromium_deps()._path, '/foo/bar/Source/WebKit/chromium/DEPS')
+
+ def test_apply_patch(self):
+ checkout = self._make_checkout()
+ checkout._executive = MockExecutive(should_log=True)
+ checkout._scm.script_path = lambda script: script
+ mock_patch = Mock()
+ mock_patch.contents = lambda: "foo"
+ mock_patch.reviewer = lambda: None
+ expected_stderr = "MOCK run_command: ['svn-apply', '--force'], cwd=/mock-checkout\n"
+ OutputCapture().assert_outputs(self, checkout.apply_patch, [mock_patch], expected_stderr=expected_stderr)
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/Tools/Scripts/webkitpy/common/checkout/scm/git.py
index 7c23be056..866b24cc4 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/git.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/git.py
@@ -434,16 +434,11 @@ class Git(SCM, SVNRepository):
def push_local_commits_to_server(self, username=None, password=None):
dcommit_command = ['git', 'svn', 'dcommit']
- if self.dryrun:
- dcommit_command.append('--dry-run')
if (not username or not password) and 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, cwd=self.checkout_root)
- # Return a string which looks like a commit so that things which parse this output will succeed.
- if self.dryrun:
- output += "\nCommitted r0"
return output
# This function supports the following argument formats:
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/scm.py b/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
index b00470bbb..4b581b17f 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
@@ -61,7 +61,6 @@ class SCM:
def __init__(self, cwd, executive=None, filesystem=None):
self.cwd = cwd
self.checkout_root = self.find_checkout_root(self.cwd)
- self.dryrun = False
self._executive = executive or Executive()
self._filesystem = filesystem or FileSystem()
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py b/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
index ae5ac845c..209bd3510 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/scm_unittest.py
@@ -757,11 +757,6 @@ Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
commit_text = self.scm.commit_with_message("another test commit", username)
self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6')
- self.scm.dryrun = True
- write_into_file_at_path('test_file', 'still more test content')
- 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")
@@ -1216,11 +1211,6 @@ class GitSVNTest(SCMTest):
commit_text = self.scm.commit_with_message("another test commit")
self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '6')
- self.scm.dryrun = True
- write_into_file_at_path('test_file', 'still more test content')
- commit_text = self.scm.commit_with_message("yet another test commit")
- self.assertEqual(self.scm.svn_revision_from_commit_text(commit_text), '0')
-
def test_commit_with_message_working_copy_only(self):
write_into_file_at_path('test_file_commit1', 'more test content')
run_command(['git', 'add', 'test_file_commit1'])
diff --git a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py b/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
index cd4e1ea60..3f583a7d3 100644
--- a/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
+++ b/Tools/Scripts/webkitpy/common/checkout/scm/svn.py
@@ -333,12 +333,6 @@ class SVN(SCM, SVNRepository):
if changed_files:
svn_commit_args.extend(changed_files)
- if self.dryrun:
- _log.debug('Would run SVN command: "' + " ".join(svn_commit_args) + '"')
-
- # 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."
-
return self._run_svn(svn_commit_args, cwd=self.checkout_root, error_handler=commit_error_handler)
def svn_commit_log(self, svn_revision):
diff --git a/Tools/Scripts/webkitpy/common/config/build.py b/Tools/Scripts/webkitpy/common/config/build.py
index ac9a1360d..fcb5e62c3 100644
--- a/Tools/Scripts/webkitpy/common/config/build.py
+++ b/Tools/Scripts/webkitpy/common/config/build.py
@@ -55,7 +55,6 @@ def _should_file_trigger_build(target_platform, file):
("wx", []),
# Directories that should trigger builds on only some bots.
- ("Source/JavaScriptGlue", ["mac"]),
("Source/WebCore/image-decoders", ["chromium"]),
("LayoutTests/platform/mac", ["mac", "win"]),
("cairo", ["gtk", "wincairo"]),
diff --git a/Tools/Scripts/webkitpy/common/config/build_unittest.py b/Tools/Scripts/webkitpy/common/config/build_unittest.py
index 7e76befe6..bdc340489 100644
--- a/Tools/Scripts/webkitpy/common/config/build_unittest.py
+++ b/Tools/Scripts/webkitpy/common/config/build_unittest.py
@@ -33,8 +33,7 @@ class ShouldBuildTest(unittest.TestCase):
(["Websites/bugs.webkit.org/foo"], []),
(["Source/JavaScriptCore/JavaScriptCore.xcodeproj/foo"], ["mac-leopard", "mac-lion", "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-lion", "mac-snowleopard"]),
+ (["LayoutTests/platform/mac/foo", "Source/WebCore/bar"], ["*"]),
(["LayoutTests/foo"], ["*"]),
(["LayoutTests/canvas/philip/tests/size.attributes.parse.exp-expected.txt", "LayoutTests/canvas/philip/tests/size.attributes.parse.exp.html"], ["*"]),
(["LayoutTests/platform/chromium-linux/foo"], ["chromium-linux"]),
diff --git a/Tools/Scripts/webkitpy/common/config/committers.py b/Tools/Scripts/webkitpy/common/config/committers.py
index eb9afc332..6e7399ecb 100644
--- a/Tools/Scripts/webkitpy/common/config/committers.py
+++ b/Tools/Scripts/webkitpy/common/config/committers.py
@@ -1,5 +1,5 @@
# Copyright (c) 2011, Apple Inc. All rights reserved.
-# Copyright (c) 2009, 2011 Google Inc. All rights reserved.
+# Copyright (c) 2009, 2011, 2012 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
@@ -105,6 +105,7 @@ watchers_who_are_not_contributors = [
contributors_who_are_not_committers = [
+ Contributor("Adam Kallai", "kallai.adam@stud.u-szeged.hu", 'kadam'),
Contributor("Aharon Lanin", "aharon@google.com"),
Contributor("Alan Stearns", "stearns@adobe.com", 'astearns'),
Contributor("Alexandre Elias", "aelias@chromium.org"),
@@ -113,8 +114,8 @@ contributors_who_are_not_committers = [
Contributor("Andras Piroska", "pandras@inf.u-szeged.hu", "andris88"),
Contributor("Anne van Kesteren", "annevankesteren+webkit@gmail.com", "annevk"),
Contributor("Annie Sullivan", "sullivan@chromium.org", "annie"),
- Contributor("Antoine Labour", "piman@chromium.org", "piman"),
Contributor("Aryeh Gregor", "ayg@aryeh.name", "AryehGregor"),
+ Contributor("Balazs Ankes", "ankes.balazs@stud.u-szeged.hu", 'abalazs'),
Contributor("Commit Queue", "commit-queue@webkit.org"),
Contributor("Dana Jansens", "danakj@chromium.org", "danakj"),
Contributor("Daniel Sievers", "sievers@chromium.org"),
@@ -130,16 +131,18 @@ contributors_who_are_not_committers = [
Contributor("Greg Simon", "gregsimon@chromium.org", "gregsimon"),
Contributor("Gregg Tavares", ["gman@google.com", "gman@chromium.org"], "gman"),
Contributor("Ian Hickson", "ian@hixie.ch", "hixie"),
+ Contributor("Janos Badics", "dicska@gmail.hu", 'dicska'),
Contributor("John Bates", ["jbates@google.com", "jbates@chromium.org"], "jbates"),
Contributor("John Bauman", ["jbauman@chromium.org", "jbauman@google.com"], "jbauman"),
Contributor("Kaustubh Atrawalkar", ["kaustubh@motorola.com"], "silverroots"),
- Contributor("Kristof Kosztyo", "kkristof@inf.u-szeged.hu", "kkristof"),
Contributor("Kulanthaivel Palanichamy", "kulanthaivel@codeaurora.org", "kvel"),
+ Contributor("Nandor Huszka", "huszka.nandor@stud.u-szeged.hu", "hnandor"),
Contributor("Oliver Varga", ["voliver@inf.u-szeged.hu", "Varga.Oliver@stud.u-szeged.hu"], "TwistO"),
Contributor("Peter Gal", "galpeter@inf.u-szeged.hu", "elecro"),
Contributor("Peter Linss", "peter.linss@hp.com", "plinss"),
Contributor("Radar WebKit Bug Importer", "webkit-bug-importer@group.apple.com"),
- Contributor("Shawn Singh", "shawnsingh@chromium.org", "shawnsingh"),
+ Contributor("Roland Takacs", "takacs.roland@stud.u-szeged.hu", "rtakacs"),
+ Contributor("Szilard Ledan-Muntean", "muntean-ledan.szilard@stud.u-szeged.hu", "szledan"),
Contributor("Tab Atkins", ["tabatkins@google.com", "jackalmage@gmail.com"], "tabatkins"),
Contributor("Tamas Czene", ["tczene@inf.u-szeged.hu", "Czene.Tamas@stud.u-szeged.hu"], "tczene"),
Contributor("WebKit Review Bot", "webkit.review.bot@gmail.com", "sheriff-bot"),
@@ -178,6 +181,7 @@ committers_unable_to_review = [
Committer("Andras Becsi", ["abecsi@webkit.org", "andras.becsi@nokia.com"], "bbandix"),
Committer("Anna Cavender", "annacc@chromium.org", "annacc"),
Committer("Anthony Ricaud", "rik@webkit.org", "rik"),
+ Committer("Antoine Labour", "piman@chromium.org", "piman"),
Committer("Anton D'Auria", "adauria@apple.com", "antonlefou"),
Committer("Anton Muhin", "antonm@chromium.org", "antonm"),
Committer("Balazs Kelemen", "kbalazs@webkit.org", "kbalazs"),
@@ -199,6 +203,7 @@ committers_unable_to_review = [
Committer("Christian Dywan", ["christian@twotoasts.de", "christian@webkit.org", "christian@lanedo.com"]),
Committer("Collin Jackson", "collinj@webkit.org", "collinjackson"),
Committer("Cris Neckar", "cdn@chromium.org", "cneckar"),
+ Committer("Dan Winship", "danw@gnome.org", "danw"),
Committer("Daniel Cheng", "dcheng@chromium.org", "dcheng"),
Committer("David Grogan", ["dgrogan@chromium.org", "dgrogan@google.com"], "dgrogan"),
Committer("David Smith", ["catfish.man@gmail.com", "dsmith@webkit.org"], "catfishman"),
@@ -257,6 +262,7 @@ committers_unable_to_review = [
Committer("Jon Lee", "jonlee@apple.com", "jonlee"),
Committer("Joone Hur", ["joone.hur@collabora.co.uk", "joone@kldp.org", "joone@webkit.org"], "joone"),
Committer("Joost de Valk", ["joost@webkit.org", "webkit-dev@joostdevalk.nl"], "Altha"),
+ Committer("Joshua Bell", ["jsbell@chromium.org", "jsbell@google.com"], "jsbell"),
Committer("Julie Parent", ["jparent@google.com", "jparent@chromium.org"], "jparent"),
Committer("Jungshik Shin", "jshin@chromium.org"),
Committer("Justin Schuh", "jschuh@chromium.org", "jschuh"),
@@ -265,10 +271,10 @@ committers_unable_to_review = [
Committer("Kenichi Ishibashi", "bashi@chromium.org", "bashi"),
Committer("Kenji Imasaki", "imasaki@chromium.org", "imasaki"),
Committer("Kent Hansen", "kent.hansen@nokia.com", "khansen"),
- Committer("Kentaro Hara", ["haraken@chromium.org"], "haraken"),
Committer(u"Kim Gr\u00f6nholm", "kim.1.gronholm@nokia.com"),
Committer("Kimmo Kinnunen", ["kimmo.t.kinnunen@nokia.com", "kimmok@iki.fi", "ktkinnun@webkit.org"], "kimmok"),
Committer("Kinuko Yasuda", "kinuko@chromium.org", "kinuko"),
+ Committer("Kristof Kosztyo", "kkristof@inf.u-szeged.hu", "kkristof"),
Committer("Krzysztof Kowalczyk", "kkowalczyk@gmail.com"),
Committer("Kwang Yul Seo", ["kwangyul.seo@gmail.com", "skyul@company100.net", "kseo@webkit.org"], "kwangseo"),
Committer("Leandro Gracia Gil", "leandrogracia@chromium.org", "leandrogracia"),
@@ -298,6 +304,7 @@ committers_unable_to_review = [
Committer("Mike Reed", "reed@google.com", "reed"),
Committer("Mike Thole", ["mthole@mikethole.com", "mthole@apple.com"]),
Committer("Mikhail Naganov", "mnaganov@chromium.org"),
+ Committer("Naoki Takano", ["honten@chromium.org", "takano.naoki@gmail.com"], "honten"),
Committer("Nat Duca", ["nduca@chromium.org", "nduca@google.com"], "nduca"),
Committer("Nayan Kumar K", ["nayankk@motorola.com", "nayankk@gmail.com"], "xc0ffee"),
Committer("Nico Weber", ["thakis@chromium.org", "thakis@google.com"], "thakis"),
@@ -323,8 +330,10 @@ committers_unable_to_review = [
Committer("Satish Sampath", "satish@chromium.org"),
Committer("Scott Violet", "sky@chromium.org", "sky"),
Committer("Sergio Villar Senin", ["svillar@igalia.com", "sergio@webkit.org"], "svillar"),
+ Committer("Shawn Singh", "shawnsingh@chromium.org", "shawnsingh"),
Committer("Siddharth Mathur", "siddharth.mathur@nokia.com", "simathur"),
Committer("Steve Lacey", "sjl@chromium.org", "stevela"),
+ Committer("Takashi Toyoshima", "toyoshim@chromium.org", "toyoshim"),
Committer("Tim Horton", "timothy_horton@apple.com", "thorton"),
Committer("Tom Zakrajsek", "tomz@codeaurora.org", "tomz"),
Committer("Tommy Widenflycht", "tommyw@google.com", "tommyw"),
@@ -336,7 +345,6 @@ committers_unable_to_review = [
Committer("Victoria Kirst", ["vrk@chromium.org", "vrk@google.com"], "vrk"),
Committer("Vincent Scheib", "scheib@chromium.org", "scheib"),
Committer("Vitaly Repeshko", "vitalyr@chromium.org"),
- Committer("Vsevolod Vlasov", "vsevik@chromium.org"),
Committer("William Siegrist", "wsiegrist@apple.com", "wms"),
Committer("W. James MacLean", "wjmaclean@chromium.org", "wjmaclean"),
Committer("Xianzhu Wang", ["wangxianzhu@chromium.org", "phnixwxz@gmail.com", "wangxianzhu@google.com"], "wangxianzhu"),
@@ -352,7 +360,6 @@ committers_unable_to_review = [
Committer("Zeno Albisser", ["zeno@webkit.org", "zeno.albisser@nokia.com"], "zalbisser"),
Committer("Zhenyao Mo", "zmo@google.com", "zhenyao"),
Committer("Zoltan Horvath", ["zoltan@webkit.org", "hzoltan@inf.u-szeged.hu", "horvath.zoltan.6@stud.u-szeged.hu"], "zoltan"),
- Committer("Naoki Takano", ["honten@chromium.org", "takano.naoki@gmail.com"], "honten"),
]
@@ -427,6 +434,7 @@ reviewers_list = [
Reviewer("Kenneth Rohde Christiansen", ["kenneth@webkit.org", "kenneth.christiansen@openbossa.org", "kenneth.christiansen@gmail.com"], ["kenne", "kenneth"]),
Reviewer("Kenneth Russell", "kbr@google.com", "kbr_google"),
Reviewer("Kent Tamura", ["tkent@chromium.org", "tkent@google.com"], "tkent"),
+ Reviewer("Kentaro Hara", ["haraken@chromium.org"], "haraken"),
Reviewer("Kevin Decker", "kdecker@apple.com", "superkevin"),
Reviewer("Kevin McCullough", "kmccullough@apple.com", "maculloch"),
Reviewer("Kevin Ollivier", ["kevino@theolliviers.com", "kevino@webkit.org"], "kollivier"),
@@ -461,6 +469,7 @@ reviewers_list = [
Reviewer("Tony Gentilcore", "tonyg@chromium.org", "tonyg-cr"),
Reviewer(u"Tor Arne Vestb\u00f8", ["vestbo@webkit.org", "tor.arne.vestbo@nokia.com"], "torarne"),
Reviewer("Vicki Murley", "vicki@apple.com"),
+ Reviewer("Vsevolod Vlasov", "vsevik@chromium.org", "vsevik"),
Reviewer("Xan Lopez", ["xan.lopez@gmail.com", "xan@gnome.org", "xan@webkit.org", "xlopez@igalia.com"], "xan"),
Reviewer("Yury Semikhatsky", "yurys@chromium.org", "yurys"),
Reviewer("Zack Rusin", "zack@kde.org", "zackr"),
diff --git a/Tools/Scripts/webkitpy/common/config/committers_unittest.py b/Tools/Scripts/webkitpy/common/config/committers_unittest.py
index d3b10b82a..53d9c4d14 100644
--- a/Tools/Scripts/webkitpy/common/config/committers_unittest.py
+++ b/Tools/Scripts/webkitpy/common/config/committers_unittest.py
@@ -104,7 +104,10 @@ class CommittersTest(unittest.TestCase):
def _assert_fuzz_match(self, text, name_of_expected_contributor, expected_distance):
committers = CommitterList()
contributors, distance = committers.contributors_by_fuzzy_match(text)
- expected_names = [name_of_expected_contributor] if name_of_expected_contributor else []
+ if type(name_of_expected_contributor) is list:
+ expected_names = name_of_expected_contributor
+ else:
+ expected_names = [name_of_expected_contributor] if name_of_expected_contributor else []
self.assertEqual(([contributor.full_name for contributor in contributors], distance), (expected_names, expected_distance))
def test_contributors_by_fuzzy_match(self):
@@ -167,7 +170,7 @@ class CommittersTest(unittest.TestCase):
# self._assert_fuzz_match('Chris', 'Chris Blumenberg', 0)
self._assert_fuzz_match('cblu', 'Chris Blumenberg', 0)
- self._assert_fuzz_match('Dan', 'Dan Bernstein', 0)
+ self._assert_fuzz_match('Dan', ['Dan Winship', 'Dan Bernstein'], 0)
self._assert_fuzz_match('Dan B', 'Dan Bernstein', 0)
# self._assert_fuzz_match('mitz', 'Dan Bernstein', 0)
self._assert_fuzz_match('Mitz Pettel', 'Dan Bernstein', 1)
diff --git a/Tools/Scripts/webkitpy/common/config/ports.py b/Tools/Scripts/webkitpy/common/config/ports.py
index 3e100b059..02c1f5b55 100644
--- a/Tools/Scripts/webkitpy/common/config/ports.py
+++ b/Tools/Scripts/webkitpy/common/config/ports.py
@@ -36,6 +36,8 @@ from webkitpy.common.system.executive import Executive
class WebKitPort(object):
+ results_directory = "/tmp/layout-test-results"
+
# We might need to pass scm into this function for scm.checkout_root
@classmethod
def script_path(cls, script_name):
@@ -122,7 +124,7 @@ class WebKitPort(object):
@classmethod
def layout_tests_results_path(cls):
- return "/tmp/layout-test-results/results.html"
+ return os.path.join(cls.results_directory, "full_results.json")
class MacPort(WebKitPort):
@@ -172,6 +174,7 @@ class GtkPort(WebKitPort):
def build_webkit_command(cls, build_style=None):
command = WebKitPort.build_webkit_command(build_style=build_style)
command.append("--gtk")
+ command.append("--update-gtk")
command.append(WebKitPort.makeArgs())
return command
@@ -244,10 +247,6 @@ class ChromiumPort(WebKitPort):
return command
@classmethod
- def run_webkit_unit_tests_command(cls):
- return cls.script_shell_command("run-chromium-webkit-unit-tests")
-
- @classmethod
def run_webkit_tests_command(cls):
command = cls.script_shell_command("new-run-webkit-tests")
command.append("--chromium")
@@ -259,34 +258,12 @@ class ChromiumPort(WebKitPort):
return None
-# FIXME: This port is a bit of a hack to get our infrastructure running on EC2.
class ChromiumXVFBPort(ChromiumPort):
- results_directory = "/tmp/layout-test-results"
-
@classmethod
def flag(cls):
return "--port=chromium-xvfb"
@classmethod
def run_webkit_tests_command(cls):
- # FIXME: We should find a better way to do this. Some of these options
- # are specific to new-run-webkit-tests and some of them are due to
- # running in non-interactive mode.
- return ["xvfb-run"] + ChromiumPort.run_webkit_tests_command() + [
- "--results-directory=%s" % cls.results_directory,
- "--skip-failing-tests",
- "--print=actual,config,expected,misc,slowest,unexpected,unexpected-results",
- ]
-
- @classmethod
- def run_python_unittests_command(cls):
- return None
-
- @classmethod
- def run_perl_unittests_command(cls):
- return None
-
- @classmethod
- def layout_tests_results_path(cls):
- return os.path.join(cls.results_directory, "full_results.json")
+ return ["xvfb-run"] + ChromiumPort.run_webkit_tests_command()
diff --git a/Tools/Scripts/webkitpy/common/config/ports_mock.py b/Tools/Scripts/webkitpy/common/config/ports_mock.py
index 77f51532e..d63efd2c6 100644
--- a/Tools/Scripts/webkitpy/common/config/ports_mock.py
+++ b/Tools/Scripts/webkitpy/common/config/ports_mock.py
@@ -28,11 +28,13 @@
class MockPort(object):
+ results_directory = "/mock-results"
+
def name(self):
return "MockPort"
def layout_tests_results_path(self):
- return "/mock-results/results.html"
+ return "/mock-results/full_results.json"
def check_webkit_style_command(self):
return ["mock-check-webkit-style"]
diff --git a/Tools/Scripts/webkitpy/common/config/ports_unittest.py b/Tools/Scripts/webkitpy/common/config/ports_unittest.py
index e413c26ec..0532512aa 100644
--- a/Tools/Scripts/webkitpy/common/config/ports_unittest.py
+++ b/Tools/Scripts/webkitpy/common/config/ports_unittest.py
@@ -51,8 +51,8 @@ class WebKitPortTest(unittest.TestCase):
self.assertEquals(GtkPort.name(), "Gtk")
self.assertEquals(GtkPort.flag(), "--port=gtk")
self.assertEquals(GtkPort.run_webkit_tests_command(), WebKitPort.script_shell_command("run-webkit-tests") + ["--gtk"])
- self.assertEquals(GtkPort.build_webkit_command(), WebKitPort.script_shell_command("build-webkit") + ["--gtk", WebKitPort.makeArgs()])
- self.assertEquals(GtkPort.build_webkit_command(build_style="debug"), WebKitPort.script_shell_command("build-webkit") + ["--debug", "--gtk", WebKitPort.makeArgs()])
+ self.assertEquals(GtkPort.build_webkit_command(), WebKitPort.script_shell_command("build-webkit") + ["--gtk", "--update-gtk", WebKitPort.makeArgs()])
+ self.assertEquals(GtkPort.build_webkit_command(build_style="debug"), WebKitPort.script_shell_command("build-webkit") + ["--debug", "--gtk", "--update-gtk", WebKitPort.makeArgs()])
def test_qt_port(self):
self.assertEquals(QtPort.name(), "Qt")
@@ -70,7 +70,7 @@ class WebKitPortTest(unittest.TestCase):
self.assertEquals(ChromiumPort.update_webkit_command(), WebKitPort.script_shell_command("update-webkit") + ["--chromium"])
def test_chromium_xvfb_port(self):
- self.assertEquals(ChromiumXVFBPort.run_webkit_tests_command(), ['xvfb-run'] + WebKitPort.script_shell_command('new-run-webkit-tests') + ['--chromium', '--skip-failing-tests', '--results-directory=/tmp/layout-test-results', '--skip-failing-tests', '--print=actual,config,expected,misc,slowest,unexpected,unexpected-results'])
+ self.assertEquals(ChromiumXVFBPort.run_webkit_tests_command(), ['xvfb-run'] + WebKitPort.script_shell_command('new-run-webkit-tests') + ['--chromium', '--skip-failing-tests'])
if __name__ == '__main__':
unittest.main()
diff --git a/Tools/Scripts/webkitpy/common/config/watchlist b/Tools/Scripts/webkitpy/common/config/watchlist
index 0354fda01..bf92f05da 100755
--- a/Tools/Scripts/webkitpy/common/config/watchlist
+++ b/Tools/Scripts/webkitpy/common/config/watchlist
@@ -21,6 +21,9 @@
"ChromiumPublicApi": {
"filename": r"Source/WebKit/chromium/public/"
},
+ "AppleMacPublicApi": {
+ "filename": r"Source/WebCore/bindings/objc/PublicDOMInterfaces.h"
+ },
"Forms": {
"filename": r"Source/WebCore/html/HTML(FieldSet|Form|FormControl|Input|Label"
r"|OptGroup|Option|Select|TextArea|TextFormControl)Element\."
@@ -81,6 +84,13 @@
"GtkWebKit2PublicAPI": {
"filename": r"Source/WebKit2/UIProcess/API/gtk/",
},
+ "QtBuildSystem": {
+ # Project files for each target are intentionally left out, as those
+ # mostly list source and header files, which would just add noise.
+ "filename": r"Tools/qmake/"
+ r"|WebKit.pro"
+ r"|.*DerivedSources\.pri",
+ },
"QtWebKit2PublicAPI": {
"filename": r"Source/WebKit2/UIProcess/API/qt/"
r"|Source/WebKit2/UIProcess/API/cpp/qt/"
@@ -131,8 +141,9 @@
"ChromiumDumpRenderTree": [ "tkent@chromium.org", ],
"ChromiumGraphics": [ "jamesr@chromium.org", "cc-bugs@google.com" ],
"ChromiumPublicApi": [ "fishd@chromium.org", ],
+ "AppleMacPublicApi": [ "timothy@apple.com" ],
"Forms": [ "tkent@chromium.org", ],
- "GStreamerGraphics": [ "pnormand@igalia.com", "gns@gnome.org" ],
+ "GStreamerGraphics": [ "alexis.menard@openbossa.org", "pnormand@igalia.com", "gns@gnome.org" ],
"WebIDL": [ "abarth@webkit.org", "ojan@chromium.org" ],
"StyleChecker": [ "levin@chromium.org", ],
"ThreadingFiles|ThreadingUsage": [ "levin+threading@chromium.org", ],
@@ -144,9 +155,10 @@
"webkitpy": [ "abarth@webkit.org", "ojan@chromium.org" ],
"TestFailures": [ "abarth@webkit.org", "dglazkov@chromium.org" ],
"GtkWebKit2PublicAPI": [ "cgarcia@igalia.com", "gns@gnome.org" ],
- "QtWebKit2PublicAPI": [ "zoltan@webkit.org", ],
- "QtWebKit2PlatformSpecific": [ "zoltan@webkit.org", ],
- "CSS": [ "macpherson@chromium.org", ],
+ "QtBuildSystem" : [ "vestbo@webkit.org", ],
+ "QtWebKit2PublicAPI": [ "alexis.menard@openbossa.org", "zoltan@webkit.org", ],
+ "QtWebKit2PlatformSpecific": [ "alexis.menard@openbossa.org", "zoltan@webkit.org", ],
+ "CSS": [ "alexis.menard@openbossa.org", "macpherson@chromium.org", ],
"EFL": [ "kubo@profusion.mobi", ],
"CMake": [ "kubo@profusion.mobi", ],
"SoupNetwork": [ "kubo@profusion.mobi", ],
@@ -154,6 +166,10 @@
"MESSAGE_RULES": {
"ChromiumPublicApi": [ "Please wait for approval from fishd@chromium.org before submitting "
"because this patch contains changes to the Chromium public API.", ],
+ "AppleMacPublicApi": [ "Please wait for approval from timothy@apple.com (or another member "
+ "of the Apple Safari Team) before submitting "
+ "because this patch contains changes to the Apple Mac "
+ "WebKit.framework public API.", ],
"GtkWebKit2PublicAPI": [ "Thanks for the patch. If this patch contains new public API "
"please make sure it follows the guidelines for new WebKit2 GTK+ API. "
"See http://trac.webkit.org/wiki/WebKitGTK/AddingNewWebKit2API", ],
diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
index 511f1bbdb..a32e86e13 100644
--- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
+++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
@@ -259,20 +259,26 @@ class BugzillaQueries(object):
class Bugzilla(object):
- def __init__(self, dryrun=False, committers=committers.CommitterList()):
- self.dryrun = dryrun
+ def __init__(self, committers=committers.CommitterList()):
self.authenticated = False
self.queries = BugzillaQueries(self)
self.committers = committers
self.cached_quips = []
self.edit_user_parser = EditUsersParser()
+ self._browser = None
- # FIXME: We should use some sort of Browser mock object when in dryrun
- # mode (to prevent any mistakes).
- from webkitpy.thirdparty.autoinstalled.mechanize import Browser
- self.browser = Browser()
- # Ignore bugs.webkit.org/robots.txt until we fix it to allow this script.
- self.browser.set_handle_robots(False)
+ def _get_browser(self):
+ if not self._browser:
+ from webkitpy.thirdparty.autoinstalled.mechanize import Browser
+ self._browser = Browser()
+ # Ignore bugs.webkit.org/robots.txt until we fix it to allow this script.
+ self._browser.set_handle_robots(False)
+ return self._browser
+
+ def _set_browser(self, value):
+ self._browser = value
+
+ browser = property(_get_browser, _set_browser)
def fetch_user(self, user_id):
self.authenticate()
@@ -291,7 +297,7 @@ class Bugzilla(object):
def quips(self):
# We only fetch and parse the list of quips once per instantiation
# so that we do not burden bugs.webkit.org.
- if not self.cached_quips and not self.dryrun:
+ if not self.cached_quips:
self.cached_quips = self.queries.fetch_quips()
return self.cached_quips
@@ -475,11 +481,6 @@ class Bugzilla(object):
if self.authenticated:
return
- if self.dryrun:
- log("Skipping log in for dry run...")
- self.authenticated = True
- return
-
credentials = Credentials(config_urls.bug_server_host, git_prefix="bugzilla")
attempts = 0
@@ -563,10 +564,6 @@ class Bugzilla(object):
comment_text=None):
self.authenticate()
log('Adding attachment "%s" to %s' % (description, self.bug_url_for_bug_id(bug_id)))
- if self.dryrun:
- log(comment_text)
- return
-
self.browser.open(self.add_attachment_url(bug_id))
self.browser.select_form(name="entryform")
file_object = self._file_object_for_upload(file_or_string)
@@ -590,10 +587,6 @@ class Bugzilla(object):
self.authenticate()
log('Adding patch "%s" to %s' % (description, self.bug_url_for_bug_id(bug_id)))
- if self.dryrun:
- log(comment_text)
- return
-
self.browser.open(self.add_attachment_url(bug_id))
self.browser.select_form(name="entryform")
file_object = self._file_object_for_upload(file_or_string)
@@ -644,11 +637,6 @@ class Bugzilla(object):
self.authenticate()
log('Creating bug with title "%s"' % bug_title)
- if self.dryrun:
- log(bug_description)
- # FIXME: This will make some paths fail, as they assume this returns an id.
- return
-
self.browser.open(config_urls.bug_server_url + "enter_bug.cgi?product=WebKit")
self.browser.select_form(name="Create")
component_items = self.browser.find_control('component').items
@@ -706,9 +694,6 @@ class Bugzilla(object):
comment_text += "\n\n%s" % additional_comment_text
log(comment_text)
- if self.dryrun:
- return
-
self.browser.open(self.attachment_url_for_id(attachment_id, 'edit'))
self.browser.select_form(nr=1)
self.browser.set_value(comment_text, name='comment', nr=0)
@@ -732,9 +717,6 @@ class Bugzilla(object):
comment_text += "\n\n%s" % additional_comment_text
log(comment_text)
- if self.dryrun:
- return
-
self.browser.open(self.attachment_url_for_id(attachment_id, 'edit'))
self.browser.select_form(nr=1)
@@ -751,10 +733,6 @@ class Bugzilla(object):
self.authenticate()
log("Obsoleting attachment: %s" % attachment_id)
- if self.dryrun:
- log(comment_text)
- return
-
self.browser.open(self.attachment_url_for_id(attachment_id, 'edit'))
self.browser.select_form(nr=1)
self.browser.find_control('isobsolete').items[0].selected = True
@@ -772,9 +750,6 @@ class Bugzilla(object):
self.authenticate()
log("Adding %s to the CC list for bug %s" % (email_address_list, bug_id))
- if self.dryrun:
- return
-
self.browser.open(self.bug_url_for_bug_id(bug_id))
self.browser.select_form(name="changeform")
self.browser["newcc"] = ", ".join(email_address_list)
@@ -784,10 +759,6 @@ class Bugzilla(object):
self.authenticate()
log("Adding comment to bug %s" % bug_id)
- if self.dryrun:
- log(comment_text)
- return
-
self.browser.open(self.bug_url_for_bug_id(bug_id))
self.browser.select_form(name="changeform")
self.browser["comment"] = comment_text
@@ -799,10 +770,6 @@ class Bugzilla(object):
self.authenticate()
log("Closing bug %s as fixed" % bug_id)
- if self.dryrun:
- log(comment_text)
- return
-
self.browser.open(self.bug_url_for_bug_id(bug_id))
self.browser.select_form(name="changeform")
if comment_text:
@@ -821,10 +788,6 @@ class Bugzilla(object):
assignee = self.username
log("Assigning bug %s to %s" % (bug_id, assignee))
- if self.dryrun:
- log(comment_text)
- return
-
self.browser.open(self.bug_url_for_bug_id(bug_id))
self.browser.select_form(name="changeform")
@@ -850,9 +813,6 @@ for someone to add EditBugs to your bugs.webkit.org account.""")
# Bugzilla requires a comment when re-opening a bug, so we know it will
# never be None.
log(comment_text)
- if self.dryrun:
- return
-
self.browser.open(self.bug_url_for_bug_id(bug_id))
self.browser.select_form(name="changeform")
bug_status = self.browser.find_control("bug_status", type="select")
diff --git a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py
index 644a8219a..e84fcbffd 100644
--- a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py
+++ b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot.py
@@ -432,23 +432,78 @@ class BuildBot(object):
return build
build = build.previous_build()
- def last_green_revision(self):
- builds = self._latest_builds_from_builders()
- target_revision = builds[0].revision()
- # An alternate way to do this would be to start at one revision and walk backwards
- # checking builder.build_for_revision, however build_for_revision is very slow on first load.
- while True:
- # Make builds agree on revision
- builds = [self._build_at_or_before_revision(build, target_revision) for build in builds]
- if None in builds: # One of the builds failed to load from the server.
- return None
- min_revision = min(map(lambda build: build.revision(), builds))
- if min_revision != target_revision:
- target_revision = min_revision
- continue # Builds don't all agree on revision, keep searching
- # Check to make sure they're all green
- all_are_green = reduce(operator.and_, map(lambda build: build.is_green(), builds))
- if not all_are_green:
- target_revision -= 1
+ def _fetch_builder_page(self, builder):
+ builder_page_url = "%s/builders/%s?numbuilds=100" % (self.buildbot_url, urllib2.quote(builder.name()))
+ return urllib2.urlopen(builder_page_url)
+
+ def _revisions_for_builder(self, builder):
+ soup = BeautifulSoup(self._fetch_builder_page(builder))
+ revisions = []
+ for status_row in soup.find('table').findAll('tr'):
+ revision_anchor = status_row.find('a')
+ table_cells = status_row.findAll('td')
+ if not table_cells or len(table_cells) < 3 or not table_cells[2].string:
continue
- return min_revision
+ if revision_anchor and revision_anchor.string and re.match(r'^\d+$', revision_anchor.string):
+ revisions.append((int(revision_anchor.string), 'success' in table_cells[2].string))
+ return revisions
+
+ def _find_green_revision(self, builder_revisions):
+ revision_statuses = {}
+ for builder in builder_revisions:
+ for revision, succeeded in builder_revisions[builder]:
+ revision_statuses.setdefault(revision, set())
+ if succeeded and revision_statuses[revision] != None:
+ revision_statuses[revision].add(builder)
+ else:
+ revision_statuses[revision] = None
+
+ # In descending order, look for a revision X with successful builds
+ # Once we found X, check if remaining builders succeeded in the neighborhood of X.
+ revisions_in_order = sorted(revision_statuses.keys(), reverse=True)
+ for i, revision in enumerate(revisions_in_order):
+ if not revision_statuses[revision]:
+ continue
+
+ builders_succeeded_in_future = set()
+ for future_revision in sorted(revisions_in_order[:i + 1]):
+ if not revision_statuses[future_revision]:
+ break
+ builders_succeeded_in_future = builders_succeeded_in_future.union(revision_statuses[future_revision])
+
+ builders_succeeded_in_past = set()
+ for past_revision in revisions_in_order[i:]:
+ if not revision_statuses[past_revision]:
+ break
+ builders_succeeded_in_past = builders_succeeded_in_past.union(revision_statuses[past_revision])
+
+ if len(builders_succeeded_in_future) == len(builder_revisions) and len(builders_succeeded_in_past) == len(builder_revisions):
+ return revision
+ return None
+
+ def last_green_revision(self, builder_name_regex):
+ compiled_builder_name_regex = re.compile(builder_name_regex, flags=re.IGNORECASE)
+ builders = [builder for builder in self.builders() if compiled_builder_name_regex.search(builder.name())]
+ if len(builders) > 10:
+ return '"%s" matches too many bots' % builder_name_regex
+ elif not len(builders):
+ return '"%s" doesn\'t match any bot' % builder_name_regex
+
+ builder_revisions = {}
+ for builder in builders:
+ builder_revisions[builder] = self._revisions_for_builder(builder)
+
+ result = ''
+ revision_with_all_builders = self._find_green_revision(builder_revisions)
+ if revision_with_all_builders:
+ result += 'The last known green revision is %d\n' % revision_with_all_builders
+
+ for builder in builders:
+ succeeded_revisions = [revision for revision, succeeded in builder_revisions[builder] if succeeded]
+ if not succeeded_revisions:
+ result += '%s has had no green revision in the last %d runs' % (builder.name(), len(builder_revisions[builder]))
+ else:
+ result += '%s: %d' % (builder.name(), max(succeeded_revisions))
+ result += "\n"
+
+ return result
diff --git a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py
index f9e27b80b..34f714985 100644
--- a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py
+++ b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_mock.py
@@ -90,8 +90,8 @@ class MockBuildBot(object):
self._mock_builder2_status,
]
- def last_green_revision(self):
- return 9479
+ def last_green_revision(self, builder_name):
+ return builder_name + ' 1: ' + str(9479) + '\n' + builder_name + ' 2: ' + str(9400)
def light_tree_on_fire(self):
self._mock_builder2_status["is_green"] = False
diff --git a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py
index 5b1e57140..7e22cf5ff 100644
--- a/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py
+++ b/Tools/Scripts/webkitpy/common/net/buildbot/buildbot_unittest.py
@@ -299,37 +299,140 @@ class BuildBotTest(unittest.TestCase):
files = buildbot._parse_twisted_directory_listing(self._example_directory_listing)
self.assertEqual(self._expected_files, files)
- # Revision, is_green
- # Ordered from newest (highest number) to oldest.
- fake_builder1 = [
- [2, False],
- [1, True],
- ]
- fake_builder2 = [
- [2, False],
- [1, True],
- ]
- fake_builders = [
- fake_builder1,
- fake_builder2,
- ]
- def _build_from_fake(self, fake_builder, index):
- if index >= len(fake_builder):
- return None
- fake_build = fake_builder[index]
- build = Build(
- builder=fake_builder,
- build_number=index,
- revision=fake_build[0],
- is_green=fake_build[1],
- )
- def mock_previous_build():
- return self._build_from_fake(fake_builder, index + 1)
- build.previous_build = mock_previous_build
- return build
-
- def _fake_builds_at_index(self, index):
- return [self._build_from_fake(builder, index) for builder in self.fake_builders]
+ _fake_builder_page = '''
+ <body>
+ <div class="content">
+ <h1>Some Builder</h1>
+ <p>(<a href="../waterfall?show=Some Builder">view in waterfall</a>)</p>
+ <div class="column">
+ <h2>Recent Builds:</h2>
+ <table class="info">
+ <tr>
+ <th>Time</th>
+ <th>Revision</th>
+ <th>Result</th> <th>Build #</th>
+ <th>Info</th>
+ </tr>
+ <tr class="alt">
+ <td>Jan 10 15:49</td>
+ <td><span class="revision" title="Revision 104643"><a href="http://trac.webkit.org/changeset/104643">104643</a></span></td>
+ <td class="success">failure</td> <td><a href=".../37604">#37604</a></td>
+ <td class="left">Build successful</td>
+ </tr>
+ <tr class="">
+ <td>Jan 10 15:32</td>
+ <td><span class="revision" title="Revision 104636"><a href="http://trac.webkit.org/changeset/104636">104636</a></span></td>
+ <td class="success">failure</td> <td><a href=".../37603">#37603</a></td>
+ <td class="left">Build successful</td>
+ </tr>
+ <tr class="alt">
+ <td>Jan 10 15:18</td>
+ <td><span class="revision" title="Revision 104635"><a href="http://trac.webkit.org/changeset/104635">104635</a></span></td>
+ <td class="success">success</td> <td><a href=".../37602">#37602</a></td>
+ <td class="left">Build successful</td>
+ </tr>
+ <tr class="">
+ <td>Jan 10 14:51</td>
+ <td><span class="revision" title="Revision 104633"><a href="http://trac.webkit.org/changeset/104633">104633</a></span></td>
+ <td class="failure">failure</td> <td><a href=".../37601">#37601</a></td>
+ <td class="left">Failed compile-webkit</td>
+ </tr>
+ </table>
+ </body>'''
+ _fake_builder_page_without_success = '''
+ <body>
+ <table>
+ <tr class="alt">
+ <td>Jan 10 15:49</td>
+ <td><span class="revision" title="Revision 104643"><a href="http://trac.webkit.org/changeset/104643">104643</a></span></td>
+ <td class="success">failure</td>
+ </tr>
+ <tr class="">
+ <td>Jan 10 15:32</td>
+ <td><span class="revision" title="Revision 104636"><a href="http://trac.webkit.org/changeset/104636">104636</a></span></td>
+ <td class="success">failure</td>
+ </tr>
+ <tr class="alt">
+ <td>Jan 10 15:18</td>
+ <td><span class="revision" title="Revision 104635"><a href="http://trac.webkit.org/changeset/104635">104635</a></span></td>
+ <td class="success">failure</td>
+ </tr>
+ <tr class="">
+ <td>Jan 10 11:58</td>
+ <td><span class="revision" title="Revision ??"><a href="http://trac.webkit.org/changeset/%3F%3F">??</a></span></td>
+ <td class="retry">retry</td>
+ </tr>
+ <tr class="">
+ <td>Jan 10 14:51</td>
+ <td><span class="revision" title="Revision 104633"><a href="http://trac.webkit.org/changeset/104633">104633</a></span></td>
+ <td class="failure">failure</td>
+ </tr>
+ </table>
+ </body>'''
+
+ def test_revisions_for_builder(self):
+ buildbot = BuildBot()
+ buildbot._fetch_builder_page = lambda builder: builder.page
+ builder_with_success = Builder('Some builder', None)
+ builder_with_success.page = self._fake_builder_page
+ self.assertEqual(buildbot._revisions_for_builder(builder_with_success), [(104643, False), (104636, False), (104635, True), (104633, False)])
+
+ builder_without_success = Builder('Some builder', None)
+ builder_without_success.page = self._fake_builder_page_without_success
+ self.assertEqual(buildbot._revisions_for_builder(builder_without_success), [(104643, False), (104636, False), (104635, False), (104633, False)])
+
+ def test_find_green_revision(self):
+ buildbot = BuildBot()
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (3, True)],
+ 'Builder 2': [(1, True), (3, False)],
+ 'Builder 3': [(1, True), (3, True)],
+ }), 1)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, False), (3, True)],
+ 'Builder 2': [(1, True), (3, True)],
+ 'Builder 3': [(1, True), (3, True)],
+ }), 3)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (2, True)],
+ 'Builder 2': [(1, False), (2, True), (3, True)],
+ 'Builder 3': [(1, True), (3, True)],
+ }), None)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (2, True)],
+ 'Builder 2': [(1, True), (2, True), (3, True)],
+ 'Builder 3': [(1, True), (3, True)],
+ }), 2)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, False), (2, True)],
+ 'Builder 2': [(1, True), (3, True)],
+ 'Builder 3': [(1, True), (3, True)],
+ }), None)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (3, True)],
+ 'Builder 2': [(1, False), (2, True), (3, True), (4, True)],
+ 'Builder 3': [(2, True), (4, True)],
+ }), 3)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (3, True)],
+ 'Builder 2': [(1, False), (2, True), (3, True), (4, False)],
+ 'Builder 3': [(2, True), (4, True)],
+ }), None)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (3, True)],
+ 'Builder 2': [(1, False), (2, True), (3, True), (4, False)],
+ 'Builder 3': [(2, True), (3, True), (4, True)],
+ }), 3)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (2, True)],
+ 'Builder 2': [],
+ 'Builder 3': [(1, True), (2, True)],
+ }), None)
+ self.assertEqual(buildbot._find_green_revision({
+ 'Builder 1': [(1, True), (3, False), (5, True), (10, True), (12, False)],
+ 'Builder 2': [(1, True), (3, False), (7, True), (9, True), (12, False)],
+ 'Builder 3': [(1, True), (3, True), (7, True), (11, False), (12, True)],
+ }), 7)
def test_last_green_revision(self):
buildbot = BuildBot()
@@ -337,8 +440,24 @@ class BuildBotTest(unittest.TestCase):
def mock_builds_from_builders():
return self._fake_builds_at_index(0)
+ # Revision, is_green
+ # Ordered from newest (highest number) to oldest.
+ fake_builder1 = Builder("Fake Builder 1", None)
+ fake_builder1.revisions = [(1, True), (3, False), (5, True), (10, True), (12, False)]
+ fake_builder2 = Builder("Fake Builder 2", None)
+ fake_builder2.revisions = [(1, True), (3, False), (7, True), (9, True), (12, False)]
+ some_builder = Builder("Some Builder", None)
+ some_builder.revisions = [(1, True), (3, True), (7, True), (11, False), (12, True)]
+
+ buildbot.builders = lambda: [fake_builder1, fake_builder2, some_builder]
+ buildbot._revisions_for_builder = lambda builder: builder.revisions
buildbot._latest_builds_from_builders = mock_builds_from_builders
- self.assertEqual(buildbot.last_green_revision(), 1)
+ self.assertEqual(buildbot.last_green_revision(''),
+ "The last known green revision is 7\nFake Builder 1: 10\nFake Builder 2: 9\nSome Builder: 12\n")
+
+ some_builder.revisions = [(1, False), (3, False)]
+ self.assertEqual(buildbot.last_green_revision(''),
+ "Fake Builder 1: 10\nFake Builder 2: 9\nSome Builder has had no green revision in the last 2 runs\n")
def _fetch_build(self, build_number):
if build_number == 5:
diff --git a/Tools/Scripts/webkitpy/common/net/file_uploader.py b/Tools/Scripts/webkitpy/common/net/file_uploader.py
index 66e49e866..aa3488bbf 100644
--- a/Tools/Scripts/webkitpy/common/net/file_uploader.py
+++ b/Tools/Scripts/webkitpy/common/net/file_uploader.py
@@ -84,31 +84,35 @@ def _encode_multipart_form_data(fields, files):
class FileUploader(object):
- def __init__(self, url):
+ def __init__(self, url, timeout_seconds):
self._url = url
+ self._timeout_seconds = timeout_seconds
- def _upload_files(self, attrs, file_objs):
- # FIXME: We should use the same variable names for the formal and actual parameters.
- content_type, data = _encode_multipart_form_data(attrs, file_objs)
- headers = {
- "Content-Type": content_type,
- }
- # FIXME: We should talk to the network via a Host object.
- request = urllib2.Request(self._url, data, headers)
- urllib2.urlopen(request)
-
- def upload(self, params, files, timeout_seconds):
+ def upload_single_text_file(self, filesystem, content_type, filename):
+ return self._upload_data(content_type, filesystem.read_text_file(filename))
+
+ def upload_as_multipart_form_data(self, filesystem, files, attrs):
file_objs = []
for filename, path in files:
# FIXME: We should talk to the filesytem via a Host object.
with codecs.open(path, "rb") as file:
file_objs.append(('file', filename, file.read()))
+ # FIXME: We should use the same variable names for the formal and actual parameters.
+ content_type, data = _encode_multipart_form_data(attrs, file_objs)
+ return self._upload_data(content_type, data)
+
+ def _upload_data(self, content_type, data):
+ def callback():
+ request = urllib2.Request(self._url, data, {"Content-Type": content_type})
+ return urllib2.urlopen(request)
+
orig_timeout = socket.getdefaulttimeout()
+ response = None
try:
# FIXME: We shouldn't mutate global static state.
- socket.setdefaulttimeout(timeout_seconds)
- NetworkTransaction(timeout_seconds=timeout_seconds).run(
- lambda: self._upload_files(params, file_objs))
+ socket.setdefaulttimeout(self._timeout_seconds)
+ response = NetworkTransaction(timeout_seconds=self._timeout_seconds).run(callback)
finally:
socket.setdefaulttimeout(orig_timeout)
+ return response
diff --git a/Tools/Scripts/webkitpy/common/system/executive.py b/Tools/Scripts/webkitpy/common/system/executive.py
index 0481f0472..06f870c72 100644
--- a/Tools/Scripts/webkitpy/common/system/executive.py
+++ b/Tools/Scripts/webkitpy/common/system/executive.py
@@ -27,12 +27,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.
-try:
- # This API exists only in Python 2.6 and higher. :(
- import multiprocessing
-except ImportError:
- multiprocessing = None
-
+import multiprocessing
import ctypes
import errno
import logging
@@ -160,21 +155,7 @@ class Executive(object):
return child_output
def cpu_count(self):
- if multiprocessing:
- return multiprocessing.cpu_count()
- # Darn. We don't have the multiprocessing package.
- system_name = platform.system()
- if system_name == "Darwin":
- return int(self.run_command(["sysctl", "-n", "hw.ncpu"]))
- elif system_name == "Windows":
- return int(os.environ.get('NUMBER_OF_PROCESSORS', 1))
- elif system_name == "Linux":
- num_cores = os.sysconf("SC_NPROCESSORS_ONLN")
- if isinstance(num_cores, int) and num_cores > 0:
- return num_cores
- # This quantity is a lie but probably a reasonable guess for modern
- # machines.
- return 2
+ return multiprocessing.cpu_count()
@staticmethod
def interpreter_for_script(script_path, fs=None):
diff --git a/Tools/Scripts/webkitpy/common/system/executive_mock.py b/Tools/Scripts/webkitpy/common/system/executive_mock.py
index c3a4c4d5f..f698235e9 100644
--- a/Tools/Scripts/webkitpy/common/system/executive_mock.py
+++ b/Tools/Scripts/webkitpy/common/system/executive_mock.py
@@ -34,6 +34,10 @@ from webkitpy.common.system.executive import ScriptError
# FIXME: This should be unified with MockExecutive2
class MockExecutive(object):
+ @staticmethod
+ def ignore_error(error):
+ pass
+
def __init__(self, should_log=False, should_throw=False, should_throw_when_run=None):
self._should_log = should_log
self._should_throw = should_throw
@@ -79,6 +83,10 @@ class MockExecutive(object):
class MockExecutive2(object):
+ @staticmethod
+ def ignore_error(error):
+ pass
+
def __init__(self, output='', exit_code=0, exception=None,
run_command_fn=None, stderr=''):
self._output = output
diff --git a/Tools/Scripts/webkitpy/common/system/executive_unittest.py b/Tools/Scripts/webkitpy/common/system/executive_unittest.py
index a0878f9ce..c63ff3555 100644
--- a/Tools/Scripts/webkitpy/common/system/executive_unittest.py
+++ b/Tools/Scripts/webkitpy/common/system/executive_unittest.py
@@ -33,9 +33,14 @@ import subprocess
import sys
import unittest
+# Since we execute this script directly as part of the unit tests, we need to ensure
+# that Tools/Scripts is in sys.path for the next imports to work correctly.
+script_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
+if script_dir not in sys.path:
+ sys.path.append(script_dir)
+
from webkitpy.common.system.executive import Executive, ScriptError
from webkitpy.common.system.filesystem_mock import MockFileSystem
-from webkitpy.test import cat, echo
class ScriptErrorTest(unittest.TestCase):
@@ -64,8 +69,11 @@ def never_ending_command():
return ['yes']
-class ExecutiveTest(unittest.TestCase):
+def command_line(cmd, *args):
+ return [sys.executable, __file__, '--' + cmd] + list(args)
+
+class ExecutiveTest(unittest.TestCase):
def assert_interpreter_for_content(self, intepreter, content):
fs = MockFileSystem()
file_path = None
@@ -102,8 +110,8 @@ class ExecutiveTest(unittest.TestCase):
executive = Executive()
self.assertRaises(AssertionError, executive.run_command, "echo")
self.assertRaises(AssertionError, executive.run_command, u"echo")
- executive.run_command(echo.command_arguments('foo'))
- executive.run_command(tuple(echo.command_arguments('foo')))
+ executive.run_command(command_line('echo', 'foo'))
+ executive.run_command(tuple(command_line('echo', 'foo')))
def test_run_command_with_unicode(self):
"""Validate that it is safe to pass unicode() objects
@@ -124,24 +132,24 @@ class ExecutiveTest(unittest.TestCase):
executive = Executive()
- output = executive.run_command(cat.command_arguments(), input=unicode_tor_input)
+ output = executive.run_command(command_line('cat'), input=unicode_tor_input)
self.assertEquals(output, unicode_tor_output)
- output = executive.run_command(echo.command_arguments("-n", unicode_tor_input))
+ output = executive.run_command(command_line('echo', unicode_tor_input))
self.assertEquals(output, unicode_tor_output)
- output = executive.run_command(echo.command_arguments("-n", unicode_tor_input), decode_output=False)
+ output = executive.run_command(command_line('echo', unicode_tor_input), decode_output=False)
self.assertEquals(output, encoded_tor)
# Make sure that str() input also works.
- output = executive.run_command(cat.command_arguments(), input=encoded_tor, decode_output=False)
+ output = executive.run_command(command_line('cat'), input=encoded_tor, decode_output=False)
self.assertEquals(output, encoded_tor)
# FIXME: We should only have one run* method to test
- output = executive.run_and_throw_if_fail(echo.command_arguments("-n", unicode_tor_input), quiet=True)
+ output = executive.run_and_throw_if_fail(command_line('echo', unicode_tor_input), quiet=True)
self.assertEquals(output, unicode_tor_output)
- output = executive.run_and_throw_if_fail(echo.command_arguments("-n", unicode_tor_input), quiet=True, decode_output=False)
+ output = executive.run_and_throw_if_fail(command_line('echo', unicode_tor_input), quiet=True, decode_output=False)
self.assertEquals(output, encoded_tor)
def test_kill_process(self):
@@ -207,3 +215,17 @@ class ExecutiveTest(unittest.TestCase):
executive = Executive()
pids = executive.running_pids()
self.assertTrue(os.getpid() in pids)
+
+
+def main(platform, stdin, stdout, cmd, args):
+ if platform == 'win32' and hasattr(stdout, 'fileno'):
+ import msvcrt
+ msvcrt.setmode(stdout.fileno(), os.O_BINARY)
+ if cmd == '--cat':
+ stdout.write(stdin.read())
+ elif cmd == '--echo':
+ stdout.write(' '.join(args))
+ return 0
+
+if __name__ == '__main__' and len(sys.argv) > 1 and sys.argv[1] in ('--cat', '--echo'):
+ sys.exit(main(sys.platform, sys.stdin, sys.stdout, sys.argv[1], sys.argv[2:]))
diff --git a/Tools/Scripts/webkitpy/common/system/fileutils.py b/Tools/Scripts/webkitpy/common/system/fileutils.py
deleted file mode 100644
index 55821f835..000000000
--- a/Tools/Scripts/webkitpy/common/system/fileutils.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2010 Apple 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:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. 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.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 sys
-
-
-def make_stdout_binary():
- """Puts sys.stdout into binary mode (on platforms that have a distinction
- between text and binary mode)."""
- if sys.platform != 'win32' or not hasattr(sys.stdout, 'fileno'):
- return
- import msvcrt
- import os
- msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
diff --git a/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py b/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py
index 71c3e8ce7..7302761de 100644
--- a/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py
+++ b/Tools/Scripts/webkitpy/common/system/platforminfo_mock.py
@@ -32,13 +32,13 @@ class MockPlatformInfo(object):
os_version = 'snowleopard'
def is_mac(self):
- return True
+ return self.os_name == 'mac'
def is_linux(self):
- return False
+ return self.os_name == 'linux'
- def is_windows(self):
- return False
+ def is_win(self):
+ return self.os_name == 'win'
def display_name(self):
return "MockPlatform 1.0"
diff --git a/Tools/Scripts/webkitpy/common/system/systemhost_mock.py b/Tools/Scripts/webkitpy/common/system/systemhost_mock.py
index 61f8972bf..f3bc94139 100644
--- a/Tools/Scripts/webkitpy/common/system/systemhost_mock.py
+++ b/Tools/Scripts/webkitpy/common/system/systemhost_mock.py
@@ -35,11 +35,15 @@ from webkitpy.common.system.workspace_mock import MockWorkspace
class MockSystemHost(object):
- def __init__(self, log_executive=False, executive_throws_when_run=None):
+ def __init__(self, log_executive=False, executive_throws_when_run=None, os_name=None, os_version=None):
self.executive = MockExecutive(should_log=log_executive, should_throw_when_run=executive_throws_when_run)
self.filesystem = MockFileSystem()
self.user = MockUser()
self.platform = MockPlatformInfo()
+ if os_name:
+ self.platform.os_name = os_name
+ if os_version:
+ self.platform.os_version = os_version
# FIXME: Should this take pointers to the filesystem and the executive?
self.workspace = MockWorkspace()