| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 the V8 project authors. All rights reserved. | 2 # Copyright 2013 the V8 project authors. All rights reserved. |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following | 10 # copyright notice, this list of conditions and the following |
| 11 # disclaimer in the documentation and/or other materials provided | 11 # disclaimer in the documentation and/or other materials provided |
| 12 # with the distribution. | 12 # with the distribution. |
| 13 # * Neither the name of Google Inc. nor the names of its | 13 # * Neither the name of Google Inc. nor the names of its |
| 14 # contributors may be used to endorse or promote products derived | 14 # contributors may be used to endorse or promote products derived |
| 15 # from this software without specific prior written permission. | 15 # from this software without specific prior written permission. |
| 16 # | 16 # |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 import argparse |
| 29 import datetime | 30 import datetime |
| 30 import json | 31 import json |
| 31 import os | 32 import os |
| 32 import re | 33 import re |
| 33 import subprocess | 34 import subprocess |
| 34 import sys | 35 import sys |
| 35 import textwrap | 36 import textwrap |
| 36 import time | 37 import time |
| 37 import urllib2 | 38 import urllib2 |
| 38 | 39 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 | 220 |
| 220 | 221 |
| 221 class NoRetryException(Exception): | 222 class NoRetryException(Exception): |
| 222 pass | 223 pass |
| 223 | 224 |
| 224 | 225 |
| 225 class GitFailedException(Exception): | 226 class GitFailedException(Exception): |
| 226 pass | 227 pass |
| 227 | 228 |
| 228 | 229 |
| 229 class CommonOptions(object): | |
| 230 def __init__(self, options, manual=True): | |
| 231 self.requires_editor = True | |
| 232 self.wait_for_lgtm = True | |
| 233 self.step = options.step | |
| 234 self.force_readline_defaults = not manual | |
| 235 self.force_upload = not manual | |
| 236 self.manual = manual | |
| 237 self.reviewer = getattr(options, 'reviewer', "") | |
| 238 self.author = getattr(options, 'author', "") | |
| 239 | |
| 240 | |
| 241 class Step(GitRecipesMixin): | 230 class Step(GitRecipesMixin): |
| 242 def __init__(self, text, requires, number, config, state, options, handler): | 231 def __init__(self, text, requires, number, config, state, options, handler): |
| 243 self._text = text | 232 self._text = text |
| 244 self._requires = requires | 233 self._requires = requires |
| 245 self._number = number | 234 self._number = number |
| 246 self._config = config | 235 self._config = config |
| 247 self._state = state | 236 self._state = state |
| 248 self._options = options | 237 self._options = options |
| 249 self._side_effect_handler = handler | 238 self._side_effect_handler = handler |
| 250 assert self._number >= 0 | 239 assert self._number >= 0 |
| 251 assert self._config is not None | 240 assert self._config is not None |
| 252 assert self._state is not None | 241 assert self._state is not None |
| 253 assert self._side_effect_handler is not None | 242 assert self._side_effect_handler is not None |
| 254 assert isinstance(options, CommonOptions) | |
| 255 | 243 |
| 256 def __getitem__(self, key): | 244 def __getitem__(self, key): |
| 257 # Convenience method to allow direct [] access on step classes for | 245 # Convenience method to allow direct [] access on step classes for |
| 258 # manipulating the backed state dict. | 246 # manipulating the backed state dict. |
| 259 return self._state[key] | 247 return self._state[key] |
| 260 | 248 |
| 261 def __setitem__(self, key, value): | 249 def __setitem__(self, key, value): |
| 262 # Convenience method to allow direct [] access on step classes for | 250 # Convenience method to allow direct [] access on step classes for |
| 263 # manipulating the backed state dict. | 251 # manipulating the backed state dict. |
| 264 self._state[key] = value | 252 self._state[key] = value |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 try: | 483 try: |
| 496 requires = step_class.REQUIRES | 484 requires = step_class.REQUIRES |
| 497 except AttributeError: | 485 except AttributeError: |
| 498 requires = None | 486 requires = None |
| 499 | 487 |
| 500 return step_class(message, requires, number=number, config=config, | 488 return step_class(message, requires, number=number, config=config, |
| 501 state=state, options=options, | 489 state=state, options=options, |
| 502 handler=side_effect_handler) | 490 handler=side_effect_handler) |
| 503 | 491 |
| 504 | 492 |
| 505 def RunScript(step_classes, | 493 class ScriptsBase(object): |
| 506 config, | 494 # TODO(machenbach): Move static config here. |
| 507 options, | 495 def __init__(self, config, side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER, |
| 508 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): | 496 state=None): |
| 509 state_file = "%s-state.json" % config[PERSISTFILE_BASENAME] | 497 self._config = config |
| 510 if options.step == 0 and os.path.exists(state_file): | 498 self._side_effect_handler = side_effect_handler |
| 511 os.remove(state_file) | 499 self._state = state if state is not None else {} |
| 512 state = {} | |
| 513 steps = [] | |
| 514 for (number, step_class) in enumerate(step_classes): | |
| 515 steps.append(MakeStep(step_class, number, state, config, | |
| 516 options, side_effect_handler)) | |
| 517 | 500 |
| 518 for step in steps[options.step:]: | 501 def _Description(self): |
| 519 step.Run() | 502 return None |
| 503 |
| 504 def _PrepareOptions(self, parser): |
| 505 pass |
| 506 |
| 507 def _ProcessOptions(self, options): |
| 508 return True |
| 509 |
| 510 def _Steps(self): |
| 511 raise Exception("Not implemented.") |
| 512 |
| 513 def MakeOptions(self, args=None): |
| 514 parser = argparse.ArgumentParser(description=self._Description()) |
| 515 parser.add_argument("-a", "--author", default="", |
| 516 help="The author email used for rietveld.") |
| 517 parser.add_argument("-r", "--reviewer", default="", |
| 518 help="The account name to be used for reviews.") |
| 519 parser.add_argument("-s", "--step", |
| 520 help="Specify the step where to start work. Default: 0.", |
| 521 default=0, type=int) |
| 522 |
| 523 self._PrepareOptions(parser) |
| 524 |
| 525 if args is None: |
| 526 options = parser.parse_args() |
| 527 else: |
| 528 options = parser.parse_args(args) |
| 529 |
| 530 # Process common options. |
| 531 if options.step < 0: |
| 532 print "Bad step number %d" % options.step |
| 533 parser.print_help() |
| 534 return None |
| 535 |
| 536 # Defaults for options, common to all scripts. |
| 537 options.manual = getattr(options, "manual", True) |
| 538 options.force = getattr(options, "force", False) |
| 539 |
| 540 # Derived options. |
| 541 options.requires_editor = not options.force |
| 542 options.wait_for_lgtm = not options.force |
| 543 options.force_readline_defaults = not options.manual |
| 544 options.force_upload = not options.manual |
| 545 |
| 546 # Process script specific options. |
| 547 if not self._ProcessOptions(options): |
| 548 parser.print_help() |
| 549 return None |
| 550 return options |
| 551 |
| 552 def RunSteps(self, step_classes, args=None): |
| 553 options = self.MakeOptions(args) |
| 554 if not options: |
| 555 return 1 |
| 556 |
| 557 state_file = "%s-state.json" % self._config[PERSISTFILE_BASENAME] |
| 558 if options.step == 0 and os.path.exists(state_file): |
| 559 os.remove(state_file) |
| 560 |
| 561 steps = [] |
| 562 for (number, step_class) in enumerate(step_classes): |
| 563 steps.append(MakeStep(step_class, number, self._state, self._config, |
| 564 options, self._side_effect_handler)) |
| 565 for step in steps[options.step:]: |
| 566 step.Run() |
| 567 return 0 |
| 568 |
| 569 def Run(self, args=None): |
| 570 return self.RunSteps(self._Steps(), args) |
| OLD | NEW |