Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
| 7 | 7 |
| 8 """A git-command for integrating reviews on Rietveld.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
| 9 | 9 |
| 10 from distutils.version import LooseVersion | 10 from distutils.version import LooseVersion |
| (...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1076 # with that branch. | 1076 # with that branch. |
| 1077 if self.GetIssue(): | 1077 if self.GetIssue(): |
| 1078 rietveld_server_config = self._RietveldServer() | 1078 rietveld_server_config = self._RietveldServer() |
| 1079 if rietveld_server_config: | 1079 if rietveld_server_config: |
| 1080 self.rietveld_server = gclient_utils.UpgradeToHttps(RunGit( | 1080 self.rietveld_server = gclient_utils.UpgradeToHttps(RunGit( |
| 1081 ['config', rietveld_server_config], error_ok=True).strip()) | 1081 ['config', rietveld_server_config], error_ok=True).strip()) |
| 1082 if not self.rietveld_server: | 1082 if not self.rietveld_server: |
| 1083 self.rietveld_server = settings.GetDefaultServerUrl() | 1083 self.rietveld_server = settings.GetDefaultServerUrl() |
| 1084 return self.rietveld_server | 1084 return self.rietveld_server |
| 1085 | 1085 |
| 1086 def GetGerritServer(self): | |
| 1087 # We don't support multiple Gerrit servers, and assume it to be same as | |
| 1088 # origin, except with a '-review' suffix for first subdomain. | |
| 1089 parts = urlparse.urlparse(self.GetRemoteUrl()).netloc.split('.') | |
| 1090 parts[0] = parts[0] + '-review' | |
| 1091 return 'https://%s' % '.'.join(parts) | |
| 1092 | |
| 1086 def GetIssueURL(self): | 1093 def GetIssueURL(self): |
| 1087 """Get the URL for a particular issue.""" | 1094 """Get the URL for a particular issue.""" |
| 1088 if not self.GetIssue(): | 1095 if not self.GetIssue(): |
| 1089 return None | 1096 return None |
| 1097 if settings.GetIsGerrit(): | |
| 1098 return '%s/%s' % (self.GetGerritServer(), self.GetIssue()) | |
| 1090 return '%s/%s' % (self.GetRietveldServer(), self.GetIssue()) | 1099 return '%s/%s' % (self.GetRietveldServer(), self.GetIssue()) |
| 1091 | 1100 |
| 1092 def GetDescription(self, pretty=False): | 1101 def GetDescription(self, pretty=False): |
| 1093 if not self.has_description: | 1102 if not self.has_description: |
| 1094 if self.GetIssue(): | 1103 if self.GetIssue(): |
| 1095 issue = self.GetIssue() | 1104 issue = self.GetIssue() |
| 1096 try: | 1105 try: |
| 1097 self.description = self.RpcServer().get_description(issue).strip() | 1106 self.description = self.RpcServer().get_description(issue).strip() |
| 1098 except urllib2.HTTPError as e: | 1107 except urllib2.HTTPError as e: |
| 1099 if e.code == 404: | 1108 if e.code == 404: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 else: | 1165 else: |
| 1157 self._props = self.RpcServer().get_issue_properties(issue, True) | 1166 self._props = self.RpcServer().get_issue_properties(issue, True) |
| 1158 return self._props | 1167 return self._props |
| 1159 | 1168 |
| 1160 def GetApprovingReviewers(self): | 1169 def GetApprovingReviewers(self): |
| 1161 return get_approving_reviewers(self.GetIssueProperties()) | 1170 return get_approving_reviewers(self.GetIssueProperties()) |
| 1162 | 1171 |
| 1163 def AddComment(self, message): | 1172 def AddComment(self, message): |
| 1164 return self.RpcServer().add_comment(self.GetIssue(), message) | 1173 return self.RpcServer().add_comment(self.GetIssue(), message) |
| 1165 | 1174 |
| 1166 def SetIssue(self, issue): | 1175 def SetIssue(self, issue=None): |
| 1167 """Set this branch's issue. If issue=0, clears the issue.""" | 1176 """Set this branch's issue. If issue isn't given, clears the issue.""" |
| 1168 if issue: | 1177 if issue: |
| 1169 self.issue = issue | 1178 self.issue = issue |
| 1170 RunGit(['config', self._IssueSetting(), str(issue)]) | 1179 RunGit(['config', self._IssueSetting(), str(issue)]) |
| 1171 if self.rietveld_server: | 1180 if not settings.GetIsGerrit() and self.rietveld_server: |
| 1172 RunGit(['config', self._RietveldServer(), self.rietveld_server]) | 1181 RunGit(['config', self._RietveldServer(), self.rietveld_server]) |
| 1173 else: | 1182 else: |
| 1174 current_issue = self.GetIssue() | 1183 current_issue = self.GetIssue() |
| 1175 if current_issue: | 1184 if current_issue: |
| 1176 RunGit(['config', '--unset', self._IssueSetting()]) | 1185 RunGit(['config', '--unset', self._IssueSetting()]) |
| 1177 self.issue = None | 1186 self.issue = None |
| 1178 self.SetPatchset(None) | 1187 self.SetPatchset(None) |
| 1179 | 1188 |
| 1180 def GetChange(self, upstream_branch, author): | 1189 def GetChange(self, upstream_branch, author): |
| 1181 if not self.GitSanityChecks(upstream_branch): | 1190 if not self.GitSanityChecks(upstream_branch): |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1312 """Returns an upload.RpcServer() to access this review's rietveld instance. | 1321 """Returns an upload.RpcServer() to access this review's rietveld instance. |
| 1313 """ | 1322 """ |
| 1314 if not self._rpc_server: | 1323 if not self._rpc_server: |
| 1315 self._rpc_server = rietveld.CachingRietveld( | 1324 self._rpc_server = rietveld.CachingRietveld( |
| 1316 self.GetRietveldServer(), | 1325 self.GetRietveldServer(), |
| 1317 self._auth_config or auth.make_auth_config()) | 1326 self._auth_config or auth.make_auth_config()) |
| 1318 return self._rpc_server | 1327 return self._rpc_server |
| 1319 | 1328 |
| 1320 def _IssueSetting(self): | 1329 def _IssueSetting(self): |
| 1321 """Return the git setting that stores this change's issue.""" | 1330 """Return the git setting that stores this change's issue.""" |
| 1331 if settings.GetIsGerrit(): | |
| 1332 return 'branch.%s.gerritissue' % self.GetBranch() | |
| 1322 return 'branch.%s.rietveldissue' % self.GetBranch() | 1333 return 'branch.%s.rietveldissue' % self.GetBranch() |
| 1323 | 1334 |
| 1324 def _PatchsetSetting(self): | 1335 def _PatchsetSetting(self): |
| 1325 """Return the git setting that stores this change's most recent patchset.""" | 1336 """Return the git setting that stores this change's most recent patchset.""" |
| 1326 return 'branch.%s.rietveldpatchset' % self.GetBranch() | 1337 return 'branch.%s.rietveldpatchset' % self.GetBranch() |
| 1327 | 1338 |
| 1328 def _RietveldServer(self): | 1339 def _RietveldServer(self): |
| 1329 """Returns the git setting that stores this change's rietveld server.""" | 1340 """Returns the git setting that stores this change's rietveld server.""" |
| 1330 branch = self.GetBranch() | 1341 branch = self.GetBranch() |
| 1331 if branch: | 1342 if branch: |
| (...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2153 def AddChangeIdToCommitMessage(options, args): | 2164 def AddChangeIdToCommitMessage(options, args): |
| 2154 """Re-commits using the current message, assumes the commit hook is in | 2165 """Re-commits using the current message, assumes the commit hook is in |
| 2155 place. | 2166 place. |
| 2156 """ | 2167 """ |
| 2157 log_desc = options.message or CreateDescriptionFromLog(args) | 2168 log_desc = options.message or CreateDescriptionFromLog(args) |
| 2158 git_command = ['commit', '--amend', '-m', log_desc] | 2169 git_command = ['commit', '--amend', '-m', log_desc] |
| 2159 RunGit(git_command) | 2170 RunGit(git_command) |
| 2160 new_log_desc = CreateDescriptionFromLog(args) | 2171 new_log_desc = CreateDescriptionFromLog(args) |
| 2161 if git_footers.get_footer_change_id(new_log_desc): | 2172 if git_footers.get_footer_change_id(new_log_desc): |
| 2162 print 'git-cl: Added Change-Id to commit message.' | 2173 print 'git-cl: Added Change-Id to commit message.' |
| 2174 return new_log_desc | |
|
Michael Achenbach
2016/03/16 09:44:28
Where is this used? It's a bit odd that the method
tandrii(chromium)
2016/03/16 10:09:24
it's not pythonic, but yes default is None. I'll f
| |
| 2163 else: | 2175 else: |
| 2164 print >> sys.stderr, 'ERROR: Gerrit commit-msg hook not available.' | 2176 print >> sys.stderr, 'ERROR: Gerrit commit-msg hook not available.' |
| 2165 | 2177 |
| 2166 | 2178 |
| 2167 def GenerateGerritChangeId(message): | 2179 def GenerateGerritChangeId(message): |
| 2168 """Returns Ixxxxxx...xxx change id. | 2180 """Returns Ixxxxxx...xxx change id. |
| 2169 | 2181 |
| 2170 Works the same way as | 2182 Works the same way as |
| 2171 https://gerrit-review.googlesource.com/tools/hooks/commit-msg | 2183 https://gerrit-review.googlesource.com/tools/hooks/commit-msg |
| 2172 but can be called on demand on all platforms. | 2184 but can be called on demand on all platforms. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2225 print "Description is empty; aborting." | 2237 print "Description is empty; aborting." |
| 2226 return 1 | 2238 return 1 |
| 2227 message = change_desc.description | 2239 message = change_desc.description |
| 2228 change_ids = git_footers.get_footer_change_id(message) | 2240 change_ids = git_footers.get_footer_change_id(message) |
| 2229 if len(change_ids) > 1: | 2241 if len(change_ids) > 1: |
| 2230 DieWithError('too many Change-Id footers in %s branch' % shadow_branch) | 2242 DieWithError('too many Change-Id footers in %s branch' % shadow_branch) |
| 2231 if not change_ids: | 2243 if not change_ids: |
| 2232 message = git_footers.add_footer_change_id( | 2244 message = git_footers.add_footer_change_id( |
| 2233 message, GenerateGerritChangeId(message)) | 2245 message, GenerateGerritChangeId(message)) |
| 2234 change_desc.set_description(message) | 2246 change_desc.set_description(message) |
| 2247 change_ids = git_footers.get_footer_change_id(message) | |
| 2248 assert len(change_ids) == 1 | |
| 2249 | |
| 2250 change_id = change_ids[0] | |
| 2235 | 2251 |
| 2236 remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch()) | 2252 remote, upstream_branch = cl.FetchUpstreamTuple(cl.GetBranch()) |
| 2237 if remote is '.': | 2253 if remote is '.': |
| 2238 # If our upstream branch is local, we base our squashed commit on its | 2254 # If our upstream branch is local, we base our squashed commit on its |
| 2239 # squashed version. | 2255 # squashed version. |
| 2240 parent = ('refs/heads/git_cl_uploads/' + | 2256 parent = ('refs/heads/git_cl_uploads/' + |
| 2241 scm.GIT.ShortBranchName(upstream_branch)) | 2257 scm.GIT.ShortBranchName(upstream_branch)) |
| 2242 | 2258 |
| 2243 # Verify that the upstream branch has been uploaded too, otherwise Gerrit | 2259 # Verify that the upstream branch has been uploaded too, otherwise Gerrit |
| 2244 # will create additional CLs when uploading. | 2260 # will create additional CLs when uploading. |
| 2245 if (RunGitSilent(['rev-parse', upstream_branch + ':']) != | 2261 if (RunGitSilent(['rev-parse', upstream_branch + ':']) != |
| 2246 RunGitSilent(['rev-parse', parent + ':'])): | 2262 RunGitSilent(['rev-parse', parent + ':'])): |
| 2247 print 'Upload upstream branch ' + upstream_branch + ' first.' | 2263 print 'Upload upstream branch ' + upstream_branch + ' first.' |
| 2248 return 1 | 2264 return 1 |
| 2249 else: | 2265 else: |
| 2250 parent = cl.GetCommonAncestorWithUpstream() | 2266 parent = cl.GetCommonAncestorWithUpstream() |
| 2251 | 2267 |
| 2252 tree = RunGit(['rev-parse', 'HEAD:']).strip() | 2268 tree = RunGit(['rev-parse', 'HEAD:']).strip() |
| 2253 ref_to_push = RunGit(['commit-tree', tree, '-p', parent, | 2269 ref_to_push = RunGit(['commit-tree', tree, '-p', parent, |
| 2254 '-m', message]).strip() | 2270 '-m', message]).strip() |
| 2255 else: | 2271 else: |
| 2256 if not git_footers.get_footer_change_id(change_desc.description): | 2272 if not git_footers.get_footer_change_id(change_desc.description): |
| 2257 DownloadGerritHook(False) | 2273 DownloadGerritHook(False) |
| 2258 AddChangeIdToCommitMessage(options, args) | 2274 change_desc.set_description(AddChangeIdToCommitMessage(options, args)) |
| 2259 ref_to_push = 'HEAD' | 2275 ref_to_push = 'HEAD' |
| 2260 parent = '%s/%s' % (gerrit_remote, branch) | 2276 parent = '%s/%s' % (gerrit_remote, branch) |
| 2277 change_id = git_footers.get_footer_change_id(change_desc.description)[0] | |
| 2261 | 2278 |
| 2262 commits = RunGitSilent(['rev-list', '%s..%s' % (parent, | 2279 commits = RunGitSilent(['rev-list', '%s..%s' % (parent, |
| 2263 ref_to_push)]).splitlines() | 2280 ref_to_push)]).splitlines() |
| 2264 if len(commits) > 1: | 2281 if len(commits) > 1: |
| 2265 print('WARNING: This will upload %d commits. Run the following command ' | 2282 print('WARNING: This will upload %d commits. Run the following command ' |
| 2266 'to see which commits will be uploaded: ' % len(commits)) | 2283 'to see which commits will be uploaded: ' % len(commits)) |
| 2267 print('git log %s..%s' % (parent, ref_to_push)) | 2284 print('git log %s..%s' % (parent, ref_to_push)) |
| 2268 print('You can also use `git squash-branch` to squash these into a single ' | 2285 print('You can also use `git squash-branch` to squash these into a single ' |
| 2269 'commit.') | 2286 'commit.') |
| 2270 ask_for_data('About to upload; enter to confirm.') | 2287 ask_for_data('About to upload; enter to confirm.') |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2281 receive_options += ['--cc=' + email for email in cc] | 2298 receive_options += ['--cc=' + email for email in cc] |
| 2282 if change_desc.get_reviewers(): | 2299 if change_desc.get_reviewers(): |
| 2283 receive_options.extend( | 2300 receive_options.extend( |
| 2284 '--reviewer=' + email for email in change_desc.get_reviewers()) | 2301 '--reviewer=' + email for email in change_desc.get_reviewers()) |
| 2285 | 2302 |
| 2286 git_command = ['push'] | 2303 git_command = ['push'] |
| 2287 if receive_options: | 2304 if receive_options: |
| 2288 git_command.append('--receive-pack=git receive-pack %s' % | 2305 git_command.append('--receive-pack=git receive-pack %s' % |
| 2289 ' '.join(receive_options)) | 2306 ' '.join(receive_options)) |
| 2290 git_command += [gerrit_remote, ref_to_push + ':refs/for/' + branch] | 2307 git_command += [gerrit_remote, ref_to_push + ':refs/for/' + branch] |
| 2291 RunGit(git_command) | 2308 push_stdout = gclient_utils.CheckCallAndFilter( |
| 2309 ['git'] + git_command, | |
| 2310 print_stdout=True, | |
| 2311 # Flush after every line: useful for seeing progress when running as | |
| 2312 # recipe. | |
| 2313 filter_fn=lambda _: sys.stdout.flush()) | |
| 2292 | 2314 |
| 2293 if options.squash: | 2315 if options.squash: |
| 2316 regex = re.compile(r'remote:\s+https?://[\w\-\.\/]*/(\d+)\s.*') | |
| 2317 change_numbers = [m.group(1) | |
| 2318 for m in map(regex.match, push_stdout.splitlines()) | |
| 2319 if m] | |
| 2320 if len(change_numbers) != 1: | |
| 2321 DieWithError( | |
| 2322 ('Created|Updated %d issues on Gerrit, but only 1 expected.\n' | |
| 2323 'Change-Id: %s') % (len(change_numbers), change_id)) | |
| 2324 cl.SetIssue(change_numbers[0]) | |
| 2294 head = RunGit(['rev-parse', 'HEAD']).strip() | 2325 head = RunGit(['rev-parse', 'HEAD']).strip() |
| 2295 RunGit(['update-ref', '-m', 'Uploaded ' + head, shadow_branch, ref_to_push]) | 2326 RunGit(['update-ref', '-m', 'Uploaded ' + head, shadow_branch, ref_to_push]) |
| 2296 | |
| 2297 # TODO(ukai): parse Change-Id: and set issue number? | |
| 2298 return 0 | 2327 return 0 |
| 2299 | 2328 |
| 2300 | 2329 |
| 2301 def GetTargetRef(remote, remote_branch, target_branch, pending_prefix): | 2330 def GetTargetRef(remote, remote_branch, target_branch, pending_prefix): |
| 2302 """Computes the remote branch ref to use for the CL. | 2331 """Computes the remote branch ref to use for the CL. |
| 2303 | 2332 |
| 2304 Args: | 2333 Args: |
| 2305 remote (str): The git remote for the CL. | 2334 remote (str): The git remote for the CL. |
| 2306 remote_branch (str): The git remote branch for the CL. | 2335 remote_branch (str): The git remote branch for the CL. |
| 2307 target_branch (str): The target branch specified by the user. | 2336 target_branch (str): The target branch specified by the user. |
| (...skipping 1675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3983 if __name__ == '__main__': | 4012 if __name__ == '__main__': |
| 3984 # These affect sys.stdout so do it outside of main() to simplify mocks in | 4013 # These affect sys.stdout so do it outside of main() to simplify mocks in |
| 3985 # unit testing. | 4014 # unit testing. |
| 3986 fix_encoding.fix_encoding() | 4015 fix_encoding.fix_encoding() |
| 3987 colorama.init() | 4016 colorama.init() |
| 3988 try: | 4017 try: |
| 3989 sys.exit(main(sys.argv[1:])) | 4018 sys.exit(main(sys.argv[1:])) |
| 3990 except KeyboardInterrupt: | 4019 except KeyboardInterrupt: |
| 3991 sys.stderr.write('interrupted\n') | 4020 sys.stderr.write('interrupted\n') |
| 3992 sys.exit(1) | 4021 sys.exit(1) |
| OLD | NEW |