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

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

Issue 169843002: Retrieve bleeding edge push revision from trunk commit message. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add the same feature to auto-roll. 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
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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 TEMP_BRANCH: "prepare-push-temporary-branch-created-by-script", 44 TEMP_BRANCH: "prepare-push-temporary-branch-created-by-script",
45 DOT_GIT_LOCATION: ".git", 45 DOT_GIT_LOCATION: ".git",
46 VERSION_FILE: "src/version.cc", 46 VERSION_FILE: "src/version.cc",
47 CHANGELOG_FILE: "ChangeLog", 47 CHANGELOG_FILE: "ChangeLog",
48 CHANGELOG_ENTRY_FILE: "/tmp/v8-push-to-trunk-tempfile-changelog-entry", 48 CHANGELOG_ENTRY_FILE: "/tmp/v8-push-to-trunk-tempfile-changelog-entry",
49 PATCH_FILE: "/tmp/v8-push-to-trunk-tempfile-patch-file", 49 PATCH_FILE: "/tmp/v8-push-to-trunk-tempfile-patch-file",
50 COMMITMSG_FILE: "/tmp/v8-push-to-trunk-tempfile-commitmsg", 50 COMMITMSG_FILE: "/tmp/v8-push-to-trunk-tempfile-commitmsg",
51 DEPS_FILE: "DEPS", 51 DEPS_FILE: "DEPS",
52 } 52 }
53 53
54 PUSH_MESSAGE_SUFFIX = " (based on bleeding_edge revision r%d)"
55 PUSH_MESSAGE_RE = re.compile(r".* \(based on bleeding_edge revision r(\d+)\)$")
56
54 57
55 class PushToTrunkOptions(CommonOptions): 58 class PushToTrunkOptions(CommonOptions):
56 @staticmethod 59 @staticmethod
57 def MakeForcedOptions(author, reviewer, chrome_path): 60 def MakeForcedOptions(author, reviewer, chrome_path):
58 """Convenience wrapper.""" 61 """Convenience wrapper."""
59 class Options(object): 62 class Options(object):
60 pass 63 pass
61 options = Options() 64 options = Options()
62 options.s = 0 65 options.s = 0
63 options.l = None 66 options.l = None
67 options.b = None
Jakob Kummerow 2014/02/19 12:44:49 I hope it's on your to-do list to give all these g
Michael Achenbach 2014/02/19 13:23:03 yap
64 options.f = True 68 options.f = True
65 options.m = False 69 options.m = False
66 options.c = chrome_path 70 options.c = chrome_path
67 options.a = author 71 options.a = author
68 return PushToTrunkOptions(options) 72 return PushToTrunkOptions(options)
69 73
70 def __init__(self, options): 74 def __init__(self, options):
71 super(PushToTrunkOptions, self).__init__(options, options.m) 75 super(PushToTrunkOptions, self).__init__(options, options.m)
72 self.requires_editor = not options.f 76 self.requires_editor = not options.f
73 self.wait_for_lgtm = not options.f 77 self.wait_for_lgtm = not options.f
74 self.tbr_commit = not options.m 78 self.tbr_commit = not options.m
75 self.l = options.l 79 self.l = options.l
76 self.reviewer = options.reviewer 80 self.reviewer = options.reviewer
77 self.c = options.c 81 self.c = options.c
82 self.b = getattr(options, 'b', None)
Jakob Kummerow 2014/02/19 12:44:49 Instead of using getattr(), the default value shou
Michael Achenbach 2014/02/19 13:23:03 The whole option design will get a new face in a f
78 self.author = getattr(options, 'a', None) 83 self.author = getattr(options, 'a', None)
79 84
80 class Preparation(Step): 85 class Preparation(Step):
81 MESSAGE = "Preparation." 86 MESSAGE = "Preparation."
82 87
83 def RunStep(self): 88 def RunStep(self):
84 self.InitialEnvironmentChecks() 89 self.InitialEnvironmentChecks()
85 self.CommonPrepare() 90 self.CommonPrepare()
86 self.PrepareBranch() 91 self.PrepareBranch()
87 self.DeleteBranch(self.Config(TRUNKBRANCH)) 92 self.DeleteBranch(self.Config(TRUNKBRANCH))
88 93
89 94
90 class FreshBranch(Step): 95 class FreshBranch(Step):
91 MESSAGE = "Create a fresh branch." 96 MESSAGE = "Create a fresh branch."
92 97
93 def RunStep(self): 98 def RunStep(self):
94 args = "checkout -b %s svn/bleeding_edge" % self.Config(BRANCHNAME) 99 args = "checkout -b %s svn/bleeding_edge" % self.Config(BRANCHNAME)
95 if self.Git(args) is None: 100 if self.Git(args) is None:
96 self.Die("Creating branch %s failed." % self.Config(BRANCHNAME)) 101 self.Die("Creating branch %s failed." % self.Config(BRANCHNAME))
97 102
98 103
99 class DetectLastPush(Step): 104 class DetectLastPush(Step):
100 MESSAGE = "Detect commit ID of last push to trunk." 105 MESSAGE = "Detect commit ID of last push to trunk."
101 106
102 def RunStep(self): 107 def RunStep(self):
103 last_push = (self._options.l or 108 push_pattern = "^Version [[:digit:]]*\.[[:digit:]]*\.[[:digit:]]* (based"
Jakob Kummerow 2014/02/19 12:44:49 For increased correctness, s/*/+/
Michael Achenbach 2014/02/19 13:23:03 There's no + in grep. At least on my command-line,
104 self.Git("log -1 --format=%H ChangeLog").strip()) 109 args = "log -1 --format=%%H --grep=\"%s\" svn/trunk" % push_pattern
110 last_push_trunk = self._options.l or self.Git(args).strip()
105 while True: 111 while True:
106 # Print assumed commit, circumventing git's pager. 112 # Print assumed commit, circumventing git's pager.
107 print self.Git("log -1 %s" % last_push) 113 print self.Git("log -1 %s" % last_push_trunk)
108 if self.Confirm("Is the commit printed above the last push to trunk?"): 114 if self.Confirm("Is the commit printed above the last push to trunk?"):
109 break 115 break
110 args = "log -1 --format=%H %s^ ChangeLog" % last_push 116 args = ("log -1 --format=%H %s^ --grep=\"%s\""
Jakob Kummerow 2014/02/19 12:44:49 s/%H/%%H/ like above? Why has this worked before?
Michael Achenbach 2014/02/19 13:23:03 Done.
111 last_push = self.Git(args).strip() 117 % (last_push_trunk, push_pattern))
112 self.Persist("last_push", last_push) 118 last_push_trunk = self.Git(args).strip()
113 self._state["last_push"] = last_push 119
120 if self._options.b:
121 # Read the bleeding edge revision of the last push from a command-line
122 # option.
123 last_push_bleeding_edge = self._options.b
124 else:
125 # Retrieve the bleeding edge revision of the last push from the text in
126 # the push commit message.
127 args = "log -1 --format=%%s %s" % last_push_trunk
128 last_push_trunk_title = self.Git(args).strip()
129 last_push_be_svn = PUSH_MESSAGE_RE.match(last_push_trunk_title).group(1)
130 if not last_push_be_svn:
131 self.Die("Could not retrieve bleeding edge revision for trunk push %s"
132 % last_push_trunk)
133 args = "svn find-rev r%d" % int(last_push_be_svn)
Jakob Kummerow 2014/02/19 12:44:49 "%d" % int(some_string) is the complicated way of
Michael Achenbach 2014/02/19 13:23:03 Done.
134 last_push_bleeding_edge = self.Git(args).strip()
135 if not last_push_bleeding_edge:
136 self.Die("Could not retrieve bleeding edge git hash for trunk push %s"
137 % last_push_trunk)
138
139 # TODO(machenbach): last_push_trunk points to the svn revision on trunk.
140 # It is not used yet but we'll need it for retrieving the current version.
141 self.Persist("last_push_trunk", last_push_trunk)
142 self._state["last_push_trunk"] = last_push_trunk
143 # TODO(machenbach): This currently points to the prepare push revision that
144 # will be deprecated soon. After the deprecation it will point to the last
145 # bleeding_edge revision that went into the last push.
146 self.Persist("last_push_bleeding_edge", last_push_bleeding_edge)
147 self._state["last_push_bleeding_edge"] = last_push_bleeding_edge
114 148
115 149
116 class PrepareChangeLog(Step): 150 class PrepareChangeLog(Step):
117 MESSAGE = "Prepare raw ChangeLog entry." 151 MESSAGE = "Prepare raw ChangeLog entry."
118 152
119 def Reload(self, body): 153 def Reload(self, body):
120 """Attempts to reload the commit message from rietveld in order to allow 154 """Attempts to reload the commit message from rietveld in order to allow
121 late changes to the LOG flag. Note: This is brittle to future changes of 155 late changes to the LOG flag. Note: This is brittle to future changes of
122 the web page name or structure. 156 the web page name or structure.
123 """ 157 """
124 match = re.search(r"^Review URL: https://codereview\.chromium\.org/(\d+)$", 158 match = re.search(r"^Review URL: https://codereview\.chromium\.org/(\d+)$",
125 body, flags=re.M) 159 body, flags=re.M)
126 if match: 160 if match:
127 cl_url = "https://codereview.chromium.org/%s/description" % match.group(1) 161 cl_url = "https://codereview.chromium.org/%s/description" % match.group(1)
128 try: 162 try:
129 # Fetch from Rietveld but only retry once with one second delay since 163 # Fetch from Rietveld but only retry once with one second delay since
130 # there might be many revisions. 164 # there might be many revisions.
131 body = self.ReadURL(cl_url, wait_plan=[1]) 165 body = self.ReadURL(cl_url, wait_plan=[1])
132 except urllib2.URLError: 166 except urllib2.URLError:
133 pass 167 pass
134 return body 168 return body
135 169
136 def RunStep(self): 170 def RunStep(self):
137 self.RestoreIfUnset("last_push") 171 self.RestoreIfUnset("last_push_bleeding_edge")
138 172
139 # These version numbers are used again later for the trunk commit. 173 # These version numbers are used again later for the trunk commit.
140 self.ReadAndPersistVersion() 174 self.ReadAndPersistVersion()
141 175
142 date = self.GetDate() 176 date = self.GetDate()
143 self.Persist("date", date) 177 self.Persist("date", date)
144 output = "%s: Version %s.%s.%s\n\n" % (date, 178 output = "%s: Version %s.%s.%s\n\n" % (date,
145 self._state["major"], 179 self._state["major"],
146 self._state["minor"], 180 self._state["minor"],
147 self._state["build"]) 181 self._state["build"])
148 TextToFile(output, self.Config(CHANGELOG_ENTRY_FILE)) 182 TextToFile(output, self.Config(CHANGELOG_ENTRY_FILE))
149 183
150 args = "log %s..HEAD --format=%%H" % self._state["last_push"] 184 args = "log %s..HEAD --format=%%H" % self._state["last_push_bleeding_edge"]
151 commits = self.Git(args).strip() 185 commits = self.Git(args).strip()
152 186
153 # Cache raw commit messages. 187 # Cache raw commit messages.
154 commit_messages = [ 188 commit_messages = [
155 [ 189 [
156 self.Git("log -1 %s --format=\"%%s\"" % commit), 190 self.Git("log -1 %s --format=\"%%s\"" % commit),
157 self.Reload(self.Git("log -1 %s --format=\"%%B\"" % commit)), 191 self.Reload(self.Git("log -1 %s --format=\"%%B\"" % commit)),
158 self.Git("log -1 %s --format=\"%%an\"" % commit), 192 self.Git("log -1 %s --format=\"%%an\"" % commit),
159 ] for commit in commits.splitlines() 193 ] for commit in commits.splitlines()
160 ] 194 ]
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 text = FileToText(self.Config(CHANGELOG_ENTRY_FILE)) 328 text = FileToText(self.Config(CHANGELOG_ENTRY_FILE))
295 329
296 # Remove date and trailing white space. 330 # Remove date and trailing white space.
297 text = re.sub(r"^%s: " % self._state["date"], "", text.rstrip()) 331 text = re.sub(r"^%s: " % self._state["date"], "", text.rstrip())
298 332
299 # Retrieve svn revision for showing the used bleeding edge revision in the 333 # Retrieve svn revision for showing the used bleeding edge revision in the
300 # commit message. 334 # commit message.
301 args = "svn find-rev %s" % self._state["prepare_commit_hash"] 335 args = "svn find-rev %s" % self._state["prepare_commit_hash"]
302 svn_revision = self.Git(args).strip() 336 svn_revision = self.Git(args).strip()
303 self.Persist("svn_revision", svn_revision) 337 self.Persist("svn_revision", svn_revision)
304 text = MSub(r"^(Version \d+\.\d+\.\d+)$", 338 suffix = PUSH_MESSAGE_SUFFIX % int(svn_revision)
305 "\\1 (based on bleeding_edge revision r%s)" % svn_revision, 339 text = MSub(r"^(Version \d+\.\d+\.\d+)$", "\\1%s" % suffix, text)
306 text)
307 340
308 # Remove indentation and merge paragraphs into single long lines, keeping 341 # Remove indentation and merge paragraphs into single long lines, keeping
309 # empty lines between them. 342 # empty lines between them.
310 def SplitMapJoin(split_text, fun, join_text): 343 def SplitMapJoin(split_text, fun, join_text):
311 return lambda text: join_text.join(map(fun, text.split(split_text))) 344 return lambda text: join_text.join(map(fun, text.split(split_text)))
312 strip = lambda line: line.strip() 345 strip = lambda line: line.strip()
313 text = SplitMapJoin("\n\n", SplitMapJoin("\n", strip, " "), "\n\n")(text) 346 text = SplitMapJoin("\n\n", SplitMapJoin("\n", strip, " "), "\n\n")(text)
314 347
315 if not text: 348 if not text:
316 self.Die("Commit message editing failed.") 349 self.Die("Commit message editing failed.")
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 CleanUp, 603 CleanUp,
571 ] 604 ]
572 605
573 RunScript(step_classes, config, options, side_effect_handler) 606 RunScript(step_classes, config, options, side_effect_handler)
574 607
575 608
576 def BuildOptions(): 609 def BuildOptions():
577 result = optparse.OptionParser() 610 result = optparse.OptionParser()
578 result.add_option("-a", "--author", dest="a", 611 result.add_option("-a", "--author", dest="a",
579 help=("Specify the author email used for rietveld.")) 612 help=("Specify the author email used for rietveld."))
613 result.add_option("-b", "--last-bleeding-edge", dest="b",
614 help=("Manually specify the git commit ID of the last "
615 "bleeding edge revision that was pushed to trunk."))
Jakob Kummerow 2014/02/19 12:44:49 For clarification, I'd add something like "This is
Michael Achenbach 2014/02/19 13:23:03 Done.
580 result.add_option("-c", "--chromium", dest="c", 616 result.add_option("-c", "--chromium", dest="c",
581 help=("Specify the path to your Chromium src/ " 617 help=("Specify the path to your Chromium src/ "
582 "directory to automate the V8 roll.")) 618 "directory to automate the V8 roll."))
583 result.add_option("-f", "--force", dest="f", 619 result.add_option("-f", "--force", dest="f",
584 help="Don't prompt the user.", 620 help="Don't prompt the user.",
585 default=False, action="store_true") 621 default=False, action="store_true")
586 result.add_option("-l", "--last-push", dest="l", 622 result.add_option("-l", "--last-push", dest="l",
587 help=("Manually specify the git commit ID " 623 help=("Manually specify the git commit ID "
588 "of the last push to trunk.")) 624 "of the last push to trunk."))
589 result.add_option("-m", "--manual", dest="m", 625 result.add_option("-m", "--manual", dest="m",
(...skipping 29 matching lines...) Expand all
619 def Main(): 655 def Main():
620 parser = BuildOptions() 656 parser = BuildOptions()
621 (options, args) = parser.parse_args() 657 (options, args) = parser.parse_args()
622 if not ProcessOptions(options): 658 if not ProcessOptions(options):
623 parser.print_help() 659 parser.print_help()
624 return 1 660 return 1
625 RunPushToTrunk(CONFIG, PushToTrunkOptions(options)) 661 RunPushToTrunk(CONFIG, PushToTrunkOptions(options))
626 662
627 if __name__ == "__main__": 663 if __name__ == "__main__":
628 sys.exit(Main()) 664 sys.exit(Main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698