Changeset 51237 in webkit
- Timestamp:
- Nov 20, 2009 6:54:34 AM (14 years ago)
- Location:
- trunk/WebKitTools
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebKitTools/ChangeLog
r51236 r51237 1 2009-11-20 Eric Seidel <eric@webkit.org> 2 3 Reviewed by Adam Barth. 4 5 MultiCommandTool should find Command objects automatically instead of with a manual list 6 https://bugs.webkit.org/show_bug.cgi?id=31710 7 8 * Scripts/bugzilla-tool: 9 * Scripts/modules/multicommandtool.py: 10 - Use some wild python-fu to crawl all the known subclasses of Command. 11 1 12 2009-11-20 Adam Barth <abarth@webkit.org> 2 13 -
trunk/WebKitTools/Scripts/bugzilla-tool
r51236 r51237 70 70 71 71 class BugsToCommit(Command): 72 name = "bugs-to-commit" 72 73 def __init__(self): 73 74 Command.__init__(self, "Bugs in the commit queue") … … 80 81 81 82 class PatchesToCommit(Command): 83 name = "patches-to-commit" 82 84 def __init__(self): 83 85 Command.__init__(self, "Patches in the commit queue") … … 91 93 92 94 class ReviewedPatches(Command): 93 def __init__(self): 94 Command.__init__(self, "r+\'d patches on a bug", "BUGID") 95 name = "reviewed-patches" 96 def __init__(self): 97 Command.__init__(self, "r+'d patches on a bug", "BUGID") 95 98 96 99 def execute(self, options, args, tool): … … 102 105 103 106 class CheckStyle(Command): 107 name = "check-style" 104 108 def __init__(self): 105 109 options = WebKitLandingScripts.cleaning_options() … … 131 135 132 136 class ApplyAttachment(Command): 137 name = "apply-attachment" 133 138 def __init__(self): 134 139 options = WebKitApplyingScripts.apply_options() + WebKitLandingScripts.cleaning_options() … … 143 148 144 149 class ApplyPatches(Command): 150 name = "apply-patches" 145 151 def __init__(self): 146 152 options = WebKitApplyingScripts.apply_options() + WebKitLandingScripts.cleaning_options() … … 211 217 212 218 class LandDiff(Command): 219 name = "land-diff" 213 220 def __init__(self): 214 221 options = [ … … 260 267 261 268 class AbstractPatchProcessingCommand(Command): 262 def __init__(self, description, args_description, options):263 Command.__init__(self, description, args_description, options=options)269 def __init__(self, help_text, args_description, options): 270 Command.__init__(self, help_text, args_description, options=options) 264 271 265 272 def _fetch_list_of_patches_to_process(self, options, args, tool): … … 293 300 294 301 class AbstractPatchLandingCommand(AbstractPatchProcessingCommand): 295 def __init__(self, description, args_description):302 def __init__(self, help_text, args_description): 296 303 options = WebKitLandingScripts.cleaning_options() + WebKitLandingScripts.land_options() 297 AbstractPatchProcessingCommand.__init__(self, description, args_description, options)304 AbstractPatchProcessingCommand.__init__(self, help_text, args_description, options) 298 305 299 306 def _prepare_to_process(self, options, args, tool): … … 307 314 308 315 class LandAttachment(AbstractPatchLandingCommand): 316 name = "land-attachment" 309 317 def __init__(self): 310 318 AbstractPatchLandingCommand.__init__(self, "Lands a patches from bugzilla, optionally building and testing them first", "ATTACHMENT_ID [ATTACHMENT_IDS]") … … 315 323 316 324 class LandPatches(AbstractPatchLandingCommand): 325 name = "land-patches" 317 326 def __init__(self): 318 327 AbstractPatchLandingCommand.__init__(self, "Lands all patches on the given bugs, optionally building and testing them first", "BUGID [BUGIDS]") … … 328 337 329 338 class CommitMessageForCurrentDiff(Command): 339 name = "commit-message" 330 340 def __init__(self): 331 341 Command.__init__(self, "Prints a commit message suitable for the uncommitted changes.") … … 337 347 338 348 class ObsoleteAttachments(Command): 349 name = "obsolete-attachments" 339 350 def __init__(self): 340 351 Command.__init__(self, "Marks all attachments on a bug as obsolete.", "BUGID") … … 349 360 350 361 class PostDiff(Command): 362 name = "post-diff" 351 363 def __init__(self): 352 364 options = [ … … 389 401 390 402 class PostCommits(Command): 403 name = "post-commits" 391 404 def __init__(self): 392 405 options = [ … … 439 452 440 453 class Rollout(Command): 454 name = "rollout" 441 455 def __init__(self): 442 456 options = WebKitLandingScripts.land_options() … … 496 510 497 511 class CreateBug(Command): 512 name = "create-bug" 498 513 def __init__(self): 499 514 options = [ … … 573 588 574 589 class TreeStatus(Command): 590 name = "tree-status" 575 591 def __init__(self): 576 592 Command.__init__(self, "Print out the status of the webkit builders.") … … 701 717 # so that we don't need to create 'epilog' before constructing HelpPrintingOptionParser. 702 718 self.cached_scm = None 703 704 # FIXME: Commands should know their own name and register themselves with the BugzillaTool instead of having a manual list. 705 MultiCommandTool.__init__(self, commands=[ 706 { "name" : "bugs-to-commit", "object" : BugsToCommit() }, 707 { "name" : "patches-to-commit", "object" : PatchesToCommit() }, 708 { "name" : "reviewed-patches", "object" : ReviewedPatches() }, 709 { "name" : "create-bug", "object" : CreateBug() }, 710 { "name" : "apply-attachment", "object" : ApplyAttachment() }, 711 { "name" : "apply-patches", "object" : ApplyPatches() }, 712 { "name" : "land-diff", "object" : LandDiff() }, 713 { "name" : "land-attachment", "object" : LandAttachment() }, 714 { "name" : "land-patches", "object" : LandPatches() }, 715 { "name" : "check-style", "object" : CheckStyle() }, 716 { "name" : "commit-message", "object" : CommitMessageForCurrentDiff() }, 717 { "name" : "obsolete-attachments", "object" : ObsoleteAttachments() }, 718 { "name" : "post-diff", "object" : PostDiff() }, 719 { "name" : "post-commits", "object" : PostCommits() }, 720 { "name" : "tree-status", "object" : TreeStatus() }, 721 { "name" : "commit-queue", "object" : CommitQueue() }, 722 { "name" : "style-queue", "object" : StyleQueue() }, 723 { "name" : "rollout", "object" : Rollout() }, 724 ]) 719 MultiCommandTool.__init__(self) 725 720 self.global_option_parser.add_option("--dry-run", action="callback", help="do not touch remote servers", callback=self.dry_run_callback) 726 721 … … 750 745 751 746 def should_show_command_help(self, command): 752 if command ["object"].requires_local_commits:747 if command.requires_local_commits: 753 748 return self.scm().supports_local_commits() 754 749 return True 755 750 756 751 def should_execute_command(self, command): 757 if command ["object"].requires_local_commits and not self.scm().supports_local_commits():758 failure_reason = "%s requires local commits using %s in %s." % (command ["name"], self.scm().display_name(), self.scm().checkout_root)752 if command.requires_local_commits and not self.scm().supports_local_commits(): 753 failure_reason = "%s requires local commits using %s in %s." % (command.name, self.scm().display_name(), self.scm().checkout_root) 759 754 return (False, failure_reason) 760 755 return (True, None) -
trunk/WebKitTools/Scripts/modules/multicommandtool.py
r51226 r51237 38 38 from modules.logging import log 39 39 40 class Command: 40 class Command(object): 41 name = None 41 42 def __init__(self, help_text, argument_names=None, options=None, requires_local_commits=False): 42 43 self.help_text = help_text … … 46 47 self.requires_local_commits = requires_local_commits 47 48 48 def name_with_arguments(self , command_name):49 usage_string = command_name49 def name_with_arguments(self): 50 usage_string = self.name 50 51 if self.options: 51 52 usage_string += " [options]" … … 59 60 def execute(self, options, args, tool): 60 61 raise NotImplementedError, "subclasses must implement" 61 62 62 63 63 class NonWrappingEpilogIndentedHelpFormatter(IndentedHelpFormatter): … … 77 77 78 78 79 class MultiCommandTool :80 def __init__(self , commands):81 self.commands = commands79 class MultiCommandTool(object): 80 def __init__(self): 81 self.commands = [cls() for cls in self._find_all_commands() if cls.name] 82 82 # FIXME: Calling self._commands_usage() in the constructor is bad because 83 83 # it calls self.should_show_command_help which is subclass-defined. … … 85 85 self.global_option_parser = HelpPrintingOptionParser(usage=self._usage_line(), formatter=NonWrappingEpilogIndentedHelpFormatter(), epilog=self._commands_usage()) 86 86 87 @classmethod 88 def _add_all_subclasses(cls, class_to_crawl, seen_classes): 89 for subclass in class_to_crawl.__subclasses__(): 90 if subclass not in seen_classes: 91 seen_classes.add(subclass) 92 cls._add_all_subclasses(subclass, seen_classes) 93 94 @classmethod 95 def _find_all_commands(cls): 96 commands = set() 97 cls._add_all_subclasses(Command, commands) 98 return sorted(commands) 99 87 100 @staticmethod 88 101 def _usage_line(): 89 102 return "Usage: %prog [options] command [command-options] [command-arguments]" 90 91 # FIXME: This can all be simplified once Command objects know their own names.92 @staticmethod93 def _name_and_arguments(command):94 return command['object'].name_with_arguments(command["name"])95 103 96 104 def _command_help_formatter(self): … … 103 111 @classmethod 104 112 def _help_for_command(cls, command, formatter, longest_name_length): 105 help_text = " " + c ls._name_and_arguments(command).ljust(longest_name_length + 3) + command['object'].help_text + "\n"106 help_text += command ['object'].option_parser.format_option_help(formatter)113 help_text = " " + command.name_with_arguments().ljust(longest_name_length + 3) + command.help_text + "\n" 114 help_text += command.option_parser.format_option_help(formatter) 107 115 return help_text 108 116 109 117 @classmethod 110 118 def _standalone_help_for_command(cls, command): 111 return cls._help_for_command(command, IndentedHelpFormatter(), len(c ls._name_and_arguments(command)))119 return cls._help_for_command(command, IndentedHelpFormatter(), len(command.name_with_arguments())) 112 120 113 121 def _commands_usage(self): 114 122 # Only show commands which are relevant to this checkout. This might be confusing to some users? 115 123 relevant_commands = filter(self.should_show_command_help, self.commands) 116 longest_name_length = max(map(lambda command: len( self._name_and_arguments(command)), relevant_commands))124 longest_name_length = max(map(lambda command: len(command.name_with_arguments()), relevant_commands)) 117 125 command_help_texts = map(lambda command: self._help_for_command(command, self._command_help_formatter(), longest_name_length), relevant_commands) 118 126 return "Commands:\n" + "".join(command_help_texts) … … 142 150 def command_by_name(self, command_name): 143 151 for command in self.commands: 144 if command_name == command ["name"]:152 if command_name == command.name: 145 153 return command 146 154 return None … … 179 187 return 0 180 188 181 command_object = command["object"] 182 (command_options, command_args) = command_object.parse_args(args_after_command_name) 183 return command_object.execute(command_options, command_args, self) 189 (command_options, command_args) = command.parse_args(args_after_command_name) 190 return command.execute(command_options, command_args, self)
Note: See TracChangeset
for help on using the changeset viewer.