[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

abarth at webkit.org abarth at webkit.org
Wed Apr 7 23:51:42 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit a17b0052a4029db730db23a544158e5392446f54
Author: abarth at webkit.org <abarth at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Nov 20 14:54:34 2009 +0000

    2009-11-20  Eric Seidel  <eric at webkit.org>
    
            Reviewed by Adam Barth.
    
            MultiCommandTool should find Command objects automatically instead of with a manual list
            https://bugs.webkit.org/show_bug.cgi?id=31710
    
            * Scripts/bugzilla-tool:
            * Scripts/modules/multicommandtool.py:
             - Use some wild python-fu to crawl all the known subclasses of Command.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51237 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 371b8ac..9394467 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,14 @@
+2009-11-20  Eric Seidel  <eric at webkit.org>
+
+        Reviewed by Adam Barth.
+
+        MultiCommandTool should find Command objects automatically instead of with a manual list
+        https://bugs.webkit.org/show_bug.cgi?id=31710
+
+        * Scripts/bugzilla-tool:
+        * Scripts/modules/multicommandtool.py:
+         - Use some wild python-fu to crawl all the known subclasses of Command.
+
 2009-11-20  Adam Barth  <abarth at webkit.org>
 
         Unreviewed "build" fix.  Added missing import.
diff --git a/WebKitTools/Scripts/bugzilla-tool b/WebKitTools/Scripts/bugzilla-tool
index 335c15a..6cfecbe 100755
--- a/WebKitTools/Scripts/bugzilla-tool
+++ b/WebKitTools/Scripts/bugzilla-tool
@@ -69,6 +69,7 @@ def pluralize(noun, count):
 
 
 class BugsToCommit(Command):
+    name = "bugs-to-commit"
     def __init__(self):
         Command.__init__(self, "Bugs in the commit queue")
 
@@ -79,6 +80,7 @@ class BugsToCommit(Command):
 
 
 class PatchesToCommit(Command):
+    name = "patches-to-commit"
     def __init__(self):
         Command.__init__(self, "Patches in the commit queue")
 
@@ -90,8 +92,9 @@ class PatchesToCommit(Command):
 
 
 class ReviewedPatches(Command):
+    name = "reviewed-patches"
     def __init__(self):
-        Command.__init__(self, "r+\'d patches on a bug", "BUGID")
+        Command.__init__(self, "r+'d patches on a bug", "BUGID")
 
     def execute(self, options, args, tool):
         bug_id = args[0]
@@ -101,6 +104,7 @@ class ReviewedPatches(Command):
 
 
 class CheckStyle(Command):
+    name = "check-style"
     def __init__(self):
         options = WebKitLandingScripts.cleaning_options()
         Command.__init__(self, "Runs check-webkit-style on the specified attachment", "ATTACHMENT_ID", options=options)
@@ -130,6 +134,7 @@ class CheckStyle(Command):
 
 
 class ApplyAttachment(Command):
+    name = "apply-attachment"
     def __init__(self):
         options = WebKitApplyingScripts.apply_options() + WebKitLandingScripts.cleaning_options()
         Command.__init__(self, "Applies an attachment to the local working directory.", "ATTACHMENT_ID", options=options)
@@ -142,6 +147,7 @@ class ApplyAttachment(Command):
 
 
 class ApplyPatches(Command):
+    name = "apply-patches"
     def __init__(self):
         options = WebKitApplyingScripts.apply_options() + WebKitLandingScripts.cleaning_options()
         Command.__init__(self, "Applies all patches on a bug to the local working directory.", "BUGID", options=options)
@@ -210,6 +216,7 @@ class LandDiffLandingSequence(ConditionalLandingSequence):
 
 
 class LandDiff(Command):
+    name = "land-diff"
     def __init__(self):
         options = [
             make_option("-r", "--reviewer", action="store", type="string", dest="reviewer", help="Update ChangeLogs to say Reviewed by REVIEWER."),
@@ -259,8 +266,8 @@ class LandDiff(Command):
 
 
 class AbstractPatchProcessingCommand(Command):
-    def __init__(self, description, args_description, options):
-        Command.__init__(self, description, args_description, options=options)
+    def __init__(self, help_text, args_description, options):
+        Command.__init__(self, help_text, args_description, options=options)
 
     def _fetch_list_of_patches_to_process(self, options, args, tool):
         raise NotImplementedError, "subclasses must implement"
@@ -292,9 +299,9 @@ class AbstractPatchProcessingCommand(Command):
 
 
 class AbstractPatchLandingCommand(AbstractPatchProcessingCommand):
-    def __init__(self, description, args_description):
+    def __init__(self, help_text, args_description):
         options = WebKitLandingScripts.cleaning_options() + WebKitLandingScripts.land_options()
-        AbstractPatchProcessingCommand.__init__(self, description, args_description, options)
+        AbstractPatchProcessingCommand.__init__(self, help_text, args_description, options)
 
     def _prepare_to_process(self, options, args, tool):
         # Check the tree status first so we can fail early.
@@ -306,6 +313,7 @@ class AbstractPatchLandingCommand(AbstractPatchProcessingCommand):
         sequence.run_and_handle_errors()
 
 class LandAttachment(AbstractPatchLandingCommand):
+    name = "land-attachment"
     def __init__(self):
         AbstractPatchLandingCommand.__init__(self, "Lands a patches from bugzilla, optionally building and testing them first", "ATTACHMENT_ID [ATTACHMENT_IDS]")
 
@@ -314,6 +322,7 @@ class LandAttachment(AbstractPatchLandingCommand):
 
 
 class LandPatches(AbstractPatchLandingCommand):
+    name = "land-patches"
     def __init__(self):
         AbstractPatchLandingCommand.__init__(self, "Lands all patches on the given bugs, optionally building and testing them first", "BUGID [BUGIDS]")
 
@@ -327,6 +336,7 @@ class LandPatches(AbstractPatchLandingCommand):
 
 
 class CommitMessageForCurrentDiff(Command):
+    name = "commit-message"
     def __init__(self):
         Command.__init__(self, "Prints a commit message suitable for the uncommitted changes.")
 
@@ -336,6 +346,7 @@ class CommitMessageForCurrentDiff(Command):
 
 
 class ObsoleteAttachments(Command):
+    name = "obsolete-attachments"
     def __init__(self):
         Command.__init__(self, "Marks all attachments on a bug as obsolete.", "BUGID")
 
@@ -348,6 +359,7 @@ class ObsoleteAttachments(Command):
 
 
 class PostDiff(Command):
+    name = "post-diff"
     def __init__(self):
         options = [
             make_option("-m", "--description", action="store", type="string", dest="description", help="Description string for the attachment (default: \"patch\")"),
@@ -388,6 +400,7 @@ class PostDiff(Command):
 
 
 class PostCommits(Command):
+    name = "post-commits"
     def __init__(self):
         options = [
             make_option("-b", "--bug-id", action="store", type="string", dest="bug_id", help="Specify bug id if no URL is provided in the commit log."),
@@ -438,6 +451,7 @@ class PostCommits(Command):
 
 
 class Rollout(Command):
+    name = "rollout"
     def __init__(self):
         options = WebKitLandingScripts.land_options()
         options += WebKitLandingScripts.cleaning_options()
@@ -495,6 +509,7 @@ class Rollout(Command):
 
 
 class CreateBug(Command):
+    name = "create-bug"
     def __init__(self):
         options = [
             make_option("--cc", action="store", type="string", dest="cc", help="Comma-separated list of email addresses to carbon-copy."),
@@ -572,6 +587,7 @@ class CreateBug(Command):
 
 
 class TreeStatus(Command):
+    name = "tree-status"
     def __init__(self):
         Command.__init__(self, "Print out the status of the webkit builders.")
 
@@ -700,28 +716,7 @@ class BugzillaTool(MultiCommandTool):
         # This hack can be removed by overriding usage() printing in HelpPrintingOptionParser
         # so that we don't need to create 'epilog' before constructing HelpPrintingOptionParser.
         self.cached_scm = None
-        
-        # FIXME: Commands should know their own name and register themselves with the BugzillaTool instead of having a manual list.
-        MultiCommandTool.__init__(self, commands=[
-            { "name" : "bugs-to-commit", "object" : BugsToCommit() },
-            { "name" : "patches-to-commit", "object" : PatchesToCommit() },
-            { "name" : "reviewed-patches", "object" : ReviewedPatches() },
-            { "name" : "create-bug", "object" : CreateBug() },
-            { "name" : "apply-attachment", "object" : ApplyAttachment() },
-            { "name" : "apply-patches", "object" : ApplyPatches() },
-            { "name" : "land-diff", "object" : LandDiff() },
-            { "name" : "land-attachment", "object" : LandAttachment() },
-            { "name" : "land-patches", "object" : LandPatches() },
-            { "name" : "check-style", "object" : CheckStyle() },
-            { "name" : "commit-message", "object" : CommitMessageForCurrentDiff() },
-            { "name" : "obsolete-attachments", "object" : ObsoleteAttachments() },
-            { "name" : "post-diff", "object" : PostDiff() },
-            { "name" : "post-commits", "object" : PostCommits() },
-            { "name" : "tree-status", "object" : TreeStatus() },
-            { "name" : "commit-queue", "object" : CommitQueue() },
-            { "name" : "style-queue", "object" : StyleQueue() },
-            { "name" : "rollout", "object" : Rollout() },
-        ])
+        MultiCommandTool.__init__(self)
         self.global_option_parser.add_option("--dry-run", action="callback", help="do not touch remote servers", callback=self.dry_run_callback)
 
         self.bugs = Bugzilla()
@@ -749,13 +744,13 @@ class BugzillaTool(MultiCommandTool):
         return self.cached_scm
 
     def should_show_command_help(self, command):
-        if command["object"].requires_local_commits:
+        if command.requires_local_commits:
             return self.scm().supports_local_commits()
         return True
 
     def should_execute_command(self, command):
-        if command["object"].requires_local_commits and not self.scm().supports_local_commits():
-            failure_reason = "%s requires local commits using %s in %s." % (command["name"], self.scm().display_name(), self.scm().checkout_root)
+        if command.requires_local_commits and not self.scm().supports_local_commits():
+            failure_reason = "%s requires local commits using %s in %s." % (command.name, self.scm().display_name(), self.scm().checkout_root)
             return (False, failure_reason)
         return (True, None)
 
diff --git a/WebKitTools/Scripts/modules/multicommandtool.py b/WebKitTools/Scripts/modules/multicommandtool.py
index 4baad51..5692404 100644
--- a/WebKitTools/Scripts/modules/multicommandtool.py
+++ b/WebKitTools/Scripts/modules/multicommandtool.py
@@ -37,7 +37,8 @@ from optparse import OptionParser, IndentedHelpFormatter, SUPPRESS_USAGE, make_o
 
 from modules.logging import log
 
-class Command:
+class Command(object):
+    name = None
     def __init__(self, help_text, argument_names=None, options=None, requires_local_commits=False):
         self.help_text = help_text
         self.argument_names = argument_names
@@ -45,8 +46,8 @@ class Command:
         self.option_parser = HelpPrintingOptionParser(usage=SUPPRESS_USAGE, add_help_option=False, option_list=self.options)
         self.requires_local_commits = requires_local_commits
 
-    def name_with_arguments(self, command_name):
-        usage_string = command_name
+    def name_with_arguments(self):
+        usage_string = self.name
         if self.options:
             usage_string += " [options]"
         if self.argument_names:
@@ -59,7 +60,6 @@ class Command:
     def execute(self, options, args, tool):
         raise NotImplementedError, "subclasses must implement"
 
-
 class NonWrappingEpilogIndentedHelpFormatter(IndentedHelpFormatter):
     # The standard IndentedHelpFormatter paragraph-wraps the epilog, killing our custom formatting.
     def format_epilog(self, epilog):
@@ -76,23 +76,31 @@ class HelpPrintingOptionParser(OptionParser):
         self.exit(1, error_message)
 
 
-class MultiCommandTool:
-    def __init__(self, commands):
-        self.commands = commands
+class MultiCommandTool(object):
+    def __init__(self):
+        self.commands = [cls() for cls in self._find_all_commands() if cls.name]
         # FIXME: Calling self._commands_usage() in the constructor is bad because
         # it calls self.should_show_command_help which is subclass-defined.
         # The subclass will not be fully initialized at this point.
         self.global_option_parser = HelpPrintingOptionParser(usage=self._usage_line(), formatter=NonWrappingEpilogIndentedHelpFormatter(), epilog=self._commands_usage())
 
+    @classmethod
+    def _add_all_subclasses(cls, class_to_crawl, seen_classes):
+        for subclass in class_to_crawl.__subclasses__():
+            if subclass not in seen_classes:
+                seen_classes.add(subclass)
+                cls._add_all_subclasses(subclass, seen_classes)
+
+    @classmethod
+    def _find_all_commands(cls):
+        commands = set()
+        cls._add_all_subclasses(Command, commands)
+        return sorted(commands)
+
     @staticmethod
     def _usage_line():
         return "Usage: %prog [options] command [command-options] [command-arguments]"
 
-    # FIXME: This can all be simplified once Command objects know their own names.
-    @staticmethod
-    def _name_and_arguments(command):
-        return command['object'].name_with_arguments(command["name"])
-
     def _command_help_formatter(self):
         # Use our own help formatter so as to indent enough.
         formatter = IndentedHelpFormatter()
@@ -102,18 +110,18 @@ class MultiCommandTool:
 
     @classmethod
     def _help_for_command(cls, command, formatter, longest_name_length):
-        help_text = "  " + cls._name_and_arguments(command).ljust(longest_name_length + 3) + command['object'].help_text + "\n"
-        help_text += command['object'].option_parser.format_option_help(formatter)
+        help_text = "  " + command.name_with_arguments().ljust(longest_name_length + 3) + command.help_text + "\n"
+        help_text += command.option_parser.format_option_help(formatter)
         return help_text
 
     @classmethod
     def _standalone_help_for_command(cls, command):
-        return cls._help_for_command(command, IndentedHelpFormatter(), len(cls._name_and_arguments(command)))
+        return cls._help_for_command(command, IndentedHelpFormatter(), len(command.name_with_arguments()))
 
     def _commands_usage(self):
         # Only show commands which are relevant to this checkout.  This might be confusing to some users?
         relevant_commands = filter(self.should_show_command_help, self.commands)
-        longest_name_length = max(map(lambda command: len(self._name_and_arguments(command)), relevant_commands))
+        longest_name_length = max(map(lambda command: len(command.name_with_arguments()), relevant_commands))
         command_help_texts = map(lambda command: self._help_for_command(command, self._command_help_formatter(), longest_name_length), relevant_commands)
         return "Commands:\n" + "".join(command_help_texts)
 
@@ -141,7 +149,7 @@ class MultiCommandTool:
 
     def command_by_name(self, command_name):
         for command in self.commands:
-            if command_name == command["name"]:
+            if command_name == command.name:
                 return command
         return None
 
@@ -178,6 +186,5 @@ class MultiCommandTool:
             log(failure_reason)
             return 0
 
-        command_object = command["object"]
-        (command_options, command_args) = command_object.parse_args(args_after_command_name)
-        return command_object.execute(command_options, command_args, self)
+        (command_options, command_args) = command.parse_args(args_after_command_name)
+        return command.execute(command_options, command_args, self)

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list