watchlist: Add support for cc and message rules.
authorlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Sep 2011 23:42:12 +0000 (23:42 +0000)
committerlevin@chromium.org <levin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Sep 2011 23:42:12 +0000 (23:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=68950

Reviewed by Adam Barth.

* Scripts/webkitpy/common/watchlist/watchlist.py: Added support to get
the cc's and messages for a patch.
* Scripts/webkitpy/common/watchlist/watchlist_unittest.py: Tests for the above.
* Scripts/webkitpy/common/watchlist/watchlistparser.py: Parsing support
for the rules.
* Scripts/webkitpy/common/watchlist/watchlistrule.py: Copied from Tools/Scripts/webkitpy/common/watchlist/watchlist.py.
A generic encapsulation of either a message list or a cc list.
* Scripts/webkitpy/common/watchlist/watchlistrule_unittest.py: Copied from Tools/Scripts/webkitpy/common/watchlist/watchlist.py.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96170 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/common/watchlist/watchlist.py
Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py
Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py
Tools/Scripts/webkitpy/common/watchlist/watchlistrule.py [new file with mode: 0644]
Tools/Scripts/webkitpy/common/watchlist/watchlistrule_unittest.py [new file with mode: 0644]

index f3d6ff3..c349e4a 100644 (file)
@@ -1,3 +1,19 @@
+2011-09-27  David Levin  <levin@chromium.org>
+
+        watchlist: Add support for cc and message rules.
+        https://bugs.webkit.org/show_bug.cgi?id=68950
+
+        Reviewed by Adam Barth.
+
+        * Scripts/webkitpy/common/watchlist/watchlist.py: Added support to get
+        the cc's and messages for a patch.
+        * Scripts/webkitpy/common/watchlist/watchlist_unittest.py: Tests for the above.
+        * Scripts/webkitpy/common/watchlist/watchlistparser.py: Parsing support
+        for the rules.
+        * Scripts/webkitpy/common/watchlist/watchlistrule.py: Copied from Tools/Scripts/webkitpy/common/watchlist/watchlist.py.
+        A generic encapsulation of either a message list or a cc list.
+        * Scripts/webkitpy/common/watchlist/watchlistrule_unittest.py: Copied from Tools/Scripts/webkitpy/common/watchlist/watchlist.py.
+
 2011-09-27  Tom Zakrajsek  <tomz@codeaurora.org>
 
         webkit-patch doesn't like UTF-8 characters in reviewers names
index fc31972..c000dfb 100644 (file)
 
 from webkitpy.common.checkout.diff_parser import DiffParser
 
+
 class WatchList(object):
     def __init__(self):
         self._definitions = {}
+        self._cc_rules = set()
+        self._message_rules = set()
 
     def set_definitions(self, definitions):
         self._definitions = definitions
 
+    def set_cc_rules(self, cc_rules):
+        self._cc_rules = cc_rules
+
+    def set_message_rules(self, message_rules):
+        self._message_rules = message_rules
+
     def find_matching_definitions(self, diff):
         matching_definitions = set()
         patch_files = DiffParser(diff.splitlines()).files
@@ -52,3 +61,23 @@ class WatchList(object):
                 else:
                     matching_definitions.add(definition)
         return matching_definitions
+
+    def _determine_instructions(self, matching_definitions, rules):
+        instructions = set()
+        for rule in rules:
+            if rule.match(matching_definitions):
+                instructions.update(rule.instructions())
+        return instructions
+
+    def determine_cc_set(self, matching_definitions):
+        return self._determine_instructions(matching_definitions, self._cc_rules)
+
+    def determine_messages(self, matching_definitions):
+        return self._determine_instructions(matching_definitions, self._message_rules)
+
+    def determine_cc_set_and_messages(self, diff):
+        definitions = self.find_matching_definitions(diff)
+        return {
+            'cc_set': self.determine_cc_set(definitions),
+            'messages':  self.determine_messages(definitions),
+            }
index 2cb3bcd..f6e8be6 100644 (file)
@@ -34,7 +34,7 @@ from webkitpy.common.checkout.diff_test_data import DIFF_TEST_DATA
 from webkitpy.common.watchlist.watchlistparser import WatchListParser
 
 
-class WatchListParserTest(unittest.TestCase):
+class WatchListTest(unittest.TestCase):
     def setUp(self):
         self._watch_list_parser = WatchListParser()
 
@@ -59,3 +59,83 @@ class WatchListParserTest(unittest.TestCase):
             '     },'
             '}')
         self.assertEquals(set(['WatchList1']), watch_list.find_matching_definitions(DIFF_TEST_DATA))
+
+    def test_cc_rules_simple(self):
+        watch_list = self._watch_list_parser.parse(
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r"WebCore/rendering/style/StyleFlexibleBoxData\.h",'
+            '        },'
+            '     },'
+            '    "CC_RULES": {'
+            '        "WatchList1": ['
+            '            "levin@chromium.org",'
+            '        ],'
+           '    },'
+            '}')
+        cc_set_and_messages = watch_list.determine_cc_set_and_messages(DIFF_TEST_DATA)
+        self.assertEquals({
+                'cc_set': set(['levin@chromium.org']),
+                'messages': set(),
+                }, cc_set_and_messages)
+
+    def test_cc_rules_complex(self):
+        watch_list = self._watch_list_parser.parse(
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r"WebCore/rendering/style/StyleFlexibleBoxData\.h",'
+            '        },'
+            '     },'
+            '    "CC_RULES": {'
+            '        "WatchList2|WatchList1|WatchList3": [ "levin@chromium.org", ],'
+            '    },'
+            '}')
+        cc_set_and_messages = watch_list.determine_cc_set_and_messages(DIFF_TEST_DATA)
+        self.assertEquals({
+                'cc_set': set(['levin@chromium.org']),
+                'messages': set(),
+                }, cc_set_and_messages)
+
+    def test_cc_and_message_rules_complex(self):
+        watch_list = self._watch_list_parser.parse(
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r"WebCore/rendering/style/StyleFlexibleBoxData\.h",'
+            '        },'
+            '     },'
+            '    "CC_RULES": {'
+            '        "WatchList2|WatchList1|WatchList3": [ "levin@chromium.org", ],'
+            '    },'
+            '    "MESSAGE_RULES": {'
+            '        "WatchList2|WatchList1|WatchList3": [ "msg1", "msg2", ],'
+            '    },'
+            '}')
+        cc_set_and_messages = watch_list.determine_cc_set_and_messages(DIFF_TEST_DATA)
+        self.assertEquals({
+                'cc_set': set(['levin@chromium.org']),
+                'messages': set(['msg1', 'msg2']),
+                }, cc_set_and_messages)
+
+    def test_cc_and_message_rules_no_matches(self):
+        watch_list = self._watch_list_parser.parse(
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r"WebCore/rendering/style/ThisFileDoesNotExist\.h",'
+            '        },'
+            '     },'
+            '    "CC_RULES": {'
+            '        "WatchList2|WatchList1|WatchList3": [ "levin@chromium.org", ],'
+            '    },'
+            '    "MESSAGE_RULES": {'
+            '        "WatchList2|WatchList1|WatchList3": [ "msg1", "msg2", ],'
+            '    },'
+            '}')
+        cc_set_and_messages = watch_list.determine_cc_set_and_messages(DIFF_TEST_DATA)
+        self.assertEquals({
+                'cc_set': set(),
+                'messages': set(),
+                }, cc_set_and_messages)
index 846cabe..f3cc118 100644 (file)
 import re
 from webkitpy.common.watchlist.watchlist import WatchList
 from webkitpy.common.watchlist.filenamepattern import FilenamePattern
+from webkitpy.common.watchlist.watchlistrule import WatchListRule
 
 
 class WatchListParser(object):
     _DEFINITIONS = 'DEFINITIONS'
+    _CC_RULES = 'CC_RULES'
+    _MESSAGE_RULES = 'MESSAGE_RULES'
     _INVALID_DEFINITION_NAME_REGEX = r'\|'
 
     def __init__(self):
-        self._section_parsers = {self._DEFINITIONS: self._parse_definition_section, }
+        self._section_parsers = {
+            self._DEFINITIONS: self._parse_definition_section,
+            self._CC_RULES: self._parse_cc_rules,
+            self._MESSAGE_RULES: self._parse_message_rules,
+            }
         self._definition_pattern_parsers = {'filename': FilenamePattern, }
 
     def parse(self, watch_list_contents):
@@ -74,3 +81,15 @@ class WatchListParser(object):
                 pattern = pattern_parser(definition[pattern_type])
                 definitions[name].append(pattern)
         watch_list.set_definitions(definitions)
+
+    def _parse_rules(self, rules_section):
+        rules = []
+        for complex_definition in rules_section:
+            rules.append(WatchListRule(complex_definition, rules_section[complex_definition]))
+        return rules
+
+    def _parse_cc_rules(self, cc_section, watch_list):
+        watch_list.set_cc_rules(self._parse_rules(cc_section))
+
+    def _parse_message_rules(self, message_section, watch_list):
+        watch_list.set_message_rules(self._parse_rules(message_section))
diff --git a/Tools/Scripts/webkitpy/common/watchlist/watchlistrule.py b/Tools/Scripts/webkitpy/common/watchlist/watchlistrule.py
new file mode 100644 (file)
index 0000000..ac3ea3c
--- /dev/null
@@ -0,0 +1,43 @@
+# Copyright (C) 2011 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.
+
+
+class WatchListRule:
+    '''A rule with instructions to do when the rule is satisified.'''
+    def __init__(self, complex_definition, instructions):
+        self._definitions_to_match = complex_definition.split('|')
+        self._instructions = instructions
+
+    def match(self, matching_definitions):
+        for test_definition in self._definitions_to_match:
+            if test_definition in matching_definitions:
+                return True
+        return False
+
+    def instructions(self):
+        return self._instructions
diff --git a/Tools/Scripts/webkitpy/common/watchlist/watchlistrule_unittest.py b/Tools/Scripts/webkitpy/common/watchlist/watchlistrule_unittest.py
new file mode 100644 (file)
index 0000000..cb2985d
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (C) 2011 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+import unittest
+from webkitpy.common.watchlist.watchlistrule import WatchListRule
+
+
+class WatchListRuleTest(unittest.TestCase):
+    def test_action_list(self):
+        instructions = ['a', 'b']
+        rule = WatchListRule('definition1', instructions[:])
+        self.assertEqual(instructions, rule.instructions())
+
+    def test_simple_definition(self):
+        definition_name = 'definition1'
+        rule = WatchListRule(definition_name, [])
+        self.assertTrue(rule.match([definition_name]))
+        self.assertFalse(rule.match([definition_name + '1']))
+
+    def test_complex_definition(self):
+        definition_name1 = 'definition1'
+        definition_name2 = 'definition2'
+        definition_name3 = 'definition3'
+        rule = WatchListRule(definition_name1 + '|' + definition_name2 + '|' + definition_name3, [])
+        self.assertTrue(rule.match([definition_name1]))
+        self.assertTrue(rule.match([definition_name2]))
+        self.assertTrue(rule.match([definition_name3]))
+        self.assertFalse(rule.match([definition_name1 + '1']))
+        self.assertFalse(rule.match([definition_name2 + '1']))
+        self.assertFalse(rule.match([definition_name3 + '1']))