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: trunk/tools/depot_tools/gcl.py

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

Powered by Google App Engine
This is Rietveld 408576698