[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

eric at webkit.org eric at webkit.org
Wed Dec 22 15:45:50 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 62126eecd6f449dc3b15fb949608f72682725c94
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Nov 11 23:26:43 2010 +0000

    2010-11-11  Eric Seidel  <eric at webkit.org>
    
            Reviewed by Adam Barth.
    
            Split out Bug, Attachment and CommitterValidator from bugzilla.py
            https://bugs.webkit.org/show_bug.cgi?id=49403
    
            CommitterValidator really had nothing to do with bugzilla.py.
            I've put it next to committers.py for now since its rather tied to that file.
    
            * Scripts/webkitpy/common/config/committervalidator.py: Added.
            * Scripts/webkitpy/common/config/committervalidator_unittest.py: Added.
            * Scripts/webkitpy/common/net/bugzilla/__init__.py:
            * Scripts/webkitpy/common/net/bugzilla/attachment.py: Added.
            * Scripts/webkitpy/common/net/bugzilla/bug.py: Added.
            * Scripts/webkitpy/common/net/bugzilla/bug_unittest.py: Added.
            * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
            * Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py:
            * Scripts/webkitpy/tool/bot/feeders.py:
            * Scripts/webkitpy/tool/commands/queues.py:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71856 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 47c7ff4..977265d 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,24 @@
+2010-11-11  Eric Seidel  <eric at webkit.org>
+
+        Reviewed by Adam Barth.
+
+        Split out Bug, Attachment and CommitterValidator from bugzilla.py
+        https://bugs.webkit.org/show_bug.cgi?id=49403
+
+        CommitterValidator really had nothing to do with bugzilla.py.
+        I've put it next to committers.py for now since its rather tied to that file.
+
+        * Scripts/webkitpy/common/config/committervalidator.py: Added.
+        * Scripts/webkitpy/common/config/committervalidator_unittest.py: Added.
+        * Scripts/webkitpy/common/net/bugzilla/__init__.py:
+        * Scripts/webkitpy/common/net/bugzilla/attachment.py: Added.
+        * Scripts/webkitpy/common/net/bugzilla/bug.py: Added.
+        * Scripts/webkitpy/common/net/bugzilla/bug_unittest.py: Added.
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py:
+        * Scripts/webkitpy/tool/bot/feeders.py:
+        * Scripts/webkitpy/tool/commands/queues.py:
+
 2010-11-11  Dirk Pranke  <dpranke at chromium.org>
 
         Reviewed by Eric Seidel.
diff --git a/WebKitTools/Scripts/webkitpy/common/config/committervalidator.py b/WebKitTools/Scripts/webkitpy/common/config/committervalidator.py
new file mode 100644
index 0000000..b7b2990
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/common/config/committervalidator.py
@@ -0,0 +1,120 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Copyright (c) 2009 Apple Inc. All rights reserved.
+# Copyright (c) 2010 Research In Motion Limited. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+
+from webkitpy.common.system.ospath import relpath
+from webkitpy.common.config import committers
+
+
+class CommitterValidator(object):
+
+    def __init__(self, bugzilla):
+        self._bugzilla = bugzilla
+
+    # _view_source_url belongs in some sort of webkit_config.py module.
+    def _view_source_url(self, local_path):
+        return "http://trac.webkit.org/browser/trunk/%s" % local_path
+
+    def _checkout_root(self):
+        # FIXME: This is a hack, we would have this from scm.checkout_root
+        # if we had any way to get to an scm object here.
+        components = __file__.split(os.sep)
+        tools_index = components.index("WebKitTools")
+        return os.sep.join(components[:tools_index])
+
+    def _committers_py_path(self):
+        # extension can sometimes be .pyc, we always want .py
+        (path, extension) = os.path.splitext(committers.__file__)
+        # FIXME: When we're allowed to use python 2.6 we can use the real
+        # os.path.relpath
+        path = relpath(path, self._checkout_root())
+        return ".".join([path, "py"])
+
+    def _flag_permission_rejection_message(self, setter_email, flag_name):
+        # Should come from some webkit_config.py
+        contribution_guidlines = "http://webkit.org/coding/contributing.html"
+        # This could be queried from the status_server.
+        queue_administrator = "eseidel at chromium.org"
+        # This could be queried from the tool.
+        queue_name = "commit-queue"
+        committers_list = self._committers_py_path()
+        message = "%s does not have %s permissions according to %s." % (
+                        setter_email,
+                        flag_name,
+                        self._view_source_url(committers_list))
+        message += "\n\n- If you do not have %s rights please read %s for instructions on how to use bugzilla flags." % (
+                        flag_name, contribution_guidlines)
+        message += "\n\n- If you have %s rights please correct the error in %s by adding yourself to the file (no review needed).  " % (
+                        flag_name, committers_list)
+        message += "The %s restarts itself every 2 hours.  After restart the %s will correctly respect your %s rights." % (
+                        queue_name, queue_name, flag_name)
+        return message
+
+    def _validate_setter_email(self, patch, result_key, rejection_function):
+        committer = getattr(patch, result_key)()
+        # If the flag is set, and we don't recognize the setter, reject the
+        # flag!
+        setter_email = patch._attachment_dictionary.get("%s_email" % result_key)
+        if setter_email and not committer:
+            rejection_function(patch.id(),
+                self._flag_permission_rejection_message(setter_email,
+                                                        result_key))
+            return False
+        return True
+
+    def _reject_patch_if_flags_are_invalid(self, patch):
+        return (self._validate_setter_email(
+                patch, "reviewer", self.reject_patch_from_review_queue)
+            and self._validate_setter_email(
+                patch, "committer", self.reject_patch_from_commit_queue))
+
+    def patches_after_rejecting_invalid_commiters_and_reviewers(self, patches):
+        return [patch for patch in patches if self._reject_patch_if_flags_are_invalid(patch)]
+
+    def reject_patch_from_commit_queue(self,
+                                       attachment_id,
+                                       additional_comment_text=None):
+        comment_text = "Rejecting patch %s from commit-queue." % attachment_id
+        self._bugzilla.set_flag_on_attachment(attachment_id,
+                                              "commit-queue",
+                                              "-",
+                                              comment_text,
+                                              additional_comment_text)
+
+    def reject_patch_from_review_queue(self,
+                                       attachment_id,
+                                       additional_comment_text=None):
+        comment_text = "Rejecting patch %s from review queue." % attachment_id
+        self._bugzilla.set_flag_on_attachment(attachment_id,
+                                              'review',
+                                              '-',
+                                              comment_text,
+                                              additional_comment_text)
diff --git a/WebKitTools/Scripts/webkitpy/common/config/committervalidator_unittest.py b/WebKitTools/Scripts/webkitpy/common/config/committervalidator_unittest.py
new file mode 100644
index 0000000..61fa3bf
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/common/config/committervalidator_unittest.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+from .committervalidator import CommitterValidator
+
+
+class CommitterValidatorTest(unittest.TestCase):
+    def test_flag_permission_rejection_message(self):
+        validator = CommitterValidator(bugzilla=None)
+        self.assertEqual(validator._committers_py_path(), "WebKitTools/Scripts/webkitpy/common/config/committers.py")
+        expected_messsage = """foo at foo.com does not have review permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py.
+
+- If you do not have review rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.
+
+- If you have review rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed).  The commit-queue restarts itself every 2 hours.  After restart the commit-queue will correctly respect your review rights."""
+        self.assertEqual(validator._flag_permission_rejection_message("foo at foo.com", "review"), expected_messsage)
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/__init__.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/__init__.py
index 2b7058f..cfaf3b1 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/__init__.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/__init__.py
@@ -1,4 +1,8 @@
 # Required for Python to search this directory for module files
 
-# Eventually bugzilla will have one-file-per-class and we'll only export public classes.
-from .bugzilla import *
+# We only export public API here.
+# FIXME: parse_bug_id should not be a free function.
+from .bugzilla import Bugzilla, parse_bug_id
+# Unclear if Bug and Attachment need to be public classes.
+from .bug import Bug
+from .attachment import Attachment
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/attachment.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/attachment.py
new file mode 100644
index 0000000..85761fe
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/attachment.py
@@ -0,0 +1,114 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Copyright (c) 2009 Apple Inc. All rights reserved.
+# Copyright (c) 2010 Research In Motion Limited. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from webkitpy.common.system.deprecated_logging import log
+
+
+class Attachment(object):
+
+    rollout_preamble = "ROLLOUT of r"
+
+    def __init__(self, attachment_dictionary, bug):
+        self._attachment_dictionary = attachment_dictionary
+        self._bug = bug
+        self._reviewer = None
+        self._committer = None
+
+    def _bugzilla(self):
+        return self._bug._bugzilla
+
+    def id(self):
+        return int(self._attachment_dictionary.get("id"))
+
+    def attacher_is_committer(self):
+        return self._bugzilla.committers.committer_by_email(
+            patch.attacher_email())
+
+    def attacher_email(self):
+        return self._attachment_dictionary.get("attacher_email")
+
+    def bug(self):
+        return self._bug
+
+    def bug_id(self):
+        return int(self._attachment_dictionary.get("bug_id"))
+
+    def is_patch(self):
+        return not not self._attachment_dictionary.get("is_patch")
+
+    def is_obsolete(self):
+        return not not self._attachment_dictionary.get("is_obsolete")
+
+    def is_rollout(self):
+        return self.name().startswith(self.rollout_preamble)
+
+    def name(self):
+        return self._attachment_dictionary.get("name")
+
+    def attach_date(self):
+        return self._attachment_dictionary.get("attach_date")
+
+    def review(self):
+        return self._attachment_dictionary.get("review")
+
+    def commit_queue(self):
+        return self._attachment_dictionary.get("commit-queue")
+
+    def url(self):
+        # FIXME: This should just return
+        # self._bugzilla().attachment_url_for_id(self.id()). scm_unittest.py
+        # depends on the current behavior.
+        return self._attachment_dictionary.get("url")
+
+    def contents(self):
+        # FIXME: We shouldn't be grabbing at _bugzilla.
+        return self._bug._bugzilla.fetch_attachment_contents(self.id())
+
+    def _validate_flag_value(self, flag):
+        email = self._attachment_dictionary.get("%s_email" % flag)
+        if not email:
+            return None
+        committer = getattr(self._bugzilla().committers,
+                            "%s_by_email" % flag)(email)
+        if committer:
+            return committer
+        log("Warning, attachment %s on bug %s has invalid %s (%s)" % (
+                 self._attachment_dictionary['id'],
+                 self._attachment_dictionary['bug_id'], flag, email))
+
+    def reviewer(self):
+        if not self._reviewer:
+            self._reviewer = self._validate_flag_value("reviewer")
+        return self._reviewer
+
+    def committer(self):
+        if not self._committer:
+            self._committer = self._validate_flag_value("committer")
+        return self._committer
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bug.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bug.py
new file mode 100644
index 0000000..2cb4bc8
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bug.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Copyright (c) 2009 Apple Inc. All rights reserved.
+# Copyright (c) 2010 Research In Motion Limited. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from .attachment import Attachment
+
+
+class Bug(object):
+    # FIXME: This class is kinda a hack for now.  It exists so we have one
+    # place to hold bug logic, even if much of the code deals with
+    # dictionaries still.
+
+    def __init__(self, bug_dictionary, bugzilla):
+        self.bug_dictionary = bug_dictionary
+        self._bugzilla = bugzilla
+
+    def id(self):
+        return self.bug_dictionary["id"]
+
+    def title(self):
+        return self.bug_dictionary["title"]
+
+    def assigned_to_email(self):
+        return self.bug_dictionary["assigned_to_email"]
+
+    # FIXME: This information should be stored in some sort of webkit_config.py instead of here.
+    unassigned_emails = frozenset([
+        "webkit-unassigned at lists.webkit.org",
+        "webkit-qt-unassigned at trolltech.com",
+    ])
+
+    def is_unassigned(self):
+        return self.assigned_to_email() in self.unassigned_emails
+
+    def status(self):
+        return self.bug_dictionary["bug_status"]
+
+    # Bugzilla has many status states we don't really use in WebKit:
+    # https://bugs.webkit.org/page.cgi?id=fields.html#status
+    _open_states = ["UNCONFIRMED", "NEW", "ASSIGNED", "REOPENED"]
+    _closed_states = ["RESOLVED", "VERIFIED", "CLOSED"]
+
+    def is_open(self):
+        return self.status() in self._open_states
+
+    def is_closed(self):
+        return not self.is_open()
+
+    # Rarely do we actually want obsolete attachments
+    def attachments(self, include_obsolete=False):
+        attachments = self.bug_dictionary["attachments"]
+        if not include_obsolete:
+            attachments = filter(lambda attachment:
+                                 not attachment["is_obsolete"], attachments)
+        return [Attachment(attachment, self) for attachment in attachments]
+
+    def patches(self, include_obsolete=False):
+        return [patch for patch in self.attachments(include_obsolete)
+                                   if patch.is_patch()]
+
+    def unreviewed_patches(self):
+        return [patch for patch in self.patches() if patch.review() == "?"]
+
+    def reviewed_patches(self, include_invalid=False):
+        patches = [patch for patch in self.patches() if patch.review() == "+"]
+        if include_invalid:
+            return patches
+        # Checking reviewer() ensures that it was both reviewed and has a valid
+        # reviewer.
+        return filter(lambda patch: patch.reviewer(), patches)
+
+    def commit_queued_patches(self, include_invalid=False):
+        patches = [patch for patch in self.patches()
+                                      if patch.commit_queue() == "+"]
+        if include_invalid:
+            return patches
+        # Checking committer() ensures that it was both commit-queue+'d and has
+        # a valid committer.
+        return filter(lambda patch: patch.committer(), patches)
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bug_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bug_unittest.py
new file mode 100644
index 0000000..d43d64f
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bug_unittest.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+from .bug import Bug
+
+
+class BugTest(unittest.TestCase):
+    def test_is_unassigned(self):
+        for email in Bug.unassigned_emails:
+            bug = Bug({"assigned_to_email": email}, bugzilla=None)
+            self.assertTrue(bug.is_unassigned())
+        bug = Bug({"assigned_to_email": "test at test.com"}, bugzilla=None)
+        self.assertFalse(bug.is_unassigned())
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
index a7dc1b7..91acdf7 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
@@ -36,15 +36,18 @@ import StringIO
 
 from datetime import datetime # used in timestamp()
 
-from webkitpy.common.system.deprecated_logging import error, log
+from .attachment import Attachment
+from .bug import Bug
+
+from webkitpy.common.system.deprecated_logging import log
 from webkitpy.common.config import committers
 from webkitpy.common.net.credentials import Credentials
-from webkitpy.common.system.ospath import relpath
 from webkitpy.common.system.user import User
 from webkitpy.thirdparty.autoinstalled.mechanize import Browser
 from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup, SoupStrainer
 
 
+# FIXME: parse_bug_id should not be a free function.
 def parse_bug_id(message):
     if not message:
         return None
@@ -63,162 +66,6 @@ def timestamp():
     return datetime.now().strftime("%Y%m%d%H%M%S")
 
 
-class Attachment(object):
-
-    rollout_preamble = "ROLLOUT of r"
-
-    def __init__(self, attachment_dictionary, bug):
-        self._attachment_dictionary = attachment_dictionary
-        self._bug = bug
-        self._reviewer = None
-        self._committer = None
-
-    def _bugzilla(self):
-        return self._bug._bugzilla
-
-    def id(self):
-        return int(self._attachment_dictionary.get("id"))
-
-    def attacher_is_committer(self):
-        return self._bugzilla.committers.committer_by_email(
-            patch.attacher_email())
-
-    def attacher_email(self):
-        return self._attachment_dictionary.get("attacher_email")
-
-    def bug(self):
-        return self._bug
-
-    def bug_id(self):
-        return int(self._attachment_dictionary.get("bug_id"))
-
-    def is_patch(self):
-        return not not self._attachment_dictionary.get("is_patch")
-
-    def is_obsolete(self):
-        return not not self._attachment_dictionary.get("is_obsolete")
-
-    def is_rollout(self):
-        return self.name().startswith(self.rollout_preamble)
-
-    def name(self):
-        return self._attachment_dictionary.get("name")
-
-    def attach_date(self):
-        return self._attachment_dictionary.get("attach_date")
-
-    def review(self):
-        return self._attachment_dictionary.get("review")
-
-    def commit_queue(self):
-        return self._attachment_dictionary.get("commit-queue")
-
-    def url(self):
-        # FIXME: This should just return
-        # self._bugzilla().attachment_url_for_id(self.id()). scm_unittest.py
-        # depends on the current behavior.
-        return self._attachment_dictionary.get("url")
-
-    def contents(self):
-        # FIXME: We shouldn't be grabbing at _bugzilla.
-        return self._bug._bugzilla.fetch_attachment_contents(self.id())
-
-    def _validate_flag_value(self, flag):
-        email = self._attachment_dictionary.get("%s_email" % flag)
-        if not email:
-            return None
-        committer = getattr(self._bugzilla().committers,
-                            "%s_by_email" % flag)(email)
-        if committer:
-            return committer
-        log("Warning, attachment %s on bug %s has invalid %s (%s)" % (
-                 self._attachment_dictionary['id'],
-                 self._attachment_dictionary['bug_id'], flag, email))
-
-    def reviewer(self):
-        if not self._reviewer:
-            self._reviewer = self._validate_flag_value("reviewer")
-        return self._reviewer
-
-    def committer(self):
-        if not self._committer:
-            self._committer = self._validate_flag_value("committer")
-        return self._committer
-
-
-class Bug(object):
-    # FIXME: This class is kinda a hack for now.  It exists so we have one
-    # place to hold bug logic, even if much of the code deals with
-    # dictionaries still.
-
-    def __init__(self, bug_dictionary, bugzilla):
-        self.bug_dictionary = bug_dictionary
-        self._bugzilla = bugzilla
-
-    def id(self):
-        return self.bug_dictionary["id"]
-
-    def title(self):
-        return self.bug_dictionary["title"]
-
-    def assigned_to_email(self):
-        return self.bug_dictionary["assigned_to_email"]
-
-    # FIXME: This information should be stored in some sort of webkit_config.py instead of here.
-    unassigned_emails = frozenset([
-        "webkit-unassigned at lists.webkit.org",
-        "webkit-qt-unassigned at trolltech.com",
-    ])
-    def is_unassigned(self):
-        return self.assigned_to_email() in self.unassigned_emails
-
-    def status(self):
-        return self.bug_dictionary["bug_status"]
-
-    # Bugzilla has many status states we don't really use in WebKit:
-    # https://bugs.webkit.org/page.cgi?id=fields.html#status
-    _open_states = ["UNCONFIRMED", "NEW", "ASSIGNED", "REOPENED"]
-    _closed_states = ["RESOLVED", "VERIFIED", "CLOSED"]
-
-    def is_open(self):
-        return self.status() in self._open_states
-
-    def is_closed(self):
-        return not self.is_open()
-
-    # Rarely do we actually want obsolete attachments
-    def attachments(self, include_obsolete=False):
-        attachments = self.bug_dictionary["attachments"]
-        if not include_obsolete:
-            attachments = filter(lambda attachment:
-                                 not attachment["is_obsolete"], attachments)
-        return [Attachment(attachment, self) for attachment in attachments]
-
-    def patches(self, include_obsolete=False):
-        return [patch for patch in self.attachments(include_obsolete)
-                                   if patch.is_patch()]
-
-    def unreviewed_patches(self):
-        return [patch for patch in self.patches() if patch.review() == "?"]
-
-    def reviewed_patches(self, include_invalid=False):
-        patches = [patch for patch in self.patches() if patch.review() == "+"]
-        if include_invalid:
-            return patches
-        # Checking reviewer() ensures that it was both reviewed and has a valid
-        # reviewer.
-        return filter(lambda patch: patch.reviewer(), patches)
-
-    def commit_queued_patches(self, include_invalid=False):
-        patches = [patch for patch in self.patches()
-                                      if patch.commit_queue() == "+"]
-        if include_invalid:
-            return patches
-        # Checking committer() ensures that it was both commit-queue+'d and has
-        # a valid committer.
-        return filter(lambda patch: patch.committer(), patches)
-
-
 # A container for all of the logic for making and parsing buzilla queries.
 class BugzillaQueries(object):
 
@@ -298,92 +145,6 @@ class BugzillaQueries(object):
         return self._fetch_attachment_ids_request_query(review_queue_url)
 
 
-class CommitterValidator(object):
-
-    def __init__(self, bugzilla):
-        self._bugzilla = bugzilla
-
-    # _view_source_url belongs in some sort of webkit_config.py module.
-    def _view_source_url(self, local_path):
-        return "http://trac.webkit.org/browser/trunk/%s" % local_path
-
-    def _checkout_root(self):
-        # FIXME: This is a hack, we would have this from scm.checkout_root
-        # if we had any way to get to an scm object here.
-        components = __file__.split(os.sep)
-        tools_index = components.index("WebKitTools")
-        return os.sep.join(components[:tools_index])
-
-    def _committers_py_path(self):
-        # extension can sometimes be .pyc, we always want .py
-        (path, extension) = os.path.splitext(committers.__file__)
-        # FIXME: When we're allowed to use python 2.6 we can use the real
-        # os.path.relpath
-        path = relpath(path, self._checkout_root())
-        return ".".join([path, "py"])
-
-    def _flag_permission_rejection_message(self, setter_email, flag_name):
-        # Should come from some webkit_config.py
-        contribution_guidlines = "http://webkit.org/coding/contributing.html"
-        # This could be queried from the status_server.
-        queue_administrator = "eseidel at chromium.org"
-        # This could be queried from the tool.
-        queue_name = "commit-queue"
-        committers_list = self._committers_py_path()
-        message = "%s does not have %s permissions according to %s." % (
-                        setter_email,
-                        flag_name,
-                        self._view_source_url(committers_list))
-        message += "\n\n- If you do not have %s rights please read %s for instructions on how to use bugzilla flags." % (
-                        flag_name, contribution_guidlines)
-        message += "\n\n- If you have %s rights please correct the error in %s by adding yourself to the file (no review needed).  " % (
-                        flag_name, committers_list)
-        message += "The %s restarts itself every 2 hours.  After restart the %s will correctly respect your %s rights." % (
-                        queue_name, queue_name, flag_name)
-        return message
-
-    def _validate_setter_email(self, patch, result_key, rejection_function):
-        committer = getattr(patch, result_key)()
-        # If the flag is set, and we don't recognize the setter, reject the
-        # flag!
-        setter_email = patch._attachment_dictionary.get("%s_email" % result_key)
-        if setter_email and not committer:
-            rejection_function(patch.id(),
-                self._flag_permission_rejection_message(setter_email,
-                                                        result_key))
-            return False
-        return True
-
-    def _reject_patch_if_flags_are_invalid(self, patch):
-        return (self._validate_setter_email(
-                patch, "reviewer", self.reject_patch_from_review_queue)
-            and self._validate_setter_email(
-                patch, "committer", self.reject_patch_from_commit_queue))
-
-    def patches_after_rejecting_invalid_commiters_and_reviewers(self, patches):
-        return [patch for patch in patches if self._reject_patch_if_flags_are_invalid(patch)]
-
-    def reject_patch_from_commit_queue(self,
-                                       attachment_id,
-                                       additional_comment_text=None):
-        comment_text = "Rejecting patch %s from commit-queue." % attachment_id
-        self._bugzilla.set_flag_on_attachment(attachment_id,
-                                              "commit-queue",
-                                              "-",
-                                              comment_text,
-                                              additional_comment_text)
-
-    def reject_patch_from_review_queue(self,
-                                       attachment_id,
-                                       additional_comment_text=None):
-        comment_text = "Rejecting patch %s from review queue." % attachment_id
-        self._bugzilla.set_flag_on_attachment(attachment_id,
-                                              'review',
-                                              '-',
-                                              comment_text,
-                                              additional_comment_text)
-
-
 class Bugzilla(object):
 
     def __init__(self, dryrun=False, committers=committers.CommitterList()):
diff --git a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py
index df1fcf6..c476c81 100644
--- a/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py
+++ b/WebKitTools/Scripts/webkitpy/common/net/bugzilla/bugzilla_unittest.py
@@ -27,38 +27,16 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import unittest
-
 import datetime
 
-from webkitpy.common.config.committers import CommitterList, Reviewer, Committer
-from webkitpy.common.net.bugzilla import Bugzilla, BugzillaQueries, parse_bug_id, CommitterValidator, Bug
+from .bugzilla import Bugzilla, BugzillaQueries, parse_bug_id
+
 from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.tool.mocktool import MockBrowser
 from webkitpy.thirdparty.mock import Mock
 from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
 
 
-class BugTest(unittest.TestCase):
-    def test_is_unassigned(self):
-        for email in Bug.unassigned_emails:
-            bug = Bug({"assigned_to_email" : email}, bugzilla=None)
-            self.assertTrue(bug.is_unassigned())
-        bug = Bug({"assigned_to_email" : "test at test.com"}, bugzilla=None)
-        self.assertFalse(bug.is_unassigned())
-
-
-class CommitterValidatorTest(unittest.TestCase):
-    def test_flag_permission_rejection_message(self):
-        validator = CommitterValidator(bugzilla=None)
-        self.assertEqual(validator._committers_py_path(), "WebKitTools/Scripts/webkitpy/common/config/committers.py")
-        expected_messsage="""foo at foo.com does not have review permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py.
-
-- If you do not have review rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.
-
-- If you have review rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed).  The commit-queue restarts itself every 2 hours.  After restart the commit-queue will correctly respect your review rights."""
-        self.assertEqual(validator._flag_permission_rejection_message("foo at foo.com", "review"), expected_messsage)
-
-
 class BugzillaTest(unittest.TestCase):
     _example_attachment = '''
         <attachment
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py
index dc892a4..046c4c1 100644
--- a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py
+++ b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py
@@ -26,8 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+from webkitpy.common.config.committervalidator import CommitterValidator
 from webkitpy.common.system.deprecated_logging import log
-from webkitpy.common.net.bugzilla import CommitterValidator
 from webkitpy.tool.grammar import pluralize
 
 
diff --git a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py
index 9d01477..bfaeb08 100644
--- a/WebKitTools/Scripts/webkitpy/tool/commands/queues.py
+++ b/WebKitTools/Scripts/webkitpy/tool/commands/queues.py
@@ -38,7 +38,8 @@ from datetime import datetime
 from optparse import make_option
 from StringIO import StringIO
 
-from webkitpy.common.net.bugzilla import CommitterValidator, Attachment
+from webkitpy.common.config.committervalidator import CommitterValidator
+from webkitpy.common.net.bugzilla import Attachment
 from webkitpy.common.net.layouttestresults import path_for_layout_test, LayoutTestResults
 from webkitpy.common.net.statusserver import StatusServer
 from webkitpy.common.system.deprecated_logging import error, log

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list