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

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

Issue 67763005: Add forced mode to push-to-trunk script. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed review comments. Created 7 years, 1 month 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 | « no previous file | tools/push-to-trunk/push_to_trunk.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
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 def ReadLine(self): 159 def ReadLine(self):
160 return sys.stdin.readline().strip() 160 return sys.stdin.readline().strip()
161 161
162 DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler() 162 DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler()
163 163
164 164
165 class Step(object): 165 class Step(object):
166 def __init__(self, text="", requires=None): 166 def __init__(self, text="", requires=None):
167 self._text = text 167 self._text = text
168 self._number = -1 168 self._number = -1
169 self._options = None
169 self._requires = requires 170 self._requires = requires
170 self._side_effect_handler = DEFAULT_SIDE_EFFECT_HANDLER 171 self._side_effect_handler = DEFAULT_SIDE_EFFECT_HANDLER
171 172
172 def SetNumber(self, number): 173 def SetNumber(self, number):
173 self._number = number 174 self._number = number
174 175
175 def SetConfig(self, config): 176 def SetConfig(self, config):
176 self._config = config 177 self._config = config
177 178
178 def SetState(self, state): 179 def SetState(self, state):
(...skipping 16 matching lines...) Expand all
195 if self._requires: 196 if self._requires:
196 self.RestoreIfUnset(self._requires) 197 self.RestoreIfUnset(self._requires)
197 if not self._state[self._requires]: 198 if not self._state[self._requires]:
198 return 199 return
199 print ">>> Step %d: %s" % (self._number, self._text) 200 print ">>> Step %d: %s" % (self._number, self._text)
200 self.RunStep() 201 self.RunStep()
201 202
202 def RunStep(self): 203 def RunStep(self):
203 raise NotImplementedError 204 raise NotImplementedError
204 205
205 def ReadLine(self): 206 def ReadLine(self, default=None):
206 return self._side_effect_handler.ReadLine() 207 # Don't prompt in forced mode.
208 if self._options and self._options.f and default is not None:
209 print "%s (forced)" % default
210 return default
211 else:
212 return self._side_effect_handler.ReadLine()
207 213
208 def Git(self, args="", prefix="", pipe=True): 214 def Git(self, args="", prefix="", pipe=True):
209 return self._side_effect_handler.Command("git", args, prefix, pipe) 215 return self._side_effect_handler.Command("git", args, prefix, pipe)
210 216
211 def Editor(self, args): 217 def Editor(self, args):
212 return self._side_effect_handler.Command(os.environ["EDITOR"], args, 218 return self._side_effect_handler.Command(os.environ["EDITOR"], args,
213 pipe=False) 219 pipe=False)
214 220
215 def Die(self, msg=""): 221 def Die(self, msg=""):
216 if msg != "": 222 if msg != "":
217 print "Error: %s" % msg 223 print "Error: %s" % msg
218 print "Exiting" 224 print "Exiting"
219 raise Exception(msg) 225 raise Exception(msg)
220 226
227 def DieInForcedMode(self, msg=""):
228 if self._options and self._options.f:
229 msg = msg or "Not implemented in forced mode."
230 self.Die(msg)
231
221 def Confirm(self, msg): 232 def Confirm(self, msg):
222 print "%s [Y/n] " % msg, 233 print "%s [Y/n] " % msg,
223 answer = self.ReadLine() 234 answer = self.ReadLine(default="Y")
224 return answer == "" or answer == "Y" or answer == "y" 235 return answer == "" or answer == "Y" or answer == "y"
225 236
226 def DeleteBranch(self, name): 237 def DeleteBranch(self, name):
227 git_result = self.Git("branch").strip() 238 git_result = self.Git("branch").strip()
228 for line in git_result.splitlines(): 239 for line in git_result.splitlines():
229 if re.match(r".*\s+%s$" % name, line): 240 if re.match(r".*\s+%s$" % name, line):
230 msg = "Branch %s exists, do you want to delete it?" % name 241 msg = "Branch %s exists, do you want to delete it?" % name
231 if self.Confirm(msg): 242 if self.Confirm(msg):
232 if self.Git("branch -D %s" % name) is None: 243 if self.Git("branch -D %s" % name) is None:
233 self.Die("Deleting branch '%s' failed." % name) 244 self.Die("Deleting branch '%s' failed." % name)
(...skipping 13 matching lines...) Expand all
247 258
248 def RestoreIfUnset(self, var_name): 259 def RestoreIfUnset(self, var_name):
249 if self._state.get(var_name) is None: 260 if self._state.get(var_name) is None:
250 self._state[var_name] = self.Restore(var_name) 261 self._state[var_name] = self.Restore(var_name)
251 262
252 def InitialEnvironmentChecks(self): 263 def InitialEnvironmentChecks(self):
253 # Cancel if this is not a git checkout. 264 # Cancel if this is not a git checkout.
254 if not os.path.exists(self._config[DOT_GIT_LOCATION]): 265 if not os.path.exists(self._config[DOT_GIT_LOCATION]):
255 self.Die("This is not a git checkout, this script won't work for you.") 266 self.Die("This is not a git checkout, this script won't work for you.")
256 267
268 # TODO(machenbach): Don't use EDITOR in forced mode as soon as script is
269 # well tested.
257 # Cancel if EDITOR is unset or not executable. 270 # Cancel if EDITOR is unset or not executable.
258 if (not os.environ.get("EDITOR") or 271 if (not os.environ.get("EDITOR") or
259 Command("which", os.environ["EDITOR"]) is None): 272 Command("which", os.environ["EDITOR"]) is None):
260 self.Die("Please set your EDITOR environment variable, you'll need it.") 273 self.Die("Please set your EDITOR environment variable, you'll need it.")
261 274
262 def CommonPrepare(self): 275 def CommonPrepare(self):
263 # Check for a clean workdir. 276 # Check for a clean workdir.
264 if self.Git("status -s -uno").strip() != "": 277 if self.Git("status -s -uno").strip() != "":
265 self.Die("Workspace is not clean. Please commit or undo your changes.") 278 self.Die("Workspace is not clean. Please commit or undo your changes.")
266 279
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 self.RestoreIfUnset("%s%s" % (prefix, v)) 331 self.RestoreIfUnset("%s%s" % (prefix, v))
319 332
320 def WaitForLGTM(self): 333 def WaitForLGTM(self):
321 print ("Please wait for an LGTM, then type \"LGTM<Return>\" to commit " 334 print ("Please wait for an LGTM, then type \"LGTM<Return>\" to commit "
322 "your change. (If you need to iterate on the patch or double check " 335 "your change. (If you need to iterate on the patch or double check "
323 "that it's sane, do so in another shell, but remember to not " 336 "that it's sane, do so in another shell, but remember to not "
324 "change the headline of the uploaded CL.") 337 "change the headline of the uploaded CL.")
325 answer = "" 338 answer = ""
326 while answer != "LGTM": 339 while answer != "LGTM":
327 print "> ", 340 print "> ",
341 # TODO(machenbach): Add default="LGTM" to avoid prompt when script is
342 # well tested and when prepare push cl has TBR flag.
328 answer = self.ReadLine() 343 answer = self.ReadLine()
329 if answer != "LGTM": 344 if answer != "LGTM":
330 print "That was not 'LGTM'." 345 print "That was not 'LGTM'."
331 346
332 def WaitForResolvingConflicts(self, patch_file): 347 def WaitForResolvingConflicts(self, patch_file):
333 print("Applying the patch \"%s\" failed. Either type \"ABORT<Return>\", " 348 print("Applying the patch \"%s\" failed. Either type \"ABORT<Return>\", "
334 "or resolve the conflicts, stage *all* touched files with " 349 "or resolve the conflicts, stage *all* touched files with "
335 "'git add', and type \"RESOLVED<Return>\"") 350 "'git add', and type \"RESOLVED<Return>\"")
351 self.DieInForcedMode()
336 answer = "" 352 answer = ""
337 while answer != "RESOLVED": 353 while answer != "RESOLVED":
338 if answer == "ABORT": 354 if answer == "ABORT":
339 self.Die("Applying the patch failed.") 355 self.Die("Applying the patch failed.")
340 if answer != "": 356 if answer != "":
341 print "That was not 'RESOLVED' or 'ABORT'." 357 print "That was not 'RESOLVED' or 'ABORT'."
342 print "> ", 358 print "> ",
343 answer = self.ReadLine() 359 answer = self.ReadLine()
344 360
345 # Takes a file containing the patch to apply as first argument. 361 # Takes a file containing the patch to apply as first argument.
346 def ApplyPatch(self, patch_file, reverse_patch=""): 362 def ApplyPatch(self, patch_file, reverse_patch=""):
347 args = "apply --index --reject %s \"%s\"" % (reverse_patch, patch_file) 363 args = "apply --index --reject %s \"%s\"" % (reverse_patch, patch_file)
348 if self.Git(args) is None: 364 if self.Git(args) is None:
349 self.WaitForResolvingConflicts(patch_file) 365 self.WaitForResolvingConflicts(patch_file)
350 366
351 367
352 class UploadStep(Step): 368 class UploadStep(Step):
353 def __init__(self): 369 def __init__(self):
354 Step.__init__(self, "Upload for code review.") 370 Step.__init__(self, "Upload for code review.")
355 371
356 def RunStep(self): 372 def RunStep(self):
357 print "Please enter the email address of a V8 reviewer for your patch: ", 373 if self._options and self._options.r:
358 reviewer = self.ReadLine() 374 print "Using account %s for review." % self._options.r
375 reviewer = self._options.r
376 else:
377 print "Please enter the email address of a V8 reviewer for your patch: ",
378 self.DieInForcedMode("A reviewer must be specified in forced mode.")
379 reviewer = self.ReadLine()
359 args = "cl upload -r \"%s\" --send-mail" % reviewer 380 args = "cl upload -r \"%s\" --send-mail" % reviewer
360 if self.Git(args,pipe=False) is None: 381 if self.Git(args,pipe=False) is None:
361 self.Die("'git cl upload' failed, please try again.") 382 self.Die("'git cl upload' failed, please try again.")
362 383
363 384
364 def RunScript(step_classes, 385 def RunScript(step_classes,
365 config, 386 config,
366 options, 387 options,
367 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): 388 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
368 state = {} 389 state = {}
369 steps = [] 390 steps = []
370 number = 0 391 number = 0
371 392
372 for step_class in step_classes: 393 for step_class in step_classes:
373 # TODO(machenbach): Factory methods. 394 # TODO(machenbach): Factory methods.
374 step = step_class() 395 step = step_class()
375 step.SetNumber(number) 396 step.SetNumber(number)
376 step.SetConfig(config) 397 step.SetConfig(config)
377 step.SetOptions(options) 398 step.SetOptions(options)
378 step.SetState(state) 399 step.SetState(state)
379 step.SetSideEffectHandler(side_effect_handler) 400 step.SetSideEffectHandler(side_effect_handler)
380 steps.append(step) 401 steps.append(step)
381 number += 1 402 number += 1
382 403
383 for step in steps[options.s:]: 404 for step in steps[options.s:]:
384 step.Run() 405 step.Run()
OLDNEW
« no previous file with comments | « no previous file | tools/push-to-trunk/push_to_trunk.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698