| Index: tools/push-to-trunk/push_to_trunk.py
|
| diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py
|
| index 9f72cd2d6dafa4cbbfb404f2668a7591f205fb00..24dfb676805a29cbdca11166c3fdfe71e9c338b5 100755
|
| --- a/tools/push-to-trunk/push_to_trunk.py
|
| +++ b/tools/push-to-trunk/push_to_trunk.py
|
| @@ -53,18 +53,17 @@ CONFIG = {
|
|
|
|
|
| class Preparation(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Preparation.")
|
| + MESSAGE = "Preparation."
|
|
|
| def RunStep(self):
|
| self.InitialEnvironmentChecks()
|
| self.CommonPrepare()
|
| + self.PrepareBranch()
|
| self.DeleteBranch(self.Config(TRUNKBRANCH))
|
|
|
|
|
| class FreshBranch(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Create a fresh branch.")
|
| + MESSAGE = "Create a fresh branch."
|
|
|
| def RunStep(self):
|
| args = "checkout -b %s svn/bleeding_edge" % self.Config(BRANCHNAME)
|
| @@ -73,8 +72,7 @@ class FreshBranch(Step):
|
|
|
|
|
| class DetectLastPush(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Detect commit ID of last push to trunk.")
|
| + MESSAGE = "Detect commit ID of last push to trunk."
|
|
|
| def RunStep(self):
|
| last_push = (self._options.l or
|
| @@ -91,8 +89,7 @@ class DetectLastPush(Step):
|
|
|
|
|
| class PrepareChangeLog(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Prepare raw ChangeLog entry.")
|
| + MESSAGE = "Prepare raw ChangeLog entry."
|
|
|
| def RunStep(self):
|
| self.RestoreIfUnset("last_push")
|
| @@ -110,58 +107,50 @@ class PrepareChangeLog(Step):
|
|
|
| args = "log %s..HEAD --format=%%H" % self._state["last_push"]
|
| commits = self.Git(args).strip()
|
| - for commit in commits.splitlines():
|
| - # Get the commit's title line.
|
| - args = "log -1 %s --format=\"%%w(80,8,8)%%s\"" % commit
|
| - title = "%s\n" % self.Git(args).rstrip()
|
| - AppendToFile(title, self.Config(CHANGELOG_ENTRY_FILE))
|
| -
|
| - # Grep for "BUG=xxxx" lines in the commit message and convert them to
|
| - # "(issue xxxx)".
|
| - out = self.Git("log -1 %s --format=\"%%B\"" % commit).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):
|
| - AppendToFile(line, self.Config(CHANGELOG_ENTRY_FILE))
|
| -
|
| - # Append the commit's author for reference.
|
| - args = "log -1 %s --format=\"%%w(80,8,8)(%%an)\"" % commit
|
| - author = self.Git(args).rstrip()
|
| - AppendToFile("%s\n\n" % author, self.Config(CHANGELOG_ENTRY_FILE))
|
| -
|
| - msg = " Performance and stability improvements on all platforms.\n"
|
| +
|
| + # Cache raw commit messages.
|
| + commit_messages = [
|
| + [
|
| + self.Git("log -1 %s --format=\"%%s\"" % commit),
|
| + self.Git("log -1 %s --format=\"%%B\"" % commit),
|
| + self.Git("log -1 %s --format=\"%%an\"" % commit),
|
| + ] for commit in commits.splitlines()
|
| + ]
|
| +
|
| + # Auto-format commit messages.
|
| + body = MakeChangeLogBody(commit_messages, auto_format=True)
|
| + AppendToFile(body, self.Config(CHANGELOG_ENTRY_FILE))
|
| +
|
| + msg = (" Performance and stability improvements on all platforms."
|
| + "\n#\n# The change log above is auto-generated. Please review if "
|
| + "all relevant\n# commit messages from the list below are included."
|
| + "\n# All lines starting with # will be stripped.\n#\n")
|
| AppendToFile(msg, self.Config(CHANGELOG_ENTRY_FILE))
|
|
|
| + # Include unformatted commit messages as a reference in a comment.
|
| + comment_body = MakeComment(MakeChangeLogBody(commit_messages))
|
| + AppendToFile(comment_body, self.Config(CHANGELOG_ENTRY_FILE))
|
| +
|
| +
|
| class EditChangeLog(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Edit ChangeLog entry.")
|
| + MESSAGE = "Edit ChangeLog entry."
|
|
|
| def RunStep(self):
|
| print ("Please press <Return> to have your EDITOR open the ChangeLog "
|
| "entry, then edit its contents to your liking. When you're done, "
|
| "save the file and exit your EDITOR. ")
|
| - self.ReadLine()
|
| + self.ReadLine(default="")
|
|
|
| + # TODO(machenbach): Don't use EDITOR in forced mode as soon as script is
|
| + # well tested.
|
| self.Editor(self.Config(CHANGELOG_ENTRY_FILE))
|
| handle, new_changelog = tempfile.mkstemp()
|
| os.close(handle)
|
|
|
| - # (1) Eliminate tabs, (2) fix too little and (3) too much indentation, and
|
| - # (4) eliminate trailing whitespace.
|
| + # Strip comments and reformat with correct indentation.
|
| changelog_entry = FileToText(self.Config(CHANGELOG_ENTRY_FILE)).rstrip()
|
| - changelog_entry = MSub(r"\t", r" ", changelog_entry)
|
| - changelog_entry = MSub(r"^ {1,7}([^ ])", r" \1", changelog_entry)
|
| - changelog_entry = MSub(r"^ {9,80}([^ ])", r" \1", changelog_entry)
|
| - changelog_entry = MSub(r" +$", r"", changelog_entry)
|
| + changelog_entry = StripComments(changelog_entry)
|
| + changelog_entry = "\n".join(map(Fill80, changelog_entry.splitlines()))
|
|
|
| if changelog_entry == "":
|
| self.Die("Empty ChangeLog entry.")
|
| @@ -176,8 +165,7 @@ class EditChangeLog(Step):
|
|
|
|
|
| class IncrementVersion(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Increment version number.")
|
| + MESSAGE = "Increment version number."
|
|
|
| def RunStep(self):
|
| self.RestoreIfUnset("build")
|
| @@ -199,8 +187,7 @@ class IncrementVersion(Step):
|
|
|
|
|
| class CommitLocal(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Commit to local branch.")
|
| + MESSAGE = "Commit to local branch."
|
|
|
| def RunStep(self):
|
| self.RestoreVersionIfUnset("new_")
|
| @@ -214,8 +201,7 @@ class CommitLocal(Step):
|
|
|
|
|
| class CommitRepository(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Commit to the repository.")
|
| + MESSAGE = "Commit to the repository."
|
|
|
| def RunStep(self):
|
| self.WaitForLGTM()
|
| @@ -224,14 +210,13 @@ class CommitRepository(Step):
|
| TextToFile(GetLastChangeLogEntries(self.Config(CHANGELOG_FILE)),
|
| self.Config(CHANGELOG_ENTRY_FILE))
|
|
|
| - if self.Git("cl dcommit -v", "PRESUBMIT_TREE_CHECK=\"skip\"") is None:
|
| + if self.Git("cl dcommit -f", "PRESUBMIT_TREE_CHECK=\"skip\"") is None:
|
| self.Die("'git cl dcommit' failed, please try again.")
|
|
|
|
|
| class StragglerCommits(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Fetch straggler commits that sneaked in since this "
|
| - "script was started.")
|
| + MESSAGE = ("Fetch straggler commits that sneaked in since this script was "
|
| + "started.")
|
|
|
| def RunStep(self):
|
| if self.Git("svn fetch") is None:
|
| @@ -244,8 +229,7 @@ class StragglerCommits(Step):
|
|
|
|
|
| class SquashCommits(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Squash commits into one.")
|
| + MESSAGE = "Squash commits into one."
|
|
|
| def RunStep(self):
|
| # Instead of relying on "git rebase -i", we'll just create a diff, because
|
| @@ -287,8 +271,7 @@ class SquashCommits(Step):
|
|
|
|
|
| class NewBranch(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Create a new branch from trunk.")
|
| + MESSAGE = "Create a new branch from trunk."
|
|
|
| def RunStep(self):
|
| if self.Git("checkout -b %s svn/trunk" % self.Config(TRUNKBRANCH)) is None:
|
| @@ -297,8 +280,7 @@ class NewBranch(Step):
|
|
|
|
|
| class ApplyChanges(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Apply squashed changes.")
|
| + MESSAGE = "Apply squashed changes."
|
|
|
| def RunStep(self):
|
| self.ApplyPatch(self.Config(PATCH_FILE))
|
| @@ -306,8 +288,7 @@ class ApplyChanges(Step):
|
|
|
|
|
| class SetVersion(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Set correct version for trunk.")
|
| + MESSAGE = "Set correct version for trunk."
|
|
|
| def RunStep(self):
|
| self.RestoreVersionIfUnset()
|
| @@ -328,8 +309,7 @@ class SetVersion(Step):
|
|
|
|
|
| class CommitTrunk(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Commit to local trunk branch.")
|
| + MESSAGE = "Commit to local trunk branch."
|
|
|
| def RunStep(self):
|
| self.Git("add \"%s\"" % self.Config(VERSION_FILE))
|
| @@ -339,8 +319,7 @@ class CommitTrunk(Step):
|
|
|
|
|
| class SanityCheck(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Sanity check.")
|
| + MESSAGE = "Sanity check."
|
|
|
| def RunStep(self):
|
| if not self.Confirm("Please check if your local checkout is sane: Inspect "
|
| @@ -350,8 +329,7 @@ class SanityCheck(Step):
|
|
|
|
|
| class CommitSVN(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Commit to SVN.")
|
| + MESSAGE = "Commit to SVN."
|
|
|
| def RunStep(self):
|
| result = self.Git("svn dcommit 2>&1")
|
| @@ -368,6 +346,7 @@ class CommitSVN(Step):
|
| print("Sorry, grepping for the SVN revision failed. Please look for it "
|
| "in the last command's output above and provide it manually (just "
|
| "the number, without the leading \"r\").")
|
| + self.DieInForcedMode("Can't prompt in forced mode.")
|
| while not trunk_revision:
|
| print "> ",
|
| trunk_revision = self.ReadLine()
|
| @@ -375,8 +354,7 @@ class CommitSVN(Step):
|
|
|
|
|
| class TagRevision(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Tag the new revision.")
|
| + MESSAGE = "Tag the new revision."
|
|
|
| def RunStep(self):
|
| self.RestoreVersionIfUnset()
|
| @@ -388,12 +366,13 @@ class TagRevision(Step):
|
|
|
|
|
| class CheckChromium(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Ask for chromium checkout.")
|
| + MESSAGE = "Ask for chromium checkout."
|
|
|
| def Run(self):
|
| chrome_path = self._options.c
|
| if not chrome_path:
|
| + self.DieInForcedMode("Please specify the path to a Chromium checkout in "
|
| + "forced mode.")
|
| print ("Do you have a \"NewGit\" Chromium checkout and want "
|
| "this script to automate creation of the roll CL? If yes, enter the "
|
| "path to (and including) the \"src\" directory here, otherwise just "
|
| @@ -403,8 +382,8 @@ class CheckChromium(Step):
|
|
|
|
|
| class SwitchChromium(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Switch to Chromium checkout.", requires="chrome_path")
|
| + MESSAGE = "Switch to Chromium checkout."
|
| + REQUIRES = "chrome_path"
|
|
|
| def RunStep(self):
|
| v8_path = os.getcwd()
|
| @@ -420,9 +399,8 @@ class SwitchChromium(Step):
|
|
|
|
|
| class UpdateChromiumCheckout(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Update the checkout and create a new branch.",
|
| - requires="chrome_path")
|
| + MESSAGE = "Update the checkout and create a new branch."
|
| + REQUIRES = "chrome_path"
|
|
|
| def RunStep(self):
|
| os.chdir(self._state["chrome_path"])
|
| @@ -438,8 +416,8 @@ class UpdateChromiumCheckout(Step):
|
|
|
|
|
| class UploadCL(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Create and upload CL.", requires="chrome_path")
|
| + MESSAGE = "Create and upload CL."
|
| + REQUIRES = "chrome_path"
|
|
|
| def RunStep(self):
|
| os.chdir(self._state["chrome_path"])
|
| @@ -456,19 +434,25 @@ class UploadCL(Step):
|
| ver = "%s.%s.%s" % (self._state["major"],
|
| self._state["minor"],
|
| self._state["build"])
|
| - print "Please enter the email address of a reviewer for the roll CL: ",
|
| - rev = self.ReadLine()
|
| + if self._options and self._options.r:
|
| + print "Using account %s for review." % self._options.r
|
| + rev = self._options.r
|
| + else:
|
| + print "Please enter the email address of a reviewer for the roll CL: ",
|
| + self.DieInForcedMode("A reviewer must be specified in forced mode.")
|
| + rev = self.ReadLine()
|
| args = "commit -am \"Update V8 to version %s.\n\nTBR=%s\"" % (ver, rev)
|
| if self.Git(args) is None:
|
| self.Die("'git commit' failed.")
|
| - if self.Git("cl upload --send-mail", pipe=False) is None:
|
| + force_flag = " -f" if self._options.f else ""
|
| + if self.Git("cl upload --send-mail%s" % force_flag, pipe=False) is None:
|
| self.Die("'git cl upload' failed, please try again.")
|
| print "CL uploaded."
|
|
|
|
|
| class SwitchV8(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Returning to V8 checkout.", requires="chrome_path")
|
| + MESSAGE = "Returning to V8 checkout."
|
| + REQUIRES = "chrome_path"
|
|
|
| def RunStep(self):
|
| self.RestoreIfUnset("v8_path")
|
| @@ -476,8 +460,7 @@ class SwitchV8(Step):
|
|
|
|
|
| class CleanUp(Step):
|
| - def __init__(self):
|
| - Step.__init__(self, "Done!")
|
| + MESSAGE = "Done!"
|
|
|
| def RunStep(self):
|
| self.RestoreVersionIfUnset()
|
| @@ -502,9 +485,9 @@ class CleanUp(Step):
|
| self.Git("branch -D %s" % self.Config(TRUNKBRANCH))
|
|
|
|
|
| -def RunScript(config,
|
| - options,
|
| - side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
|
| +def RunPushToTrunk(config,
|
| + options,
|
| + side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER):
|
| step_classes = [
|
| Preparation,
|
| FreshBranch,
|
| @@ -532,36 +515,25 @@ def RunScript(config,
|
| CleanUp,
|
| ]
|
|
|
| - state = {}
|
| - steps = []
|
| - number = 0
|
| -
|
| - for step_class in step_classes:
|
| - # TODO(machenbach): Factory methods.
|
| - step = step_class()
|
| - step.SetNumber(number)
|
| - step.SetConfig(config)
|
| - step.SetOptions(options)
|
| - step.SetState(state)
|
| - step.SetSideEffectHandler(side_effect_handler)
|
| - steps.append(step)
|
| - number += 1
|
| -
|
| - for step in steps[options.s:]:
|
| - step.Run()
|
| + RunScript(step_classes, config, options, side_effect_handler)
|
|
|
|
|
| def BuildOptions():
|
| result = optparse.OptionParser()
|
| - result.add_option("-s", "--step", dest="s",
|
| - help="Specify the step where to start work. Default: 0.",
|
| - default=0, type="int")
|
| - result.add_option("-l", "--last-push", dest="l",
|
| - help=("Manually specify the git commit ID "
|
| - "of the last push to trunk."))
|
| result.add_option("-c", "--chromium", dest="c",
|
| help=("Specify the path to your Chromium src/ "
|
| "directory to automate the V8 roll."))
|
| + result.add_option("-f", "--force", dest="f",
|
| + help="Don't prompt the user.",
|
| + default=False, action="store_true")
|
| + result.add_option("-l", "--last-push", dest="l",
|
| + help=("Manually specify the git commit ID "
|
| + "of the last push to trunk."))
|
| + result.add_option("-r", "--reviewer", dest="r",
|
| + help=("Specify the account name to be used for reviews."))
|
| + result.add_option("-s", "--step", dest="s",
|
| + help="Specify the step where to start work. Default: 0.",
|
| + default=0, type="int")
|
| return result
|
|
|
|
|
| @@ -578,7 +550,7 @@ def Main():
|
| if not ProcessOptions(options):
|
| parser.print_help()
|
| return 1
|
| - RunScript(CONFIG, options)
|
| + RunPushToTrunk(CONFIG, options)
|
|
|
| if __name__ == "__main__":
|
| sys.exit(Main())
|
|
|