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

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

Issue 148593004: A64: Synchronize with r18084. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/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 13 matching lines...) Expand all
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 os 29 import os
30 import re 30 import re
31 import subprocess 31 import subprocess
32 import sys 32 import sys
33 import textwrap 33 import textwrap
34 import urllib2
34 35
35 PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME" 36 PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME"
36 TEMP_BRANCH = "TEMP_BRANCH" 37 TEMP_BRANCH = "TEMP_BRANCH"
37 BRANCHNAME = "BRANCHNAME" 38 BRANCHNAME = "BRANCHNAME"
38 DOT_GIT_LOCATION = "DOT_GIT_LOCATION" 39 DOT_GIT_LOCATION = "DOT_GIT_LOCATION"
39 VERSION_FILE = "VERSION_FILE" 40 VERSION_FILE = "VERSION_FILE"
40 CHANGELOG_FILE = "CHANGELOG_FILE" 41 CHANGELOG_FILE = "CHANGELOG_FILE"
41 CHANGELOG_ENTRY_FILE = "CHANGELOG_ENTRY_FILE" 42 CHANGELOG_ENTRY_FILE = "CHANGELOG_ENTRY_FILE"
42 COMMITMSG_FILE = "COMMITMSG_FILE" 43 COMMITMSG_FILE = "COMMITMSG_FILE"
43 PATCH_FILE = "PATCH_FILE" 44 PATCH_FILE = "PATCH_FILE"
(...skipping 18 matching lines...) Expand all
62 def FileToText(file_name): 63 def FileToText(file_name):
63 with open(file_name) as f: 64 with open(file_name) as f:
64 return f.read() 65 return f.read()
65 66
66 67
67 def MSub(rexp, replacement, text): 68 def MSub(rexp, replacement, text):
68 return re.sub(rexp, replacement, text, flags=re.MULTILINE) 69 return re.sub(rexp, replacement, text, flags=re.MULTILINE)
69 70
70 71
71 def Fill80(line): 72 def Fill80(line):
73 # Replace tabs and remove surrounding space.
74 line = re.sub(r"\t", r" ", line.strip())
75
76 # Format with 8 characters indentation and line width 80.
72 return textwrap.fill(line, width=80, initial_indent=" ", 77 return textwrap.fill(line, width=80, initial_indent=" ",
73 subsequent_indent=" ") 78 subsequent_indent=" ")
74 79
75 80
76 def GetLastChangeLogEntries(change_log_file): 81 def GetLastChangeLogEntries(change_log_file):
77 result = [] 82 result = []
78 for line in LinesInFile(change_log_file): 83 for line in LinesInFile(change_log_file):
79 if re.search(r"^\d{4}-\d{2}-\d{2}:", line) and result: break 84 if re.search(r"^\d{4}-\d{2}-\d{2}:", line) and result: break
80 result.append(line) 85 result.append(line)
81 return "".join(result) 86 return "".join(result)
82 87
83 88
84 def MakeChangeLogBody(commit_generator): 89 def MakeComment(text):
90 return MSub(r"^( ?)", "#", text)
91
92
93 def StripComments(text):
94 # Use split not splitlines to keep terminal newlines.
95 return "\n".join(filter(lambda x: not x.startswith("#"), text.split("\n")))
96
97
98 def MakeChangeLogBody(commit_messages, auto_format=False):
85 result = "" 99 result = ""
86 for (title, body, author) in commit_generator(): 100 added_titles = set()
87 # Add the commit's title line. 101 for (title, body, author) in commit_messages:
88 result += "%s\n" % title.rstrip() 102 # TODO(machenbach): Better check for reverts. A revert should remove the
103 # original CL from the actual log entry.
104 title = title.strip()
105 if auto_format:
106 # Only add commits that set the LOG flag correctly.
107 log_exp = r"^[ \t]*LOG[ \t]*=[ \t]*(?:Y(?:ES)?)|TRUE"
108 if not re.search(log_exp, body, flags=re.I | re.M):
109 continue
110 # Never include reverts.
111 if title.startswith("Revert "):
112 continue
113 # Don't include duplicates.
114 if title in added_titles:
115 continue
89 116
90 # Add bug references. 117 # Add and format the commit's title and bug reference. Move dot to the end.
91 result += MakeChangeLogBugReference(body) 118 added_titles.add(title)
119 raw_title = re.sub(r"(\.|\?|!)$", "", title)
120 bug_reference = MakeChangeLogBugReference(body)
121 space = " " if bug_reference else ""
122 result += "%s\n" % Fill80("%s%s%s." % (raw_title, space, bug_reference))
92 123
93 # Append the commit's author for reference. 124 # Append the commit's author for reference if not in auto-format mode.
94 result += "%s\n\n" % author.rstrip() 125 if not auto_format:
126 result += "%s\n" % Fill80("(%s)" % author.strip())
127
128 result += "\n"
95 return result 129 return result
96 130
97 131
98 def MakeChangeLogBugReference(body): 132 def MakeChangeLogBugReference(body):
99 """Grep for "BUG=xxxx" lines in the commit message and convert them to 133 """Grep for "BUG=xxxx" lines in the commit message and convert them to
100 "(issue xxxx)". 134 "(issue xxxx)".
101 """ 135 """
102 crbugs = [] 136 crbugs = []
103 v8bugs = [] 137 v8bugs = []
104 138
(...skipping 19 matching lines...) Expand all
124 bug_groups = [] 158 bug_groups = []
125 def FormatIssues(prefix, bugs): 159 def FormatIssues(prefix, bugs):
126 if len(bugs) > 0: 160 if len(bugs) > 0:
127 plural = "s" if len(bugs) > 1 else "" 161 plural = "s" if len(bugs) > 1 else ""
128 bug_groups.append("%sissue%s %s" % (prefix, plural, ", ".join(bugs))) 162 bug_groups.append("%sissue%s %s" % (prefix, plural, ", ".join(bugs)))
129 163
130 FormatIssues("", v8bugs) 164 FormatIssues("", v8bugs)
131 FormatIssues("Chromium ", crbugs) 165 FormatIssues("Chromium ", crbugs)
132 166
133 if len(bug_groups) > 0: 167 if len(bug_groups) > 0:
134 # Format with 8 characters indentation and max 80 character lines. 168 return "(%s)" % ", ".join(bug_groups)
135 return "%s\n" % Fill80("(%s)" % ", ".join(bug_groups))
136 else: 169 else:
137 return "" 170 return ""
138 171
139 172
140 # Some commands don't like the pipe, e.g. calling vi from within the script or 173 # Some commands don't like the pipe, e.g. calling vi from within the script or
141 # from subscripts like git cl upload. 174 # from subscripts like git cl upload.
142 def Command(cmd, args="", prefix="", pipe=True): 175 def Command(cmd, args="", prefix="", pipe=True):
143 cmd_line = "%s %s %s" % (prefix, cmd, args) 176 cmd_line = "%s %s %s" % (prefix, cmd, args)
144 print "Command: %s" % cmd_line 177 print "Command: %s" % cmd_line
145 try: 178 try:
146 if pipe: 179 if pipe:
147 return subprocess.check_output(cmd_line, shell=True) 180 return subprocess.check_output(cmd_line, shell=True)
148 else: 181 else:
149 return subprocess.check_call(cmd_line, shell=True) 182 return subprocess.check_call(cmd_line, shell=True)
150 except subprocess.CalledProcessError: 183 except subprocess.CalledProcessError:
151 return None 184 return None
152 185
153 186
154 # Wrapper for side effects. 187 # Wrapper for side effects.
155 class SideEffectHandler(object): 188 class SideEffectHandler(object):
156 def Command(self, cmd, args="", prefix="", pipe=True): 189 def Command(self, cmd, args="", prefix="", pipe=True):
157 return Command(cmd, args, prefix, pipe) 190 return Command(cmd, args, prefix, pipe)
158 191
159 def ReadLine(self): 192 def ReadLine(self):
160 return sys.stdin.readline().strip() 193 return sys.stdin.readline().strip()
161 194
195 def ReadURL(self, url):
196 # pylint: disable=E1121
197 url_fh = urllib2.urlopen(url, None, 60)
198 try:
199 return url_fh.read()
200 finally:
201 url_fh.close()
202
162 DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler() 203 DEFAULT_SIDE_EFFECT_HANDLER = SideEffectHandler()
163 204
164 205
165 class Step(object): 206 class Step(object):
166 def __init__(self, text="", requires=None): 207 def __init__(self, text, requires, number, config, state, options, handler):
167 self._text = text 208 self._text = text
168 self._number = -1
169 self._options = None
170 self._requires = requires 209 self._requires = requires
171 self._side_effect_handler = DEFAULT_SIDE_EFFECT_HANDLER
172
173 def SetNumber(self, number):
174 self._number = number 210 self._number = number
175
176 def SetConfig(self, config):
177 self._config = config 211 self._config = config
178
179 def SetState(self, state):
180 self._state = state 212 self._state = state
181
182 def SetOptions(self, options):
183 self._options = options 213 self._options = options
184
185 def SetSideEffectHandler(self, handler):
186 self._side_effect_handler = handler 214 self._side_effect_handler = handler
215 assert self._number >= 0
216 assert self._config is not None
217 assert self._state is not None
218 assert self._side_effect_handler is not None
187 219
188 def Config(self, key): 220 def Config(self, key):
189 return self._config[key] 221 return self._config[key]
190 222
191 def Run(self): 223 def Run(self):
192 assert self._number >= 0
193 assert self._config is not None
194 assert self._state is not None
195 assert self._side_effect_handler is not None
196 if self._requires: 224 if self._requires:
197 self.RestoreIfUnset(self._requires) 225 self.RestoreIfUnset(self._requires)
198 if not self._state[self._requires]: 226 if not self._state[self._requires]:
199 return 227 return
200 print ">>> Step %d: %s" % (self._number, self._text) 228 print ">>> Step %d: %s" % (self._number, self._text)
201 self.RunStep() 229 self.RunStep()
202 230
203 def RunStep(self): 231 def RunStep(self):
204 raise NotImplementedError 232 raise NotImplementedError
205 233
206 def ReadLine(self, default=None): 234 def ReadLine(self, default=None):
207 # Don't prompt in forced mode. 235 # Don't prompt in forced mode.
208 if self._options and self._options.f and default is not None: 236 if self._options and self._options.f and default is not None:
209 print "%s (forced)" % default 237 print "%s (forced)" % default
210 return default 238 return default
211 else: 239 else:
212 return self._side_effect_handler.ReadLine() 240 return self._side_effect_handler.ReadLine()
213 241
214 def Git(self, args="", prefix="", pipe=True): 242 def Git(self, args="", prefix="", pipe=True):
215 return self._side_effect_handler.Command("git", args, prefix, pipe) 243 return self._side_effect_handler.Command("git", args, prefix, pipe)
216 244
217 def Editor(self, args): 245 def Editor(self, args):
218 return self._side_effect_handler.Command(os.environ["EDITOR"], args, 246 return self._side_effect_handler.Command(os.environ["EDITOR"], args,
219 pipe=False) 247 pipe=False)
220 248
249 def ReadURL(self, url):
250 return self._side_effect_handler.ReadURL(url)
251
221 def Die(self, msg=""): 252 def Die(self, msg=""):
222 if msg != "": 253 if msg != "":
223 print "Error: %s" % msg 254 print "Error: %s" % msg
224 print "Exiting" 255 print "Exiting"
225 raise Exception(msg) 256 raise Exception(msg)
226 257
227 def DieInForcedMode(self, msg=""): 258 def DieInForcedMode(self, msg=""):
228 if self._options and self._options.f: 259 if self._options and self._options.f:
229 msg = msg or "Not implemented in forced mode." 260 msg = msg or "Not implemented in forced mode."
230 self.Die(msg) 261 self.Die(msg)
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 answer = self.ReadLine() 390 answer = self.ReadLine()
360 391
361 # Takes a file containing the patch to apply as first argument. 392 # Takes a file containing the patch to apply as first argument.
362 def ApplyPatch(self, patch_file, reverse_patch=""): 393 def ApplyPatch(self, patch_file, reverse_patch=""):
363 args = "apply --index --reject %s \"%s\"" % (reverse_patch, patch_file) 394 args = "apply --index --reject %s \"%s\"" % (reverse_patch, patch_file)
364 if self.Git(args) is None: 395 if self.Git(args) is None:
365 self.WaitForResolvingConflicts(patch_file) 396 self.WaitForResolvingConflicts(patch_file)
366 397
367 398
368 class UploadStep(Step): 399 class UploadStep(Step):
369 def __init__(self): 400 MESSAGE = "Upload for code review."
370 Step.__init__(self, "Upload for code review.")
371 401
372 def RunStep(self): 402 def RunStep(self):
373 if self._options and self._options.r: 403 if self._options.r:
374 print "Using account %s for review." % self._options.r 404 print "Using account %s for review." % self._options.r
375 reviewer = self._options.r 405 reviewer = self._options.r
376 else: 406 else:
377 print "Please enter the email address of a V8 reviewer for your patch: ", 407 print "Please enter the email address of a V8 reviewer for your patch: ",
378 self.DieInForcedMode("A reviewer must be specified in forced mode.") 408 self.DieInForcedMode("A reviewer must be specified in forced mode.")
379 reviewer = self.ReadLine() 409 reviewer = self.ReadLine()
380 args = "cl upload -r \"%s\" --send-mail" % reviewer 410 force_flag = " -f" if self._options.f else ""
381 if self.Git(args,pipe=False) is None: 411 args = "cl upload -r \"%s\" --send-mail%s" % (reviewer, force_flag)
412 # TODO(machenbach): Check output in forced mode. Verify that all required
413 # base files were uploaded, if not retry.
414 if self.Git(args, pipe=False) is None:
382 self.Die("'git cl upload' failed, please try again.") 415 self.Die("'git cl upload' failed, please try again.")
383 416
384 417
418 def MakeStep(step_class=Step, number=0, state=None, config=None,
419 options=None, side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
420 # Allow to pass in empty dictionaries.
421 state = state if state is not None else {}
422 config = config if config is not None else {}
423
424 try:
425 message = step_class.MESSAGE
426 except AttributeError:
427 message = step_class.__name__
428 try:
429 requires = step_class.REQUIRES
430 except AttributeError:
431 requires = None
432
433 return step_class(message, requires, number=number, config=config,
434 state=state, options=options,
435 handler=side_effect_handler)
436
437
385 def RunScript(step_classes, 438 def RunScript(step_classes,
386 config, 439 config,
387 options, 440 options,
388 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER): 441 side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
389 state = {} 442 state = {}
390 steps = [] 443 steps = []
391 number = 0 444 for (number, step_class) in enumerate(step_classes):
392 445 steps.append(MakeStep(step_class, number, state, config,
393 for step_class in step_classes: 446 options, side_effect_handler))
394 # TODO(machenbach): Factory methods.
395 step = step_class()
396 step.SetNumber(number)
397 step.SetConfig(config)
398 step.SetOptions(options)
399 step.SetState(state)
400 step.SetSideEffectHandler(side_effect_handler)
401 steps.append(step)
402 number += 1
403 447
404 for step in steps[options.s:]: 448 for step in steps[options.s:]:
405 step.Run() 449 step.Run()
OLDNEW
« no previous file with comments | « tools/push-to-trunk/auto_roll.py ('k') | tools/push-to-trunk/push_to_trunk.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698