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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/push-to-trunk/push_to_trunk.py » ('j') | tools/push-to-trunk/push_to_trunk.py » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/push-to-trunk/common_includes.py
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index 06b7ebe53a3c3655e41048c186bef308b59402c0..545fab382fe6a05f59b506cc906a58c217138333 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -30,6 +30,7 @@ import os
import re
import subprocess
import sys
+import textwrap
PERSISTFILE_BASENAME = "PERSISTFILE_BASENAME"
TEMP_BRANCH = "TEMP_BRANCH"
@@ -67,6 +68,11 @@ def MSub(rexp, replacement, text):
return re.sub(rexp, replacement, text, flags=re.MULTILINE)
+def Fill80(line):
+ return textwrap.fill(line, width=80, initial_indent=" ",
+ subsequent_indent=" ")
+
+
def GetLastChangeLogEntries(change_log_file):
result = []
for line in LinesInFile(change_log_file):
@@ -81,28 +87,66 @@ def MakeChangeLogBody(commit_generator):
# Add the commit's title line.
result += "%s\n" % title.rstrip()
- # Grep for "BUG=xxxx" lines in the commit message and convert them to
- # "(issue xxxx)".
- out = body.splitlines()
- out = filter(lambda x: re.search(r"^BUG=", x), out)
- out = filter(lambda x: not re.search(r"BUG=$", x), out)
- out = filter(lambda x: not re.search(r"BUG=none$", x), out)
-
- # TODO(machenbach): Handle multiple entries (e.g. BUG=123, 234).
- def FormatIssue(text):
- text = re.sub(r"BUG=v8:(.*)$", r"(issue \1)", text)
- text = re.sub(r"BUG=chromium:(.*)$", r"(Chromium issue \1)", text)
- text = re.sub(r"BUG=(.*)$", r"(Chromium issue \1)", text)
- return " %s\n" % text
-
- for line in map(FormatIssue, out):
- result += line
+ # Add bug references.
+ result += MakeChangeLogBugReference(body)
# Append the commit's author for reference.
result += "%s\n\n" % author.rstrip()
return result
+def MakeChangeLogBugReference(body):
+ # Grep for "BUG=xxxx" lines in the commit message and convert them to
+ # "(issue xxxx)".
+ out = body.splitlines()
+ out = filter(lambda x: re.search(r"^[ \t]*BUG[ \t]*=", x), out)
+ out = filter(lambda x: not re.search(r"BUG[ \t]*=[ \t]*$", x), out)
+ out = filter(lambda x: not re.search(r"BUG[ \t]*=[ \t]*none[ \t]*$", x), out)
+
+ crbugs = []
+ v8bugs = []
+
+ def AddSafe(bugs, bug):
+ try:
+ bugs.append(int(bug))
+ except ValueError:
+ pass
+
+ def AddIssues(text):
+ ref = re.match(r"^[ \t]*BUG[ \t]*=[ \t]*(.*?)[ \t]*$", text)
+ if not ref:
+ return
+ for bug in ref.group(1).split(","):
+ bug = bug.strip()
+ match = re.match(r"^v8[ \t]*:[ \t]*(.*)$", bug)
+ if match: AddSafe(v8bugs, match.group(1))
+ else:
+ match = re.match(r"^(?:chromium[ \t]*:)?[ \t]*(.*)$", bug)
+ if match: AddSafe(crbugs, match.group(1))
+
+ # Add issues to crbugs and v8bugs.
+ map(AddIssues, out)
+
+ # Filter duplicates, sort, stringify.
+ crbugs = map(str, sorted(set(crbugs)))
+ v8bugs = map(str, sorted(set(v8bugs)))
+
+ bug_groups = []
+ def FormatIssues(prefix, bugs):
+ if len(bugs) > 0:
+ plural = "s" if len(bugs) > 1 else ""
+ bug_groups.append("%sissue%s %s" % (prefix, plural, ", ".join(bugs)))
+
+ FormatIssues("Chromium ", crbugs)
+ FormatIssues("", v8bugs)
+
+ if len(bug_groups) > 0:
+ # Format with 8 characters indentation and max 80 character lines.
+ return "%s\n" % Fill80("(%s)" % ", ".join(bug_groups))
+ else:
+ return ""
+
+
# Some commands don't like the pipe, e.g. calling vi from within the script or
# from subscripts like git cl upload.
def Command(cmd, args="", prefix="", pipe=True):
@@ -132,6 +176,7 @@ class Step(object):
def __init__(self, text="", requires=None):
self._text = text
self._number = -1
+ self._options = None
self._requires = requires
self._side_effect_handler = DEFAULT_SIDE_EFFECT_HANDLER
@@ -168,8 +213,13 @@ class Step(object):
def RunStep(self):
raise NotImplementedError
- def ReadLine(self):
- return self._side_effect_handler.ReadLine()
+ def ReadLine(self, default=None):
+ # Don't prompt in forced mode.
+ if self._options and self._options.f and default is not None:
+ print "%s (forced)" % default
+ return default
+ else:
+ return self._side_effect_handler.ReadLine()
def Git(self, args="", prefix="", pipe=True):
return self._side_effect_handler.Command("git", args, prefix, pipe)
@@ -184,9 +234,14 @@ class Step(object):
print "Exiting"
raise Exception(msg)
+ def DieInForcedMode(self, msg=""):
+ if self._options and self._options.f:
+ msg = msg or "Not implemented in forced mode."
+ self.Die(msg)
+
def Confirm(self, msg):
print "%s [Y/n] " % msg,
- answer = self.ReadLine()
+ answer = self.ReadLine(default="Y")
return answer == "" or answer == "Y" or answer == "y"
def DeleteBranch(self, name):
@@ -220,6 +275,8 @@ class Step(object):
if not os.path.exists(self._config[DOT_GIT_LOCATION]):
self.Die("This is not a git checkout, this script won't work for you.")
+ # TODO(machenbach): Don't use EDITOR in forced mode as soon as script is
+ # well tested.
# Cancel if EDITOR is unset or not executable.
if (not os.environ.get("EDITOR") or
Command("which", os.environ["EDITOR"]) is None):
@@ -291,6 +348,8 @@ class Step(object):
answer = ""
while answer != "LGTM":
print "> ",
+ # TODO(machenbach): Add default="LGTM" to avoid prompt when script is
+ # well tested and when prepare push cl has TBR flag.
answer = self.ReadLine()
if answer != "LGTM":
print "That was not 'LGTM'."
@@ -299,6 +358,7 @@ class Step(object):
print("Applying the patch \"%s\" failed. Either type \"ABORT<Return>\", "
"or resolve the conflicts, stage *all* touched files with "
"'git add', and type \"RESOLVED<Return>\"")
+ self.DieInForcedMode()
answer = ""
while answer != "RESOLVED":
if answer == "ABORT":
@@ -320,8 +380,13 @@ class UploadStep(Step):
Step.__init__(self, "Upload for code review.")
def RunStep(self):
- print "Please enter the email address of a V8 reviewer for your patch: ",
- reviewer = self.ReadLine()
+ if self._options and self._options.r:
+ print "Using account %s for review." % self._options.r
+ reviewer = self._options.r
+ else:
+ print "Please enter the email address of a V8 reviewer for your patch: ",
+ self.DieInForcedMode("A reviewer must be specified in forced mode.")
+ reviewer = self.ReadLine()
args = "cl upload -r \"%s\" --send-mail" % reviewer
if self.Git(args,pipe=False) is None:
self.Die("'git cl upload' failed, please try again.")
« no previous file with comments | « no previous file | tools/push-to-trunk/push_to_trunk.py » ('j') | tools/push-to-trunk/push_to_trunk.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698