Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Side by Side Diff: tools/push-to-trunk/common_includes.py

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/push-to-trunk/auto_roll.py ('k') | tools/push-to-trunk/git_recipes.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 datetime 29 import datetime
30 import json
30 import os 31 import os
31 import re 32 import re
32 import subprocess 33 import subprocess
33 import sys 34 import sys
34 import textwrap 35 import textwrap
35 import time 36 import time
36 import urllib2 37 import urllib2
37 38
39 from git_recipes import GitRecipesMixin
40
38 PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME" 41 PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME"
39 TEMP_BRANCH = "TEMP_BRANCH" 42 TEMP_BRANCH = "TEMP_BRANCH"
40 BRANCHNAME = "BRANCHNAME" 43 BRANCHNAME = "BRANCHNAME"
41 DOT_GIT_LOCATION = "DOT_GIT_LOCATION" 44 DOT_GIT_LOCATION = "DOT_GIT_LOCATION"
42 VERSION_FILE = "VERSION_FILE" 45 VERSION_FILE = "VERSION_FILE"
43 CHANGELOG_FILE = "CHANGELOG_FILE" 46 CHANGELOG_FILE = "CHANGELOG_FILE"
44 CHANGELOG_ENTRY_FILE = "CHANGELOG_ENTRY_FILE" 47 CHANGELOG_ENTRY_FILE = "CHANGELOG_ENTRY_FILE"
45 COMMITMSG_FILE = "COMMITMSG_FILE" 48 COMMITMSG_FILE = "COMMITMSG_FILE"
46 PATCH_FILE = "PATCH_FILE" 49 PATCH_FILE = "PATCH_FILE"
47 50
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 def GetDate(self): 215 def GetDate(self):
213 return datetime.date.today().strftime("%Y-%m-%d") 216 return datetime.date.today().strftime("%Y-%m-%d")
214 217
215 DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler() 218 DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler()
216 219
217 220
218 class NoRetryException(Exception): 221 class NoRetryException(Exception):
219 pass 222 pass
220 223
221 224
225 class GitFailedException(Exception):
226 pass
227
228
222 class CommonOptions(object): 229 class CommonOptions(object):
223 def __init__(self, options, manual=True): 230 def __init__(self, options, manual=True):
224 self.requires_editor = True 231 self.requires_editor = True
225 self.wait_for_lgtm = True 232 self.wait_for_lgtm = True
226 self.s = options.s 233 self.step = options.step
227 self.force_readline_defaults = not manual 234 self.force_readline_defaults = not manual
228 self.force_upload = not manual 235 self.force_upload = not manual
229 self.manual = manual 236 self.manual = manual
237 self.reviewer = getattr(options, 'reviewer', "")
238 self.author = getattr(options, 'author', "")
230 239
231 240
232 class Step(object): 241 class Step(GitRecipesMixin):
233 def __init__(self, text, requires, number, config, state, options, handler): 242 def __init__(self, text, requires, number, config, state, options, handler):
234 self._text = text 243 self._text = text
235 self._requires = requires 244 self._requires = requires
236 self._number = number 245 self._number = number
237 self._config = config 246 self._config = config
238 self._state = state 247 self._state = state
239 self._options = options 248 self._options = options
240 self._side_effect_handler = handler 249 self._side_effect_handler = handler
241 assert self._number >= 0 250 assert self._number >= 0
242 assert self._config is not None 251 assert self._config is not None
243 assert self._state is not None 252 assert self._state is not None
244 assert self._side_effect_handler is not None 253 assert self._side_effect_handler is not None
245 assert isinstance(options, CommonOptions) 254 assert isinstance(options, CommonOptions)
246 255
256 def __getitem__(self, key):
257 # Convenience method to allow direct [] access on step classes for
258 # manipulating the backed state dict.
259 return self._state[key]
260
261 def __setitem__(self, key, value):
262 # Convenience method to allow direct [] access on step classes for
263 # manipulating the backed state dict.
264 self._state[key] = value
265
247 def Config(self, key): 266 def Config(self, key):
248 return self._config[key] 267 return self._config[key]
249 268
250 def Run(self): 269 def Run(self):
251 if self._requires: 270 # Restore state.
252 self.RestoreIfUnset(self._requires) 271 state_file = "%s-state.json" % self._config[PERSISTFILE_BASENAME]
253 if not self._state[self._requires]: 272 if not self._state and os.path.exists(state_file):
254 return 273 self._state.update(json.loads(FileToText(state_file)))
274
275 # Skip step if requirement is not met.
276 if self._requires and not self._state.get(self._requires):
277 return
278
255 print ">>> Step %d: %s" % (self._number, self._text) 279 print ">>> Step %d: %s" % (self._number, self._text)
256 self.RunStep() 280 self.RunStep()
257 281
282 # Persist state.
283 TextToFile(json.dumps(self._state), state_file)
284
258 def RunStep(self): 285 def RunStep(self):
259 raise NotImplementedError 286 raise NotImplementedError
260 287
261 def Retry(self, cb, retry_on=None, wait_plan=None): 288 def Retry(self, cb, retry_on=None, wait_plan=None):
262 """ Retry a function. 289 """ Retry a function.
263 Params: 290 Params:
264 cb: The function to retry. 291 cb: The function to retry.
265 retry_on: A callback that takes the result of the function and returns 292 retry_on: A callback that takes the result of the function and returns
266 True if the function should be retried. A function throwing an 293 True if the function should be retried. A function throwing an
267 exception is always retried. 294 exception is always retried.
(...skipping 24 matching lines...) Expand all
292 def ReadLine(self, default=None): 319 def ReadLine(self, default=None):
293 # Don't prompt in forced mode. 320 # Don't prompt in forced mode.
294 if self._options.force_readline_defaults and default is not None: 321 if self._options.force_readline_defaults and default is not None:
295 print "%s (forced)" % default 322 print "%s (forced)" % default
296 return default 323 return default
297 else: 324 else:
298 return self._side_effect_handler.ReadLine() 325 return self._side_effect_handler.ReadLine()
299 326
300 def Git(self, args="", prefix="", pipe=True, retry_on=None): 327 def Git(self, args="", prefix="", pipe=True, retry_on=None):
301 cmd = lambda: self._side_effect_handler.Command("git", args, prefix, pipe) 328 cmd = lambda: self._side_effect_handler.Command("git", args, prefix, pipe)
329 result = self.Retry(cmd, retry_on, [5, 30])
330 if result is None:
331 raise GitFailedException("'git %s' failed." % args)
332 return result
333
334 def SVN(self, args="", prefix="", pipe=True, retry_on=None):
335 cmd = lambda: self._side_effect_handler.Command("svn", args, prefix, pipe)
302 return self.Retry(cmd, retry_on, [5, 30]) 336 return self.Retry(cmd, retry_on, [5, 30])
303 337
304 def Editor(self, args): 338 def Editor(self, args):
305 if self._options.requires_editor: 339 if self._options.requires_editor:
306 return self._side_effect_handler.Command(os.environ["EDITOR"], args, 340 return self._side_effect_handler.Command(os.environ["EDITOR"], args,
307 pipe=False) 341 pipe=False)
308 342
309 def ReadURL(self, url, params=None, retry_on=None, wait_plan=None): 343 def ReadURL(self, url, params=None, retry_on=None, wait_plan=None):
310 wait_plan = wait_plan or [3, 60, 600] 344 wait_plan = wait_plan or [3, 60, 600]
311 cmd = lambda: self._side_effect_handler.ReadURL(url, params) 345 cmd = lambda: self._side_effect_handler.ReadURL(url, params)
(...skipping 12 matching lines...) Expand all
324 if not self._options.manual: 358 if not self._options.manual:
325 msg = msg or "Only available in manual mode." 359 msg = msg or "Only available in manual mode."
326 self.Die(msg) 360 self.Die(msg)
327 361
328 def Confirm(self, msg): 362 def Confirm(self, msg):
329 print "%s [Y/n] " % msg, 363 print "%s [Y/n] " % msg,
330 answer = self.ReadLine(default="Y") 364 answer = self.ReadLine(default="Y")
331 return answer == "" or answer == "Y" or answer == "y" 365 return answer == "" or answer == "Y" or answer == "y"
332 366
333 def DeleteBranch(self, name): 367 def DeleteBranch(self, name):
334 git_result = self.Git("branch").strip() 368 for line in self.GitBranch().splitlines():
335 for line in git_result.splitlines():
336 if re.match(r".*\s+%s$" % name, line): 369 if re.match(r".*\s+%s$" % name, line):
337 msg = "Branch %s exists, do you want to delete it?" % name 370 msg = "Branch %s exists, do you want to delete it?" % name
338 if self.Confirm(msg): 371 if self.Confirm(msg):
339 if self.Git("branch -D %s" % name) is None: 372 self.GitDeleteBranch(name)
340 self.Die("Deleting branch '%s' failed." % name)
341 print "Branch %s deleted." % name 373 print "Branch %s deleted." % name
342 else: 374 else:
343 msg = "Can't continue. Please delete branch %s and try again." % name 375 msg = "Can't continue. Please delete branch %s and try again." % name
344 self.Die(msg) 376 self.Die(msg)
345 377
346 def Persist(self, var, value):
347 value = value or "__EMPTY__"
348 TextToFile(value, "%s-%s" % (self._config[PERSISTFILE_BASENAME], var))
349
350 def Restore(self, var):
351 value = FileToText("%s-%s" % (self._config[PERSISTFILE_BASENAME], var))
352 value = value or self.Die("Variable '%s' could not be restored." % var)
353 return "" if value == "__EMPTY__" else value
354
355 def RestoreIfUnset(self, var_name):
356 if self._state.get(var_name) is None:
357 self._state[var_name] = self.Restore(var_name)
358
359 def InitialEnvironmentChecks(self): 378 def InitialEnvironmentChecks(self):
360 # Cancel if this is not a git checkout. 379 # Cancel if this is not a git checkout.
361 if not os.path.exists(self._config[DOT_GIT_LOCATION]): 380 if not os.path.exists(self._config[DOT_GIT_LOCATION]):
362 self.Die("This is not a git checkout, this script won't work for you.") 381 self.Die("This is not a git checkout, this script won't work for you.")
363 382
364 # Cancel if EDITOR is unset or not executable. 383 # Cancel if EDITOR is unset or not executable.
365 if (self._options.requires_editor and (not os.environ.get("EDITOR") or 384 if (self._options.requires_editor and (not os.environ.get("EDITOR") or
366 Command("which", os.environ["EDITOR"]) is None)): 385 Command("which", os.environ["EDITOR"]) is None)):
367 self.Die("Please set your EDITOR environment variable, you'll need it.") 386 self.Die("Please set your EDITOR environment variable, you'll need it.")
368 387
369 def CommonPrepare(self): 388 def CommonPrepare(self):
370 # Check for a clean workdir. 389 # Check for a clean workdir.
371 if self.Git("status -s -uno").strip() != "": 390 if not self.GitIsWorkdirClean():
372 self.Die("Workspace is not clean. Please commit or undo your changes.") 391 self.Die("Workspace is not clean. Please commit or undo your changes.")
373 392
374 # Persist current branch. 393 # Persist current branch.
375 current_branch = "" 394 self["current_branch"] = self.GitCurrentBranch()
376 git_result = self.Git("status -s -b -uno").strip()
377 for line in git_result.splitlines():
378 match = re.match(r"^## (.+)", line)
379 if match:
380 current_branch = match.group(1)
381 break
382 self.Persist("current_branch", current_branch)
383 395
384 # Fetch unfetched revisions. 396 # Fetch unfetched revisions.
385 if self.Git("svn fetch") is None: 397 self.GitSVNFetch()
386 self.Die("'git svn fetch' failed.")
387 398
388 def PrepareBranch(self): 399 def PrepareBranch(self):
389 # Get ahold of a safe temporary branch and check it out. 400 # Get ahold of a safe temporary branch and check it out.
390 self.RestoreIfUnset("current_branch") 401 if self["current_branch"] != self._config[TEMP_BRANCH]:
391 if self._state["current_branch"] != self._config[TEMP_BRANCH]:
392 self.DeleteBranch(self._config[TEMP_BRANCH]) 402 self.DeleteBranch(self._config[TEMP_BRANCH])
393 self.Git("checkout -b %s" % self._config[TEMP_BRANCH]) 403 self.GitCreateBranch(self._config[TEMP_BRANCH])
394 404
395 # Delete the branch that will be created later if it exists already. 405 # Delete the branch that will be created later if it exists already.
396 self.DeleteBranch(self._config[BRANCHNAME]) 406 self.DeleteBranch(self._config[BRANCHNAME])
397 407
398 def CommonCleanup(self): 408 def CommonCleanup(self):
399 self.RestoreIfUnset("current_branch") 409 self.GitCheckout(self["current_branch"])
400 self.Git("checkout -f %s" % self._state["current_branch"]) 410 if self._config[TEMP_BRANCH] != self["current_branch"]:
401 if self._config[TEMP_BRANCH] != self._state["current_branch"]: 411 self.GitDeleteBranch(self._config[TEMP_BRANCH])
402 self.Git("branch -D %s" % self._config[TEMP_BRANCH]) 412 if self._config[BRANCHNAME] != self["current_branch"]:
403 if self._config[BRANCHNAME] != self._state["current_branch"]: 413 self.GitDeleteBranch(self._config[BRANCHNAME])
404 self.Git("branch -D %s" % self._config[BRANCHNAME])
405 414
406 # Clean up all temporary files. 415 # Clean up all temporary files.
407 Command("rm", "-f %s*" % self._config[PERSISTFILE_BASENAME]) 416 Command("rm", "-f %s*" % self._config[PERSISTFILE_BASENAME])
408 417
409 def ReadAndPersistVersion(self, prefix=""): 418 def ReadAndPersistVersion(self, prefix=""):
410 def ReadAndPersist(var_name, def_name): 419 def ReadAndPersist(var_name, def_name):
411 match = re.match(r"^#define %s\s+(\d*)" % def_name, line) 420 match = re.match(r"^#define %s\s+(\d*)" % def_name, line)
412 if match: 421 if match:
413 value = match.group(1) 422 value = match.group(1)
414 self.Persist("%s%s" % (prefix, var_name), value) 423 self["%s%s" % (prefix, var_name)] = value
415 self._state["%s%s" % (prefix, var_name)] = value
416 for line in LinesInFile(self._config[VERSION_FILE]): 424 for line in LinesInFile(self._config[VERSION_FILE]):
417 for (var_name, def_name) in [("major", "MAJOR_VERSION"), 425 for (var_name, def_name) in [("major", "MAJOR_VERSION"),
418 ("minor", "MINOR_VERSION"), 426 ("minor", "MINOR_VERSION"),
419 ("build", "BUILD_NUMBER"), 427 ("build", "BUILD_NUMBER"),
420 ("patch", "PATCH_LEVEL")]: 428 ("patch", "PATCH_LEVEL")]:
421 ReadAndPersist(var_name, def_name) 429 ReadAndPersist(var_name, def_name)
422 430
423 def RestoreVersionIfUnset(self, prefix=""):
424 for v in ["major", "minor", "build", "patch"]:
425 self.RestoreIfUnset("%s%s" % (prefix, v))
426
427 def WaitForLGTM(self): 431 def WaitForLGTM(self):
428 print ("Please wait for an LGTM, then type \"LGTM<Return>\" to commit " 432 print ("Please wait for an LGTM, then type \"LGTM<Return>\" to commit "
429 "your change. (If you need to iterate on the patch or double check " 433 "your change. (If you need to iterate on the patch or double check "
430 "that it's sane, do so in another shell, but remember to not " 434 "that it's sane, do so in another shell, but remember to not "
431 "change the headline of the uploaded CL.") 435 "change the headline of the uploaded CL.")
432 answer = "" 436 answer = ""
433 while answer != "LGTM": 437 while answer != "LGTM":
434 print "> ", 438 print "> ",
435 answer = self.ReadLine(None if self._options.wait_for_lgtm else "LGTM") 439 answer = self.ReadLine(None if self._options.wait_for_lgtm else "LGTM")
436 if answer != "LGTM": 440 if answer != "LGTM":
437 print "That was not 'LGTM'." 441 print "That was not 'LGTM'."
438 442
439 def WaitForResolvingConflicts(self, patch_file): 443 def WaitForResolvingConflicts(self, patch_file):
440 print("Applying the patch \"%s\" failed. Either type \"ABORT<Return>\", " 444 print("Applying the patch \"%s\" failed. Either type \"ABORT<Return>\", "
441 "or resolve the conflicts, stage *all* touched files with " 445 "or resolve the conflicts, stage *all* touched files with "
442 "'git add', and type \"RESOLVED<Return>\"") 446 "'git add', and type \"RESOLVED<Return>\"")
443 self.DieNoManualMode() 447 self.DieNoManualMode()
444 answer = "" 448 answer = ""
445 while answer != "RESOLVED": 449 while answer != "RESOLVED":
446 if answer == "ABORT": 450 if answer == "ABORT":
447 self.Die("Applying the patch failed.") 451 self.Die("Applying the patch failed.")
448 if answer != "": 452 if answer != "":
449 print "That was not 'RESOLVED' or 'ABORT'." 453 print "That was not 'RESOLVED' or 'ABORT'."
450 print "> ", 454 print "> ",
451 answer = self.ReadLine() 455 answer = self.ReadLine()
452 456
453 # Takes a file containing the patch to apply as first argument. 457 # Takes a file containing the patch to apply as first argument.
454 def ApplyPatch(self, patch_file, reverse_patch=""): 458 def ApplyPatch(self, patch_file, revert=False):
455 args = "apply --index --reject %s \"%s\"" % (reverse_patch, patch_file) 459 try:
456 if self.Git(args) is None: 460 self.GitApplyPatch(patch_file, revert)
461 except GitFailedException:
457 self.WaitForResolvingConflicts(patch_file) 462 self.WaitForResolvingConflicts(patch_file)
458 463
464 def FindLastTrunkPush(self, parent_hash=""):
465 push_pattern = "^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based"
466 branch = "" if parent_hash else "svn/trunk"
467 return self.GitLog(n=1, format="%H", grep=push_pattern,
468 parent_hash=parent_hash, branch=branch)
469
459 470
460 class UploadStep(Step): 471 class UploadStep(Step):
461 MESSAGE = "Upload for code review." 472 MESSAGE = "Upload for code review."
462 473
463 def RunStep(self): 474 def RunStep(self):
464 if self._options.r: 475 if self._options.reviewer:
465 print "Using account %s for review." % self._options.r 476 print "Using account %s for review." % self._options.reviewer
466 reviewer = self._options.r 477 reviewer = self._options.reviewer
467 else: 478 else:
468 print "Please enter the email address of a V8 reviewer for your patch: ", 479 print "Please enter the email address of a V8 reviewer for your patch: ",
469 self.DieNoManualMode("A reviewer must be specified in forced mode.") 480 self.DieNoManualMode("A reviewer must be specified in forced mode.")
470 reviewer = self.ReadLine() 481 reviewer = self.ReadLine()
471 force_flag = " -f" if self._options.force_upload else "" 482 self.GitUpload(reviewer, self._options.author, self._options.force_upload)
472 args = "cl upload -r \"%s\" --send-mail%s" % (reviewer, force_flag)
473 # TODO(machenbach): Check output in forced mode. Verify that all required
474 # base files were uploaded, if not retry.
475 if self.Git(args, pipe=False) is None:
476 self.Die("'git cl upload' failed, please try again.")
477 483
478 484
479 def MakeStep(step_class=Step, number=0, state=None, config=None, 485 def MakeStep(step_class=Step, number=0, state=None, config=None,
480 options=None, side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): 486 options=None, side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
481 # Allow to pass in empty dictionaries. 487 # Allow to pass in empty dictionaries.
482 state = state if state is not None else {} 488 state = state if state is not None else {}
483 config = config if config is not None else {} 489 config = config if config is not None else {}
484 490
485 try: 491 try:
486 message = step_class.MESSAGE 492 message = step_class.MESSAGE
487 except AttributeError: 493 except AttributeError:
488 message = step_class.__name__ 494 message = step_class.__name__
489 try: 495 try:
490 requires = step_class.REQUIRES 496 requires = step_class.REQUIRES
491 except AttributeError: 497 except AttributeError:
492 requires = None 498 requires = None
493 499
494 return step_class(message, requires, number=number, config=config, 500 return step_class(message, requires, number=number, config=config,
495 state=state, options=options, 501 state=state, options=options,
496 handler=side_effect_handler) 502 handler=side_effect_handler)
497 503
498 504
499 def RunScript(step_classes, 505 def RunScript(step_classes,
500 config, 506 config,
501 options, 507 options,
502 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): 508 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
509 state_file = "%s-state.json" % config[PERSISTFILE_BASENAME]
510 if options.step == 0 and os.path.exists(state_file):
511 os.remove(state_file)
503 state = {} 512 state = {}
504 steps = [] 513 steps = []
505 for (number, step_class) in enumerate(step_classes): 514 for (number, step_class) in enumerate(step_classes):
506 steps.append(MakeStep(step_class, number, state, config, 515 steps.append(MakeStep(step_class, number, state, config,
507 options, side_effect_handler)) 516 options, side_effect_handler))
508 517
509 for step in steps[options.s:]: 518 for step in steps[options.step:]:
510 step.Run() 519 step.Run()
OLDNEW
« no previous file with comments | « tools/push-to-trunk/auto_roll.py ('k') | tools/push-to-trunk/git_recipes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698