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

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: 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"
120 # The commit message title is added below after the version is specified. 118 # The commit message title is added below after the version is specified.
121 self["new_commit_msg"] = "" 119 self["new_commit_msg"] = "\n".join(map(lambda s: action_text % s,
120 self["full_revision_list"]))
tandrii(chromium) 2014/11/05 12:59:15 I think this is shorter and more readable: join(ac
Michael Achenbach 2014/11/05 13:30:37 Done.
121 self["new_commit_msg"] += "\n\n"
122 122
123 for commit_hash in self["patch_commit_hashes"]: 123 for commit_hash in self["full_revision_list"]:
124 patch_merge_desc = self.GitLog(n=1, format="%s", git_hash=commit_hash) 124 patch_merge_desc = self.GitLog(n=1, format="%s", git_hash=commit_hash)
125 self["new_commit_msg"] += "%s\n\n" % patch_merge_desc 125 self["new_commit_msg"] += "%s\n\n" % patch_merge_desc
126 126
127 bugs = [] 127 bugs = []
128 for commit_hash in self["patch_commit_hashes"]: 128 for commit_hash in self["full_revision_list"]:
129 msg = self.GitLog(n=1, git_hash=commit_hash) 129 msg = self.GitLog(n=1, git_hash=commit_hash)
130 for bug in re.findall(r"^[ \t]*BUG[ \t]*=[ \t]*(.*?)[ \t]*$", msg, 130 for bug in re.findall(r"^[ \t]*BUG[ \t]*=[ \t]*(.*?)[ \t]*$", msg,
131 re.M): 131 re.M):
132 bugs.extend(map(lambda s: s.strip(), bug.split(","))) 132 bugs.extend(map(lambda s: s.strip(), bug.split(",")))
tandrii(chromium) 2014/11/05 12:59:15 consider shorter: bugs.extend(s.strip() for s in b
Michael Achenbach 2014/11/05 13:30:37 Done.
133 bug_aggregate = ",".join(sorted(filter(lambda s: s and s != "none", bugs))) 133 bug_aggregate = ",".join(sorted(filter(lambda s: s and s != "none", bugs)))
134 if bug_aggregate: 134 if bug_aggregate:
135 self["new_commit_msg"] += "BUG=%s\nLOG=N\n" % bug_aggregate 135 self["new_commit_msg"] += "BUG=%s\nLOG=N\n" % bug_aggregate
136 136
137 137
138 class ApplyPatches(Step): 138 class ApplyPatches(Step):
139 MESSAGE = "Apply patches for selected revisions." 139 MESSAGE = "Apply patches for selected revisions."
140 140
141 def RunStep(self): 141 def RunStep(self):
142 for commit_hash in self["patch_commit_hashes"]: 142 for commit_hash in self["full_revision_list"]:
143 print("Applying patch for %s to %s..." 143 print("Applying patch for %s to %s..."
144 % (commit_hash, self["merge_to_branch"])) 144 % (commit_hash, self["merge_to_branch"]))
145 patch = self.GitGetPatch(commit_hash) 145 patch = self.GitGetPatch(commit_hash)
146 TextToFile(patch, self.Config("TEMPORARY_PATCH_FILE")) 146 TextToFile(patch, self.Config("TEMPORARY_PATCH_FILE"))
147 self.ApplyPatch(self.Config("TEMPORARY_PATCH_FILE"), self._options.revert) 147 self.ApplyPatch(self.Config("TEMPORARY_PATCH_FILE"), self._options.revert)
148 if self._options.patch: 148 if self._options.patch:
149 self.ApplyPatch(self._options.patch, self._options.revert) 149 self.ApplyPatch(self._options.patch, self._options.revert)
150 150
151 151
152 class PrepareVersion(Step): 152 class PrepareVersion(Step):
(...skipping 29 matching lines...) Expand all
182 self["new_minor"], 182 self["new_minor"],
183 self["new_build"], 183 self["new_build"],
184 self["new_patch"]) 184 self["new_patch"])
185 185
186 186
187 class CommitLocal(Step): 187 class CommitLocal(Step):
188 MESSAGE = "Commit to local branch." 188 MESSAGE = "Commit to local branch."
189 189
190 def RunStep(self): 190 def RunStep(self):
191 # Add a commit message title. 191 # Add a commit message title.
192 if self._options.revert: 192 if self._options.revert and self._options.revert_bleeding_edge:
193 if not self._options.revert_bleeding_edge: 193 # TODO(machenbach): Find a better convention if multiple patches are
194 title = ("Version %s (rollback of %s)" 194 # reverted in one CL.
195 % (self["version"], self["revision_list"])) 195 self["commit_title"] = "Revert on master"
196 else:
197 title = "Revert %s." % self["revision_list"]
198 else: 196 else:
199 title = ("Version %s (merged %s)" 197 self["commit_title"] = "Version %s (cherry-pick)" % self["version"]
200 % (self["version"], self["revision_list"])) 198 self["new_commit_msg"] = "%s\n\n%s" % (self["commit_title"],
201 self["commit_title"] = title 199 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")) 200 TextToFile(self["new_commit_msg"], self.Config("COMMITMSG_FILE"))
204 self.GitCommit(file_name=self.Config("COMMITMSG_FILE")) 201 self.GitCommit(file_name=self.Config("COMMITMSG_FILE"))
205 202
206 203
207 class CommitRepository(Step): 204 class CommitRepository(Step):
208 MESSAGE = "Commit to the repository." 205 MESSAGE = "Commit to the repository."
209 206
210 def RunStep(self): 207 def RunStep(self):
211 self.GitCheckout(self.Config("BRANCHNAME")) 208 self.GitCheckout(self.Config("BRANCHNAME"))
212 self.WaitForLGTM() 209 self.WaitForLGTM()
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 if len(options.revisions) < 1: 265 if len(options.revisions) < 1:
269 if not options.patch: 266 if not options.patch:
270 print "Either a patch file or revision numbers must be specified" 267 print "Either a patch file or revision numbers must be specified"
271 return False 268 return False
272 if not options.message: 269 if not options.message:
273 print "You must specify a merge comment if no patches are specified" 270 print "You must specify a merge comment if no patches are specified"
274 return False 271 return False
275 options.bypass_upload_hooks = True 272 options.bypass_upload_hooks = True
276 # CC ulan to make sure that fixes are merged to Google3. 273 # CC ulan to make sure that fixes are merged to Google3.
277 options.cc = "ulan@chromium.org" 274 options.cc = "ulan@chromium.org"
275
276 # Thd old git-svn workflow is deprecated for this script.
277 assert options.vc_interface != "git_svn"
278
279 # Make sure to use git hashes in the new workflows.
280 for revision in options.revisions:
281 if (IsSvnNumber(revision) or
282 (revision[0:1] == "r" and IsSvnNumber(revision[1:]))):
283 print "Please provide full git hashes of the patches to merge."
284 print "Got: %s" % revision
285 return False
278 return True 286 return True
279 287
280 def _Config(self): 288 def _Config(self):
281 return { 289 return {
282 "BRANCHNAME": "prepare-merge", 290 "BRANCHNAME": "prepare-merge",
283 "PERSISTFILE_BASENAME": "/tmp/v8-merge-to-branch-tempfile", 291 "PERSISTFILE_BASENAME": "/tmp/v8-merge-to-branch-tempfile",
284 "ALREADY_MERGING_SENTINEL_FILE": 292 "ALREADY_MERGING_SENTINEL_FILE":
285 "/tmp/v8-merge-to-branch-tempfile-already-merging", 293 "/tmp/v8-merge-to-branch-tempfile-already-merging",
286 "TEMPORARY_PATCH_FILE": "/tmp/v8-prepare-merge-tempfile-temporary-patch", 294 "TEMPORARY_PATCH_FILE": "/tmp/v8-prepare-merge-tempfile-temporary-patch",
287 "COMMITMSG_FILE": "/tmp/v8-prepare-merge-tempfile-commitmsg", 295 "COMMITMSG_FILE": "/tmp/v8-prepare-merge-tempfile-commitmsg",
288 } 296 }
289 297
290 def _Steps(self): 298 def _Steps(self):
291 return [ 299 return [
292 Preparation, 300 Preparation,
293 CreateBranch, 301 CreateBranch,
294 SearchArchitecturePorts, 302 SearchArchitecturePorts,
295 FindGitRevisions, 303 CreateCommitMessage,
296 ApplyPatches, 304 ApplyPatches,
297 PrepareVersion, 305 PrepareVersion,
298 IncrementVersion, 306 IncrementVersion,
299 CommitLocal, 307 CommitLocal,
300 UploadStep, 308 UploadStep,
301 CommitRepository, 309 CommitRepository,
302 TagRevision, 310 TagRevision,
303 CleanUp, 311 CleanUp,
304 ] 312 ]
305 313
306 314
307 if __name__ == "__main__": # pragma: no cover 315 if __name__ == "__main__": # pragma: no cover
308 sys.exit(MergeToBranch().Run()) 316 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