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

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

Issue 702843002: Make merge_to_branch more git-friendly. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review Created 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/push-to-trunk/releases.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 2014 the V8 project authors. All rights reserved. 2 # Copyright 2014 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 14 matching lines...) Expand all
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 argparse 29 import argparse
30 from collections import OrderedDict 30 from collections import OrderedDict
31 import sys 31 import sys
32 32
33 from common_includes import * 33 from common_includes import *
34 34
35 def IsSvnNumber(rev):
36 return rev.isdigit() and len(rev) < 8
37
35 class Preparation(Step): 38 class Preparation(Step):
36 MESSAGE = "Preparation." 39 MESSAGE = "Preparation."
37 40
38 def RunStep(self): 41 def RunStep(self):
39 if os.path.exists(self.Config("ALREADY_MERGING_SENTINEL_FILE")): 42 if os.path.exists(self.Config("ALREADY_MERGING_SENTINEL_FILE")):
40 if self._options.force: 43 if self._options.force:
41 os.remove(self.Config("ALREADY_MERGING_SENTINEL_FILE")) 44 os.remove(self.Config("ALREADY_MERGING_SENTINEL_FILE"))
42 elif self._options.step == 0: # pragma: no cover 45 elif self._options.step == 0: # pragma: no cover
43 self.Die("A merge is already in progress") 46 self.Die("A merge is already in progress")
44 open(self.Config("ALREADY_MERGING_SENTINEL_FILE"), "a").close() 47 open(self.Config("ALREADY_MERGING_SENTINEL_FILE"), "a").close()
(...skipping 20 matching lines...) Expand all
65 68
66 69
67 class SearchArchitecturePorts(Step): 70 class SearchArchitecturePorts(Step):
68 MESSAGE = "Search for corresponding architecture ports." 71 MESSAGE = "Search for corresponding architecture ports."
69 72
70 def RunStep(self): 73 def RunStep(self):
71 self["full_revision_list"] = list(OrderedDict.fromkeys( 74 self["full_revision_list"] = list(OrderedDict.fromkeys(
72 self._options.revisions)) 75 self._options.revisions))
73 port_revision_list = [] 76 port_revision_list = []
74 for revision in self["full_revision_list"]: 77 for revision in self["full_revision_list"]:
75 # Search for commits which matches the "Port rXXX" pattern. 78 # Search for commits which matches the "Port XXX" pattern.
76 git_hashes = self.GitLog(reverse=True, format="%H", 79 git_hashes = self.GitLog(reverse=True, format="%H",
77 grep="Port r%d" % int(revision), 80 grep="Port %s" % revision,
78 branch=self.vc.RemoteMasterBranch()) 81 branch=self.vc.RemoteMasterBranch())
79 for git_hash in git_hashes.splitlines(): 82 for git_hash in git_hashes.splitlines():
80 svn_revision = self.vc.GitSvn(git_hash, self.vc.RemoteMasterBranch())
81 if not svn_revision: # pragma: no cover
82 self.Die("Cannot determine svn revision for %s" % git_hash)
83 revision_title = self.GitLog(n=1, format="%s", git_hash=git_hash) 83 revision_title = self.GitLog(n=1, format="%s", git_hash=git_hash)
84 84
85 # Is this revision included in the original revision list? 85 # Is this revision included in the original revision list?
86 if svn_revision in self["full_revision_list"]: 86 if git_hash in self["full_revision_list"]:
87 print("Found port of r%s -> r%s (already included): %s" 87 print("Found port of %s -> %s (already included): %s"
88 % (revision, svn_revision, revision_title)) 88 % (revision, git_hash, revision_title))
89 else: 89 else:
90 print("Found port of r%s -> r%s: %s" 90 print("Found port of %s -> %s: %s"
91 % (revision, svn_revision, revision_title)) 91 % (revision, git_hash, revision_title))
92 port_revision_list.append(svn_revision) 92 port_revision_list.append(git_hash)
93 93
94 # Do we find any port? 94 # Do we find any port?
95 if len(port_revision_list) > 0: 95 if len(port_revision_list) > 0:
96 if self.Confirm("Automatically add corresponding ports (%s)?" 96 if self.Confirm("Automatically add corresponding ports (%s)?"
97 % ", ".join(port_revision_list)): 97 % ", ".join(port_revision_list)):
98 #: 'y': Add ports to revision list. 98 #: 'y': Add ports to revision list.
99 self["full_revision_list"].extend(port_revision_list) 99 self["full_revision_list"].extend(port_revision_list)
100 100
101 101
102 class FindGitRevisions(Step): 102 class CreateCommitMessage(Step):
103 MESSAGE = "Find the git revisions associated with the patches." 103 MESSAGE = "Create commit message."
104 104
105 def RunStep(self): 105 def RunStep(self):
106 self["patch_commit_hashes"] = []
107 for revision in self["full_revision_list"]:
108 next_hash = self.vc.SvnGit(revision, self.vc.RemoteMasterBranch())
109 if not next_hash: # pragma: no cover
110 self.Die("Cannot determine git hash for r%s" % revision)
111 self["patch_commit_hashes"].append(next_hash)
112 106
113 # Stringify: [123, 234] -> "r123, r234" 107 # Stringify: [123, 234] -> "r123, r234"
114 self["revision_list"] = ", ".join(map(lambda s: "r%s" % s, 108 self["revision_list"] = ", ".join(map(lambda s: "r%s" % s,
115 self["full_revision_list"])) 109 self["full_revision_list"]))
116 110
117 if not self["revision_list"]: # pragma: no cover 111 if not self["revision_list"]: # pragma: no cover
118 self.Die("Revision list is empty.") 112 self.Die("Revision list is empty.")
119 113
114 if self._options.revert and not self._options.revert_bleeding_edge:
115 action_text = "Rollback of %s"
116 else:
117 action_text = "Merged %s"
118
120 # The commit message title is added below after the version is specified. 119 # The commit message title is added below after the version is specified.
121 self["new_commit_msg"] = "" 120 msg_pieces = [
121 "\n".join(action_text % s for s in self["full_revision_list"]),
122 ]
123 msg_pieces.append("\n\n")
122 124
123 for commit_hash in self["patch_commit_hashes"]: 125 for commit_hash in self["full_revision_list"]:
124 patch_merge_desc = self.GitLog(n=1, format="%s", git_hash=commit_hash) 126 patch_merge_desc = self.GitLog(n=1, format="%s", git_hash=commit_hash)
125 self["new_commit_msg"] += "%s\n\n" % patch_merge_desc 127 msg_pieces.append("%s\n\n" % patch_merge_desc)
126 128
127 bugs = [] 129 bugs = []
128 for commit_hash in self["patch_commit_hashes"]: 130 for commit_hash in self["full_revision_list"]:
129 msg = self.GitLog(n=1, git_hash=commit_hash) 131 msg = self.GitLog(n=1, git_hash=commit_hash)
130 for bug in re.findall(r"^[ \t]*BUG[ \t]*=[ \t]*(.*?)[ \t]*$", msg, 132 for bug in re.findall(r"^[ \t]*BUG[ \t]*=[ \t]*(.*?)[ \t]*$", msg, re.M):
131 re.M): 133 bugs.extend(s.strip() for s in bug.split(","))
132 bugs.extend(map(lambda s: s.strip(), bug.split(",")))
133 bug_aggregate = ",".join(sorted(filter(lambda s: s and s != "none", bugs))) 134 bug_aggregate = ",".join(sorted(filter(lambda s: s and s != "none", bugs)))
134 if bug_aggregate: 135 if bug_aggregate:
135 self["new_commit_msg"] += "BUG=%s\nLOG=N\n" % bug_aggregate 136 msg_pieces.append("BUG=%s\nLOG=N\n" % bug_aggregate)
137
138 self["new_commit_msg"] = "".join(msg_pieces)
136 139
137 140
138 class ApplyPatches(Step): 141 class ApplyPatches(Step):
139 MESSAGE = "Apply patches for selected revisions." 142 MESSAGE = "Apply patches for selected revisions."
140 143
141 def RunStep(self): 144 def RunStep(self):
142 for commit_hash in self["patch_commit_hashes"]: 145 for commit_hash in self["full_revision_list"]:
143 print("Applying patch for %s to %s..." 146 print("Applying patch for %s to %s..."
144 % (commit_hash, self["merge_to_branch"])) 147 % (commit_hash, self["merge_to_branch"]))
145 patch = self.GitGetPatch(commit_hash) 148 patch = self.GitGetPatch(commit_hash)
146 TextToFile(patch, self.Config("TEMPORARY_PATCH_FILE")) 149 TextToFile(patch, self.Config("TEMPORARY_PATCH_FILE"))
147 self.ApplyPatch(self.Config("TEMPORARY_PATCH_FILE"), self._options.revert) 150 self.ApplyPatch(self.Config("TEMPORARY_PATCH_FILE"), self._options.revert)
148 if self._options.patch: 151 if self._options.patch:
149 self.ApplyPatch(self._options.patch, self._options.revert) 152 self.ApplyPatch(self._options.patch, self._options.revert)
150 153
151 154
152 class PrepareVersion(Step): 155 class PrepareVersion(Step):
(...skipping 29 matching lines...) Expand all
182 self["new_minor"], 185 self["new_minor"],
183 self["new_build"], 186 self["new_build"],
184 self["new_patch"]) 187 self["new_patch"])
185 188
186 189
187 class CommitLocal(Step): 190 class CommitLocal(Step):
188 MESSAGE = "Commit to local branch." 191 MESSAGE = "Commit to local branch."
189 192
190 def RunStep(self): 193 def RunStep(self):
191 # Add a commit message title. 194 # Add a commit message title.
192 if self._options.revert: 195 if self._options.revert and self._options.revert_bleeding_edge:
193 if not self._options.revert_bleeding_edge: 196 # TODO(machenbach): Find a better convention if multiple patches are
194 title = ("Version %s (rollback of %s)" 197 # reverted in one CL.
195 % (self["version"], self["revision_list"])) 198 self["commit_title"] = "Revert on master"
196 else:
197 title = "Revert %s." % self["revision_list"]
198 else: 199 else:
199 title = ("Version %s (merged %s)" 200 self["commit_title"] = "Version %s (cherry-pick)" % self["version"]
200 % (self["version"], self["revision_list"])) 201 self["new_commit_msg"] = "%s\n\n%s" % (self["commit_title"],
201 self["commit_title"] = title 202 self["new_commit_msg"])
202 self["new_commit_msg"] = "%s\n\n%s" % (title, self["new_commit_msg"])
203 TextToFile(self["new_commit_msg"], self.Config("COMMITMSG_FILE")) 203 TextToFile(self["new_commit_msg"], self.Config("COMMITMSG_FILE"))
204 self.GitCommit(file_name=self.Config("COMMITMSG_FILE")) 204 self.GitCommit(file_name=self.Config("COMMITMSG_FILE"))
205 205
206 206
207 class CommitRepository(Step): 207 class CommitRepository(Step):
208 MESSAGE = "Commit to the repository." 208 MESSAGE = "Commit to the repository."
209 209
210 def RunStep(self): 210 def RunStep(self):
211 self.GitCheckout(self.Config("BRANCHNAME")) 211 self.GitCheckout(self.Config("BRANCHNAME"))
212 self.WaitForLGTM() 212 self.WaitForLGTM()
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 if len(options.revisions) < 1: 268 if len(options.revisions) < 1:
269 if not options.patch: 269 if not options.patch:
270 print "Either a patch file or revision numbers must be specified" 270 print "Either a patch file or revision numbers must be specified"
271 return False 271 return False
272 if not options.message: 272 if not options.message:
273 print "You must specify a merge comment if no patches are specified" 273 print "You must specify a merge comment if no patches are specified"
274 return False 274 return False
275 options.bypass_upload_hooks = True 275 options.bypass_upload_hooks = True
276 # CC ulan to make sure that fixes are merged to Google3. 276 # CC ulan to make sure that fixes are merged to Google3.
277 options.cc = "ulan@chromium.org" 277 options.cc = "ulan@chromium.org"
278
279 # Thd old git-svn workflow is deprecated for this script.
280 assert options.vc_interface != "git_svn"
281
282 # Make sure to use git hashes in the new workflows.
283 for revision in options.revisions:
284 if (IsSvnNumber(revision) or
285 (revision[0:1] == "r" and IsSvnNumber(revision[1:]))):
286 print "Please provide full git hashes of the patches to merge."
287 print "Got: %s" % revision
288 return False
278 return True 289 return True
279 290
280 def _Config(self): 291 def _Config(self):
281 return { 292 return {
282 "BRANCHNAME": "prepare-merge", 293 "BRANCHNAME": "prepare-merge",
283 "PERSISTFILE_BASENAME": "/tmp/v8-merge-to-branch-tempfile", 294 "PERSISTFILE_BASENAME": "/tmp/v8-merge-to-branch-tempfile",
284 "ALREADY_MERGING_SENTINEL_FILE": 295 "ALREADY_MERGING_SENTINEL_FILE":
285 "/tmp/v8-merge-to-branch-tempfile-already-merging", 296 "/tmp/v8-merge-to-branch-tempfile-already-merging",
286 "TEMPORARY_PATCH_FILE": "/tmp/v8-prepare-merge-tempfile-temporary-patch", 297 "TEMPORARY_PATCH_FILE": "/tmp/v8-prepare-merge-tempfile-temporary-patch",
287 "COMMITMSG_FILE": "/tmp/v8-prepare-merge-tempfile-commitmsg", 298 "COMMITMSG_FILE": "/tmp/v8-prepare-merge-tempfile-commitmsg",
288 } 299 }
289 300
290 def _Steps(self): 301 def _Steps(self):
291 return [ 302 return [
292 Preparation, 303 Preparation,
293 CreateBranch, 304 CreateBranch,
294 SearchArchitecturePorts, 305 SearchArchitecturePorts,
295 FindGitRevisions, 306 CreateCommitMessage,
296 ApplyPatches, 307 ApplyPatches,
297 PrepareVersion, 308 PrepareVersion,
298 IncrementVersion, 309 IncrementVersion,
299 CommitLocal, 310 CommitLocal,
300 UploadStep, 311 UploadStep,
301 CommitRepository, 312 CommitRepository,
302 TagRevision, 313 TagRevision,
303 CleanUp, 314 CleanUp,
304 ] 315 ]
305 316
306 317
307 if __name__ == "__main__": # pragma: no cover 318 if __name__ == "__main__": # pragma: no cover
308 sys.exit(MergeToBranch().Run()) 319 sys.exit(MergeToBranch().Run())
OLDNEW
« no previous file with comments | « no previous file | tools/push-to-trunk/releases.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698