Chromium Code Reviews| 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 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 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 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 | 34 |
| 34 PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME" | 35 PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME" |
| 35 TEMP_BRANCH = "TEMP_BRANCH" | 36 TEMP_BRANCH = "TEMP_BRANCH" |
| 36 BRANCHNAME = "BRANCHNAME" | 37 BRANCHNAME = "BRANCHNAME" |
| 37 DOT_GIT_LOCATION = "DOT_GIT_LOCATION" | 38 DOT_GIT_LOCATION = "DOT_GIT_LOCATION" |
| 38 VERSION_FILE = "VERSION_FILE" | 39 VERSION_FILE = "VERSION_FILE" |
| 39 CHANGELOG_FILE = "CHANGELOG_FILE" | 40 CHANGELOG_FILE = "CHANGELOG_FILE" |
| 40 CHANGELOG_ENTRY_FILE = "CHANGELOG_ENTRY_FILE" | 41 CHANGELOG_ENTRY_FILE = "CHANGELOG_ENTRY_FILE" |
| 41 COMMITMSG_FILE = "COMMITMSG_FILE" | 42 COMMITMSG_FILE = "COMMITMSG_FILE" |
| 42 PATCH_FILE = "PATCH_FILE" | 43 PATCH_FILE = "PATCH_FILE" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 60 | 61 |
| 61 def FileToText(file_name): | 62 def FileToText(file_name): |
| 62 with open(file_name) as f: | 63 with open(file_name) as f: |
| 63 return f.read() | 64 return f.read() |
| 64 | 65 |
| 65 | 66 |
| 66 def MSub(rexp, replacement, text): | 67 def MSub(rexp, replacement, text): |
| 67 return re.sub(rexp, replacement, text, flags=re.MULTILINE) | 68 return re.sub(rexp, replacement, text, flags=re.MULTILINE) |
| 68 | 69 |
| 69 | 70 |
| 71 def Fill80(line): | |
| 72 return textwrap.fill(line, width=80, initial_indent=" ", | |
| 73 subsequent_indent=" ") | |
| 74 | |
| 75 | |
| 70 def GetLastChangeLogEntries(change_log_file): | 76 def GetLastChangeLogEntries(change_log_file): |
| 71 result = [] | 77 result = [] |
| 72 for line in LinesInFile(change_log_file): | 78 for line in LinesInFile(change_log_file): |
| 73 if re.search(r"^\d{4}-\d{2}-\d{2}:", line) and result: break | 79 if re.search(r"^\d{4}-\d{2}-\d{2}:", line) and result: break |
| 74 result.append(line) | 80 result.append(line) |
| 75 return "".join(result) | 81 return "".join(result) |
| 76 | 82 |
| 77 | 83 |
| 78 def MakeChangeLogBody(commit_generator): | 84 def MakeChangeLogBody(commit_generator): |
| 79 result = "" | 85 result = "" |
| 80 for (title, body, author) in commit_generator(): | 86 for (title, body, author) in commit_generator(): |
| 81 # Add the commit's title line. | 87 # Add the commit's title line. |
| 82 result += "%s\n" % title.rstrip() | 88 result += "%s\n" % title.rstrip() |
| 83 | 89 |
| 84 # Grep for "BUG=xxxx" lines in the commit message and convert them to | 90 # Add bug references. |
| 85 # "(issue xxxx)". | 91 result += MakeChangeLogBugReference(body) |
| 86 out = body.splitlines() | |
| 87 out = filter(lambda x: re.search(r"^BUG=", x), out) | |
| 88 out = filter(lambda x: not re.search(r"BUG=$", x), out) | |
| 89 out = filter(lambda x: not re.search(r"BUG=none$", x), out) | |
| 90 | |
| 91 # TODO(machenbach): Handle multiple entries (e.g. BUG=123, 234). | |
| 92 def FormatIssue(text): | |
| 93 text = re.sub(r"BUG=v8:(.*)$", r"(issue \1)", text) | |
| 94 text = re.sub(r"BUG=chromium:(.*)$", r"(Chromium issue \1)", text) | |
| 95 text = re.sub(r"BUG=(.*)$", r"(Chromium issue \1)", text) | |
| 96 return " %s\n" % text | |
| 97 | |
| 98 for line in map(FormatIssue, out): | |
| 99 result += line | |
| 100 | 92 |
| 101 # Append the commit's author for reference. | 93 # Append the commit's author for reference. |
| 102 result += "%s\n\n" % author.rstrip() | 94 result += "%s\n\n" % author.rstrip() |
| 103 return result | 95 return result |
| 104 | 96 |
| 105 | 97 |
| 98 def MakeChangeLogBugReference(body): | |
| 99 # Grep for "BUG=xxxx" lines in the commit message and convert them to | |
| 100 # "(issue xxxx)". | |
| 101 out = body.splitlines() | |
| 102 out = filter(lambda x: re.search(r"^[ \t]*BUG[ \t]*=", x), out) | |
|
Jakob Kummerow
2013/11/19 13:39:29
I don't think we need any of these three "filter"
Michael Achenbach
2013/11/19 15:02:57
Done.
| |
| 103 out = filter(lambda x: not re.search(r"BUG[ \t]*=[ \t]*$", x), out) | |
| 104 out = filter(lambda x: not re.search(r"BUG[ \t]*=[ \t]*none[ \t]*$", x), out) | |
| 105 | |
| 106 crbugs = [] | |
| 107 v8bugs = [] | |
| 108 | |
| 109 def AddSafe(bugs, bug): | |
|
Jakob Kummerow
2013/11/19 13:39:29
I think you don't need this function at all, if be
Michael Achenbach
2013/11/19 15:02:57
Done.
| |
| 110 try: | |
| 111 bugs.append(int(bug)) | |
| 112 except ValueError: | |
| 113 pass | |
| 114 | |
| 115 def AddIssues(text): | |
| 116 ref = re.match(r"^[ \t]*BUG[ \t]*=[ \t]*(.*?)[ \t]*$", text) | |
|
Jakob Kummerow
2013/11/19 13:39:29
I think the regex can be simplified to:
r"^[ \t]*
Michael Achenbach
2013/11/19 15:02:57
Regarding the inner whitespace I had https://code.
| |
| 117 if not ref: | |
| 118 return | |
| 119 for bug in ref.group(1).split(","): | |
| 120 bug = bug.strip() | |
| 121 match = re.match(r"^v8[ \t]*:[ \t]*(.*)$", bug) | |
|
Jakob Kummerow
2013/11/19 13:39:29
similarly, we don't need to support whitespace aro
Michael Achenbach
2013/11/19 15:02:57
Done.
| |
| 122 if match: AddSafe(v8bugs, match.group(1)) | |
| 123 else: | |
| 124 match = re.match(r"^(?:chromium[ \t]*:)?[ \t]*(.*)$", bug) | |
| 125 if match: AddSafe(crbugs, match.group(1)) | |
| 126 | |
| 127 # Add issues to crbugs and v8bugs. | |
| 128 map(AddIssues, out) | |
| 129 | |
| 130 # Filter duplicates, sort, stringify. | |
| 131 crbugs = map(str, sorted(set(crbugs))) | |
| 132 v8bugs = map(str, sorted(set(v8bugs))) | |
| 133 | |
| 134 bug_groups = [] | |
| 135 def FormatIssues(prefix, bugs): | |
| 136 if len(bugs) > 0: | |
| 137 plural = "s" if len(bugs) > 1 else "" | |
| 138 bug_groups.append("%sissue%s %s" % (prefix, plural, ", ".join(bugs))) | |
| 139 | |
| 140 FormatIssues("Chromium ", crbugs) | |
| 141 FormatIssues("", v8bugs) | |
|
Jakob Kummerow
2013/11/19 13:39:29
V8 bugs first, please :-)
Michael Achenbach
2013/11/19 15:02:57
Done. That required some test changes...
| |
| 142 | |
| 143 if len(bug_groups) > 0: | |
| 144 # Format with 8 characters indentation and max 80 character lines. | |
| 145 return "%s\n" % Fill80("(%s)" % ", ".join(bug_groups)) | |
| 146 else: | |
| 147 return "" | |
| 148 | |
| 149 | |
| 106 # Some commands don't like the pipe, e.g. calling vi from within the script or | 150 # Some commands don't like the pipe, e.g. calling vi from within the script or |
| 107 # from subscripts like git cl upload. | 151 # from subscripts like git cl upload. |
| 108 def Command(cmd, args="", prefix="", pipe=True): | 152 def Command(cmd, args="", prefix="", pipe=True): |
| 109 cmd_line = "%s %s %s" % (prefix, cmd, args) | 153 cmd_line = "%s %s %s" % (prefix, cmd, args) |
| 110 print "Command: %s" % cmd_line | 154 print "Command: %s" % cmd_line |
| 111 try: | 155 try: |
| 112 if pipe: | 156 if pipe: |
| 113 return subprocess.check_output(cmd_line, shell=True) | 157 return subprocess.check_output(cmd_line, shell=True) |
| 114 else: | 158 else: |
| 115 return subprocess.check_call(cmd_line, shell=True) | 159 return subprocess.check_call(cmd_line, shell=True) |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 step.SetNumber(number) | 385 step.SetNumber(number) |
| 342 step.SetConfig(config) | 386 step.SetConfig(config) |
| 343 step.SetOptions(options) | 387 step.SetOptions(options) |
| 344 step.SetState(state) | 388 step.SetState(state) |
| 345 step.SetSideEffectHandler(side_effect_handler) | 389 step.SetSideEffectHandler(side_effect_handler) |
| 346 steps.append(step) | 390 steps.append(step) |
| 347 number += 1 | 391 number += 1 |
| 348 | 392 |
| 349 for step in steps[options.s:]: | 393 for step in steps[options.s:]: |
| 350 step.Run() | 394 step.Run() |
| OLD | NEW |