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

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

Issue 868473004: External name changes of release scripts. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2014 the V8 project authors. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following
11 # disclaimer in the documentation and/or other materials provided
12 # with the distribution.
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived
15 # from this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
28
29 import re
30
31 SHA1_RE = re.compile('^[a-fA-F0-9]{40}$')
32 ROLL_DEPS_GIT_SVN_ID_RE = re.compile('^git-svn-id: .*@([0-9]+) .*$')
33
34 # Regular expression that matches a single commit footer line.
35 COMMIT_FOOTER_ENTRY_RE = re.compile(r'([^:]+):\s+(.+)')
36
37 # Footer metadata key for commit position.
38 COMMIT_POSITION_FOOTER_KEY = 'Cr-Commit-Position'
39
40 # Regular expression to parse a commit position
41 COMMIT_POSITION_RE = re.compile(r'(.+)@\{#(\d+)\}')
42
43 # Key for the 'git-svn' ID metadata commit footer entry.
44 GIT_SVN_ID_FOOTER_KEY = 'git-svn-id'
45
46 # e.g., git-svn-id: https://v8.googlecode.com/svn/trunk@23117
47 # ce2b1a6d-e550-0410-aec6-3dcde31c8c00
48 GIT_SVN_ID_RE = re.compile(r'[^@]+@(\d+)\s+(?:[a-zA-Z0-9\-]+)')
49
50
51 # Copied from bot_update.py.
52 def GetCommitMessageFooterMap(message):
53 """Returns: (dict) A dictionary of commit message footer entries.
54 """
55 footers = {}
56
57 # Extract the lines in the footer block.
58 lines = []
59 for line in message.strip().splitlines():
60 line = line.strip()
61 if len(line) == 0:
62 del(lines[:])
63 continue
64 lines.append(line)
65
66 # Parse the footer
67 for line in lines:
68 m = COMMIT_FOOTER_ENTRY_RE.match(line)
69 if not m:
70 # If any single line isn't valid, the entire footer is invalid.
71 footers.clear()
72 return footers
73 footers[m.group(1)] = m.group(2).strip()
74 return footers
75
76
77 class GitFailedException(Exception):
78 pass
79
80
81 def Strip(f):
82 def new_f(*args, **kwargs):
83 result = f(*args, **kwargs)
84 if result is None:
85 return result
86 else:
87 return result.strip()
88 return new_f
89
90
91 def MakeArgs(l):
92 """['-a', '', 'abc', ''] -> '-a abc'"""
93 return " ".join(filter(None, l))
94
95
96 def Quoted(s):
97 return "\"%s\"" % s
98
99
100 class GitRecipesMixin(object):
101 def GitIsWorkdirClean(self, **kwargs):
102 return self.Git("status -s -uno", **kwargs).strip() == ""
103
104 @Strip
105 def GitBranch(self, **kwargs):
106 return self.Git("branch", **kwargs)
107
108 def GitCreateBranch(self, name, remote="", **kwargs):
109 assert name
110 remote_args = ["--upstream", remote] if remote else []
111 self.Git(MakeArgs(["new-branch", name] + remote_args), **kwargs)
112
113 def GitDeleteBranch(self, name, **kwargs):
114 assert name
115 self.Git(MakeArgs(["branch -D", name]), **kwargs)
116
117 def GitReset(self, name, **kwargs):
118 assert name
119 self.Git(MakeArgs(["reset --hard", name]), **kwargs)
120
121 def GitStash(self, **kwargs):
122 self.Git(MakeArgs(["stash"]), **kwargs)
123
124 def GitRemotes(self, **kwargs):
125 return map(str.strip,
126 self.Git(MakeArgs(["branch -r"]), **kwargs).splitlines())
127
128 def GitCheckout(self, name, **kwargs):
129 assert name
130 self.Git(MakeArgs(["checkout -f", name]), **kwargs)
131
132 def GitCheckoutFile(self, name, branch_or_hash, **kwargs):
133 assert name
134 assert branch_or_hash
135 self.Git(MakeArgs(["checkout -f", branch_or_hash, "--", name]), **kwargs)
136
137 def GitCheckoutFileSafe(self, name, branch_or_hash, **kwargs):
138 try:
139 self.GitCheckoutFile(name, branch_or_hash, **kwargs)
140 except GitFailedException: # pragma: no cover
141 # The file doesn't exist in that revision.
142 return False
143 return True
144
145 def GitChangedFiles(self, git_hash, **kwargs):
146 assert git_hash
147 try:
148 files = self.Git(MakeArgs(["diff --name-only",
149 git_hash,
150 "%s^" % git_hash]), **kwargs)
151 return map(str.strip, files.splitlines())
152 except GitFailedException: # pragma: no cover
153 # Git fails using "^" at branch roots.
154 return []
155
156
157 @Strip
158 def GitCurrentBranch(self, **kwargs):
159 for line in self.Git("status -s -b -uno", **kwargs).strip().splitlines():
160 match = re.match(r"^## (.+)", line)
161 if match: return match.group(1)
162 raise Exception("Couldn't find curent branch.") # pragma: no cover
163
164 @Strip
165 def GitLog(self, n=0, format="", grep="", git_hash="", parent_hash="",
166 branch="", reverse=False, **kwargs):
167 assert not (git_hash and parent_hash)
168 args = ["log"]
169 if n > 0:
170 args.append("-%d" % n)
171 if format:
172 args.append("--format=%s" % format)
173 if grep:
174 args.append("--grep=\"%s\"" % grep.replace("\"", "\\\""))
175 if reverse:
176 args.append("--reverse")
177 if git_hash:
178 args.append(git_hash)
179 if parent_hash:
180 args.append("%s^" % parent_hash)
181 args.append(branch)
182 return self.Git(MakeArgs(args), **kwargs)
183
184 def GitGetPatch(self, git_hash, **kwargs):
185 assert git_hash
186 return self.Git(MakeArgs(["log", "-1", "-p", git_hash]), **kwargs)
187
188 # TODO(machenbach): Unused? Remove.
189 def GitAdd(self, name, **kwargs):
190 assert name
191 self.Git(MakeArgs(["add", Quoted(name)]), **kwargs)
192
193 def GitApplyPatch(self, patch_file, reverse=False, **kwargs):
194 assert patch_file
195 args = ["apply --index --reject"]
196 if reverse:
197 args.append("--reverse")
198 args.append(Quoted(patch_file))
199 self.Git(MakeArgs(args), **kwargs)
200
201 def GitUpload(self, reviewer="", author="", force=False, cq=False,
202 bypass_hooks=False, cc="", **kwargs):
203 args = ["cl upload --send-mail"]
204 if author:
205 args += ["--email", Quoted(author)]
206 if reviewer:
207 args += ["-r", Quoted(reviewer)]
208 if force:
209 args.append("-f")
210 if cq:
211 args.append("--use-commit-queue")
212 if bypass_hooks:
213 args.append("--bypass-hooks")
214 if cc:
215 args += ["--cc", Quoted(cc)]
216 # TODO(machenbach): Check output in forced mode. Verify that all required
217 # base files were uploaded, if not retry.
218 self.Git(MakeArgs(args), pipe=False, **kwargs)
219
220 def GitCommit(self, message="", file_name="", author=None, **kwargs):
221 assert message or file_name
222 args = ["commit"]
223 if file_name:
224 args += ["-aF", Quoted(file_name)]
225 if message:
226 args += ["-am", Quoted(message)]
227 if author:
228 args += ["--author", "\"%s <%s>\"" % (author, author)]
229 self.Git(MakeArgs(args), **kwargs)
230
231 def GitPresubmit(self, **kwargs):
232 self.Git("cl presubmit", "PRESUBMIT_TREE_CHECK=\"skip\"", **kwargs)
233
234 def GitCLLand(self, **kwargs):
235 self.Git(
236 "cl land -f --bypass-hooks", retry_on=lambda x: x is None, **kwargs)
237
238 def GitDiff(self, loc1, loc2, **kwargs):
239 return self.Git(MakeArgs(["diff", loc1, loc2]), **kwargs)
240
241 def GitPull(self, **kwargs):
242 self.Git("pull", **kwargs)
243
244 def GitFetchOrigin(self, **kwargs):
245 self.Git("fetch origin", **kwargs)
246
247 @Strip
248 # Copied from bot_update.py and modified for svn-like numbers only.
249 def GetCommitPositionNumber(self, git_hash, **kwargs):
250 """Dumps the 'git' log for a specific revision and parses out the commit
251 position number.
252
253 If a commit position metadata key is found, its number will be returned.
254
255 Otherwise, we will search for a 'git-svn' metadata entry. If one is found,
256 its SVN revision value is returned.
257 """
258 git_log = self.GitLog(format='%B', n=1, git_hash=git_hash, **kwargs)
259 footer_map = GetCommitMessageFooterMap(git_log)
260
261 # Search for commit position metadata
262 value = footer_map.get(COMMIT_POSITION_FOOTER_KEY)
263 if value:
264 match = COMMIT_POSITION_RE.match(value)
265 if match:
266 return match.group(2)
267
268 # Extract the svn revision from 'git-svn' metadata
269 value = footer_map.get(GIT_SVN_ID_FOOTER_KEY)
270 if value:
271 match = GIT_SVN_ID_RE.match(value)
272 if match:
273 return match.group(1)
274 raise GitFailedException("Couldn't determine commit position for %s" %
275 git_hash)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698