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: gcl.py

Issue 13800018: Make gcl use git_cl.py code for consistency in the CL description formatting. (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@2_refactor
Patch Set: append_line -> append_footer Created 7 years, 8 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
« no previous file with comments | « no previous file | tests/gcl_unittest.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 (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 """\ 6 """\
7 Wrapper script around Rietveld's upload.py that simplifies working with groups 7 Wrapper script around Rietveld's upload.py that simplifies working with groups
8 of files. 8 of files.
9 """ 9 """
10 10
11 import json 11 import json
12 import optparse 12 import optparse
13 import os 13 import os
14 import random 14 import random
15 import re 15 import re
16 import string 16 import string
17 import sys 17 import sys
18 import tempfile 18 import tempfile
19 import time 19 import time
20 import urllib2 20 import urllib2
21 21
22 import breakpad # pylint: disable=W0611 22 import breakpad # pylint: disable=W0611
23 23
24 24
25 import fix_encoding 25 import fix_encoding
26 import gclient_utils 26 import gclient_utils
27 import git_cl
27 import presubmit_support 28 import presubmit_support
28 import rietveld 29 import rietveld
29 from scm import SVN 30 from scm import SVN
30 import subprocess2 31 import subprocess2
31 from third_party import upload 32 from third_party import upload
32 33
33 __version__ = '1.2.1' 34 __version__ = '1.2.1'
34 35
35 36
36 CODEREVIEW_SETTINGS = { 37 CODEREVIEW_SETTINGS = {
(...skipping 15 matching lines...) Expand all
52 # Warning message when the change appears to be missing tests. 53 # Warning message when the change appears to be missing tests.
53 MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!" 54 MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!"
54 55
55 # Global cache of files cached in GetCacheDir(). 56 # Global cache of files cached in GetCacheDir().
56 FILES_CACHE = {} 57 FILES_CACHE = {}
57 58
58 # Valid extensions for files we want to lint. 59 # Valid extensions for files we want to lint.
59 DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)" 60 DEFAULT_LINT_REGEX = r"(.*\.cpp|.*\.cc|.*\.h)"
60 DEFAULT_LINT_IGNORE_REGEX = r"$^" 61 DEFAULT_LINT_IGNORE_REGEX = r"$^"
61 62
62 REVIEWERS_REGEX = r'\s*R=(.+)'
63
64 def CheckHomeForFile(filename): 63 def CheckHomeForFile(filename):
65 """Checks the users home dir for the existence of the given file. Returns 64 """Checks the users home dir for the existence of the given file. Returns
66 the path to the file if it's there, or None if it is not. 65 the path to the file if it's there, or None if it is not.
67 """ 66 """
68 home_vars = ['HOME'] 67 home_vars = ['HOME']
69 if sys.platform in ('cygwin', 'win32'): 68 if sys.platform in ('cygwin', 'win32'):
70 home_vars.append('USERPROFILE') 69 home_vars.append('USERPROFILE')
71 for home_var in home_vars: 70 for home_var in home_vars:
72 home = os.getenv(home_var) 71 home = os.getenv(home_var)
73 if home != None: 72 if home != None:
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 files: a list of 2 tuple containing (status, filename) of changed files, 265 files: a list of 2 tuple containing (status, filename) of changed files,
267 with paths being relative to the top repository directory. 266 with paths being relative to the top repository directory.
268 local_root: Local root directory 267 local_root: Local root directory
269 rietveld: rietveld server for this change 268 rietveld: rietveld server for this change
270 """ 269 """
271 # Kept for unit test support. This is for the old format, it's deprecated. 270 # Kept for unit test support. This is for the old format, it's deprecated.
272 SEPARATOR = "\n-----\n" 271 SEPARATOR = "\n-----\n"
273 272
274 def __init__(self, name, issue, patchset, description, files, local_root, 273 def __init__(self, name, issue, patchset, description, files, local_root,
275 rietveld_url, needs_upload): 274 rietveld_url, needs_upload):
275 # Defer the description processing to git_cl.ChangeDescription.
276 self._desc = git_cl.ChangeDescription(description)
276 self.name = name 277 self.name = name
277 self.issue = int(issue) 278 self.issue = int(issue)
278 self.patchset = int(patchset) 279 self.patchset = int(patchset)
279 self._description = None 280 self._files = files or []
280 self._reviewers = None
281 self._set_description(description)
282 if files is None:
283 files = []
284 self._files = files
285 self.patch = None 281 self.patch = None
286 self._local_root = local_root 282 self._local_root = local_root
287 self.needs_upload = needs_upload 283 self.needs_upload = needs_upload
288 self.rietveld = gclient_utils.UpgradeToHttps( 284 self.rietveld = gclient_utils.UpgradeToHttps(
289 rietveld_url or GetCodeReviewSetting('CODE_REVIEW_SERVER')) 285 rietveld_url or GetCodeReviewSetting('CODE_REVIEW_SERVER'))
290 self._rpc_server = None 286 self._rpc_server = None
291 287
292 def _get_description(self): 288 @property
293 return self._description 289 def description(self):
290 return self._desc.description
294 291
295 def _set_description(self, description): 292 def force_description(self, new_description):
296 # TODO(dpranke): Cloned from git_cl.py. These should be shared. 293 self._desc = git_cl.ChangeDescription(new_description)
297 if not description: 294 self.needs_upload = True
298 self._description = description
299 return
300 295
301 parsed_lines = [] 296 def append_footer(self, line):
302 reviewers_re = re.compile(REVIEWERS_REGEX) 297 self._desc.append_footer(line)
303 reviewers = ''
304 for l in description.splitlines():
305 matched_reviewers = reviewers_re.match(l)
306 if matched_reviewers:
307 reviewers = matched_reviewers.group(1).split(',')
308 parsed_lines.append(l)
309 self._reviewers = reviewers
310 self._description = '\n'.join(parsed_lines)
311 298
312 description = property(_get_description, _set_description) 299 def get_reviewers(self):
313 300 return self._desc.get_reviewers()
314 @property
315 def reviewers(self):
316 return self._reviewers
317 301
318 def NeedsUpload(self): 302 def NeedsUpload(self):
319 return self.needs_upload 303 return self.needs_upload
320 304
321 def GetFileNames(self): 305 def GetFileNames(self):
322 """Returns the list of file names included in this change.""" 306 """Returns the list of file names included in this change."""
323 return [f[1] for f in self._files] 307 return [f[1] for f in self._files]
324 308
325 def GetFiles(self): 309 def GetFiles(self):
326 """Returns the list of files included in this change with their status.""" 310 """Returns the list of files included in this change with their status."""
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 ctype, body = upload.EncodeMultipartFormData(data, []) 365 ctype, body = upload.EncodeMultipartFormData(data, [])
382 self.SendToRietveld('/%d/close' % self.issue, payload=body, 366 self.SendToRietveld('/%d/close' % self.issue, payload=body,
383 content_type=ctype) 367 content_type=ctype)
384 368
385 def UpdateRietveldDescription(self): 369 def UpdateRietveldDescription(self):
386 """Sets the description for an issue on Rietveld.""" 370 """Sets the description for an issue on Rietveld."""
387 data = [("description", self.description),] 371 data = [("description", self.description),]
388 ctype, body = upload.EncodeMultipartFormData(data, []) 372 ctype, body = upload.EncodeMultipartFormData(data, [])
389 self.SendToRietveld('/%d/description' % self.issue, payload=body, 373 self.SendToRietveld('/%d/description' % self.issue, payload=body,
390 content_type=ctype) 374 content_type=ctype)
375 self.needs_upload = False
391 376
392 def GetIssueDescription(self): 377 def UpdateDescriptionFromIssue(self):
393 """Returns the issue description from Rietveld.""" 378 """Updates self.description with the issue description from Rietveld."""
394 return self.SendToRietveld('/%d/description' % self.issue) 379 self._desc = git_cl.ChangeDescription(
380 self.SendToRietveld('/%d/description' % self.issue))
395 381
396 def AddComment(self, comment): 382 def AddComment(self, comment):
397 """Adds a comment for an issue on Rietveld. 383 """Adds a comment for an issue on Rietveld.
398 As a side effect, this will email everyone associated with the issue.""" 384 As a side effect, this will email everyone associated with the issue."""
399 return self.RpcServer().add_comment(self.issue, comment) 385 return self.RpcServer().add_comment(self.issue, comment)
400 386
401 def PrimeLint(self): 387 def PrimeLint(self):
402 """Do background work on Rietveld to lint the file so that the results are 388 """Do background work on Rietveld to lint the file so that the results are
403 ready when the issue is viewed.""" 389 ready when the issue is viewed."""
404 if self.issue and self.patchset: 390 if self.issue and self.patchset:
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 args = map(replace_message, args) 830 args = map(replace_message, args)
845 if found_deprecated_arg[0]: 831 if found_deprecated_arg[0]:
846 print >> sys.stderr, ( 832 print >> sys.stderr, (
847 '\nWARNING: Use -t or --title to set the title of the patchset.\n' 833 '\nWARNING: Use -t or --title to set the title of the patchset.\n'
848 'In the near future, -m or --message will send a message instead.\n' 834 'In the near future, -m or --message will send a message instead.\n'
849 'See http://goo.gl/JGg0Z for details.\n') 835 'See http://goo.gl/JGg0Z for details.\n')
850 836
851 upload_arg = ["upload.py", "-y"] 837 upload_arg = ["upload.py", "-y"]
852 upload_arg.append("--server=%s" % change_info.rietveld) 838 upload_arg.append("--server=%s" % change_info.rietveld)
853 839
854 reviewers = change_info.reviewers or output.reviewers 840 reviewers = change_info.get_reviewers() or output.reviewers
855 if (reviewers and 841 if (reviewers and
856 not any(arg.startswith('-r') or arg.startswith('--reviewer') for 842 not any(arg.startswith('-r') or arg.startswith('--reviewer') for
857 arg in args)): 843 arg in args)):
858 upload_arg.append('--reviewers=%s' % ','.join(reviewers)) 844 upload_arg.append('--reviewers=%s' % ','.join(reviewers))
859 845
860 upload_arg.extend(args) 846 upload_arg.extend(args)
861 847
862 desc_file = None 848 desc_file = None
863 try: 849 try:
864 if change_info.issue: 850 if change_info.issue:
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 # We face a problem with svn here: Let's say change 'bleh' modifies 982 # We face a problem with svn here: Let's say change 'bleh' modifies
997 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies 983 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies
998 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. 984 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*.
999 # The only fix is to use --non-recursive but that has its issues too: 985 # The only fix is to use --non-recursive but that has its issues too:
1000 # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise 986 # Let's say if dir1 is deleted, --non-recursive must *not* be used otherwise
1001 # you'll get "svn: Cannot non-recursively commit a directory deletion of a 987 # you'll get "svn: Cannot non-recursively commit a directory deletion of a
1002 # directory with child nodes". Yay... 988 # directory with child nodes". Yay...
1003 commit_cmd = ["svn", "commit"] 989 commit_cmd = ["svn", "commit"]
1004 if change_info.issue: 990 if change_info.issue:
1005 # Get the latest description from Rietveld. 991 # Get the latest description from Rietveld.
1006 change_info.description = change_info.GetIssueDescription() 992 change_info.UpdateDescriptionFromIssue()
1007 993
1008 commit_message = change_info.description.replace('\r\n', '\n') 994 commit_desc = git_cl.ChangeDescription(change_info.description)
1009 if change_info.issue: 995 if change_info.issue:
1010 server = change_info.rietveld 996 server = change_info.rietveld
1011 if not server.startswith("http://") and not server.startswith("https://"): 997 if not server.startswith("http://") and not server.startswith("https://"):
1012 server = "http://" + server 998 server = "http://" + server
1013 commit_message += ('\nReview URL: %s/%d' % (server, change_info.issue)) 999 commit_desc.append_footer('Review URL: %s/%d' % (server, change_info.issue))
1014 1000
1015 handle, commit_filename = tempfile.mkstemp(text=True) 1001 handle, commit_filename = tempfile.mkstemp(text=True)
1016 os.write(handle, commit_message) 1002 os.write(handle, commit_desc.description)
1017 os.close(handle) 1003 os.close(handle)
1018 try: 1004 try:
1019 handle, targets_filename = tempfile.mkstemp(text=True) 1005 handle, targets_filename = tempfile.mkstemp(text=True)
1020 os.write(handle, "\n".join(change_info.GetFileNames())) 1006 os.write(handle, "\n".join(change_info.GetFileNames()))
1021 os.close(handle) 1007 os.close(handle)
1022 try: 1008 try:
1023 commit_cmd += ['--file=' + commit_filename] 1009 commit_cmd += ['--file=' + commit_filename]
1024 commit_cmd += ['--targets=' + targets_filename] 1010 commit_cmd += ['--targets=' + targets_filename]
1025 # Change the current working directory before calling commit. 1011 # Change the current working directory before calling commit.
1026 output = '' 1012 output = ''
1027 try: 1013 try:
1028 output = RunShell(commit_cmd, True) 1014 output = RunShell(commit_cmd, True)
1029 except subprocess2.CalledProcessError, e: 1015 except subprocess2.CalledProcessError, e:
1030 ErrorExit('Commit failed.\n%s' % e) 1016 ErrorExit('Commit failed.\n%s' % e)
1031 finally: 1017 finally:
1032 os.remove(commit_filename) 1018 os.remove(commit_filename)
1033 finally: 1019 finally:
1034 os.remove(targets_filename) 1020 os.remove(targets_filename)
1035 if output.find("Committed revision") != -1: 1021 if output.find("Committed revision") != -1:
1036 change_info.Delete() 1022 change_info.Delete()
1037 1023
1038 if change_info.issue: 1024 if change_info.issue:
1039 revision = re.compile(".*?\nCommitted revision (\d+)", 1025 revision = re.compile(".*?\nCommitted revision (\d+)",
1040 re.DOTALL).match(output).group(1) 1026 re.DOTALL).match(output).group(1)
1041 viewvc_url = GetCodeReviewSetting('VIEW_VC') 1027 viewvc_url = GetCodeReviewSetting('VIEW_VC')
1042 change_info.description += '\n'
1043 if viewvc_url and revision: 1028 if viewvc_url and revision:
1044 change_info.description += "\nCommitted: " + viewvc_url + revision 1029 change_info.append_footer('Committed: ' + viewvc_url + revision)
1045 elif revision: 1030 elif revision:
1046 change_info.description += "\nCommitted: " + revision 1031 change_info.append_footer('Committed: ' + revision)
1047 change_info.CloseIssue() 1032 change_info.CloseIssue()
1048 props = change_info.RpcServer().get_issue_properties( 1033 props = change_info.RpcServer().get_issue_properties(
1049 change_info.issue, False) 1034 change_info.issue, False)
1050 patch_num = len(props['patchsets']) 1035 patch_num = len(props['patchsets'])
1051 comment = "Committed patchset #%d manually as r%s" % (patch_num, revision) 1036 comment = "Committed patchset #%d manually as r%s" % (patch_num, revision)
1052 comment += ' (presubmit successful).' if not bypassed else '.' 1037 comment += ' (presubmit successful).' if not bypassed else '.'
1053 change_info.AddComment(comment) 1038 change_info.AddComment(comment)
1054 return 0 1039 return 0
1055 1040
1056 1041
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 ErrorExit('Running editor failed') 1116 ErrorExit('Running editor failed')
1132 1117
1133 split_result = result.split(separator1, 1) 1118 split_result = result.split(separator1, 1)
1134 if len(split_result) != 2: 1119 if len(split_result) != 2:
1135 ErrorExit("Don't modify the text starting with ---!\n\n%r" % result) 1120 ErrorExit("Don't modify the text starting with ---!\n\n%r" % result)
1136 1121
1137 # Update the CL description if it has changed. 1122 # Update the CL description if it has changed.
1138 new_description = split_result[0] 1123 new_description = split_result[0]
1139 cl_files_text = split_result[1] 1124 cl_files_text = split_result[1]
1140 if new_description != description or override_description: 1125 if new_description != description or override_description:
1141 change_info.description = new_description 1126 change_info.force_description(new_description)
1142 change_info.needs_upload = True
1143 1127
1144 new_cl_files = [] 1128 new_cl_files = []
1145 for line in cl_files_text.splitlines(): 1129 for line in cl_files_text.splitlines():
1146 if not len(line): 1130 if not len(line):
1147 continue 1131 continue
1148 if line.startswith("---"): 1132 if line.startswith("---"):
1149 break 1133 break
1150 status = line[:7] 1134 status = line[:7]
1151 filename = line[7:] 1135 filename = line[7:]
1152 new_cl_files.append((status, filename)) 1136 new_cl_files.append((status, filename))
1153 1137
1154 if (not len(change_info.GetFiles()) and not change_info.issue and 1138 if (not len(change_info.GetFiles()) and not change_info.issue and
1155 not len(new_description) and not new_cl_files): 1139 not len(new_description) and not new_cl_files):
1156 ErrorExit("Empty changelist not saved") 1140 ErrorExit("Empty changelist not saved")
1157 1141
1158 change_info._files = new_cl_files 1142 change_info._files = new_cl_files
1159 change_info.Save() 1143 change_info.Save()
1160 if svn_info.get('URL', '').startswith('http:'): 1144 if svn_info.get('URL', '').startswith('http:'):
1161 Warn("WARNING: Creating CL in a read-only checkout. You will need to " 1145 Warn("WARNING: Creating CL in a read-only checkout. You will need to "
1162 "commit using a commit queue!") 1146 "commit using a commit queue!")
1163 1147
1164 print change_info.name + " changelist saved." 1148 print change_info.name + " changelist saved."
1165 if change_info.MissingTests(): 1149 if change_info.MissingTests():
1166 Warn("WARNING: " + MISSING_TEST_MSG) 1150 Warn("WARNING: " + MISSING_TEST_MSG)
1167 1151
1168 # Update the Rietveld issue. 1152 # Update the Rietveld issue.
1169 if change_info.issue and change_info.NeedsUpload(): 1153 if change_info.issue and change_info.NeedsUpload():
1170 change_info.UpdateRietveldDescription() 1154 change_info.UpdateRietveldDescription()
1171 change_info.needs_upload = False
1172 change_info.Save() 1155 change_info.Save()
1173 return 0 1156 return 0
1174 1157
1175 1158
1176 @need_change_and_args 1159 @need_change_and_args
1177 def CMDlint(change_info, args): 1160 def CMDlint(change_info, args):
1178 """Runs cpplint.py on all the files in the change list. 1161 """Runs cpplint.py on all the files in the change list.
1179 1162
1180 Checks all the files in the changelist for possible style violations. 1163 Checks all the files in the changelist for possible style violations.
1181 """ 1164 """
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 raise 1453 raise
1471 print >> sys.stderr, ( 1454 print >> sys.stderr, (
1472 'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' 1455 'AppEngine is misbehaving and returned HTTP %d, again. Keep faith '
1473 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) 1456 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))
1474 return 1 1457 return 1
1475 1458
1476 1459
1477 if __name__ == "__main__": 1460 if __name__ == "__main__":
1478 fix_encoding.fix_encoding() 1461 fix_encoding.fix_encoding()
1479 sys.exit(main(sys.argv[1:])) 1462 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « no previous file | tests/gcl_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698