| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 | 226 |
| 227 | 227 |
| 228 def ErrorExit(msg): | 228 def ErrorExit(msg): |
| 229 print >> sys.stderr, msg | 229 print >> sys.stderr, msg |
| 230 sys.exit(1) | 230 sys.exit(1) |
| 231 | 231 |
| 232 | 232 |
| 233 def RunShellWithReturnCode(command, print_output=False): | 233 def RunShellWithReturnCode(command, print_output=False): |
| 234 """Executes a command and returns the output and the return code.""" | 234 """Executes a command and returns the output and the return code.""" |
| 235 p = subprocess2.Popen( | 235 p = subprocess2.Popen( |
| 236 command, stdout=subprocess2.PIPE, | 236 command, |
| 237 stderr=subprocess2.STDOUT, universal_newlines=True) | 237 cwd=GetRepositoryRoot(), |
| 238 stdout=subprocess2.PIPE, |
| 239 stderr=subprocess2.STDOUT, |
| 240 universal_newlines=True) |
| 238 if print_output: | 241 if print_output: |
| 239 output_array = [] | 242 output_array = [] |
| 240 while True: | 243 while True: |
| 241 line = p.stdout.readline() | 244 line = p.stdout.readline() |
| 242 if not line: | 245 if not line: |
| 243 break | 246 break |
| 244 if print_output: | 247 if print_output: |
| 245 print line.strip('\n') | 248 print line.strip('\n') |
| 246 output_array.append(line) | 249 output_array.append(line) |
| 247 output = "".join(output_array) | 250 output = "".join(output_array) |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 status = line[:7] | 609 status = line[:7] |
| 607 filename = line[7:] | 610 filename = line[7:] |
| 608 values['files'].append((status, filename)) | 611 values['files'].append((status, filename)) |
| 609 values['description'] = split_data[2] | 612 values['description'] = split_data[2] |
| 610 return values | 613 return values |
| 611 | 614 |
| 612 @staticmethod | 615 @staticmethod |
| 613 def _LoadNewFormat(content): | 616 def _LoadNewFormat(content): |
| 614 return json.loads(content) | 617 return json.loads(content) |
| 615 | 618 |
| 619 def __str__(self): |
| 620 out = ['%s:' % self.__class__.__name__] |
| 621 for k in dir(self): |
| 622 if k.startswith('__'): |
| 623 continue |
| 624 v = getattr(self, k) |
| 625 if v is self or callable(getattr(self, k)): |
| 626 continue |
| 627 out.append(' %s: %r' % (k, v)) |
| 628 return '\n'.join(out) |
| 629 |
| 616 | 630 |
| 617 def GetChangelistInfoFile(changename): | 631 def GetChangelistInfoFile(changename): |
| 618 """Returns the file that stores information about a changelist.""" | 632 """Returns the file that stores information about a changelist.""" |
| 619 if not changename or re.search(r'[^\w-]', changename): | 633 if not changename or re.search(r'[^\w-]', changename): |
| 620 ErrorExit("Invalid changelist name: " + changename) | 634 ErrorExit("Invalid changelist name: " + changename) |
| 621 return os.path.join(GetChangesDir(), changename) | 635 return os.path.join(GetChangesDir(), changename) |
| 622 | 636 |
| 623 | 637 |
| 624 def LoadChangelistInfoForMultiple(changenames, local_root, fail_on_not_found, | 638 def LoadChangelistInfoForMultiple(changenames, local_root, fail_on_not_found, |
| 625 update_status): | 639 update_status): |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 dir_prefix = os.getcwd()[len(GetRepositoryRoot()):].strip(os.sep) | 686 dir_prefix = os.getcwd()[len(GetRepositoryRoot()):].strip(os.sep) |
| 673 | 687 |
| 674 # Get a list of all files in changelists. | 688 # Get a list of all files in changelists. |
| 675 files_in_cl = {} | 689 files_in_cl = {} |
| 676 for cl in GetCLs(): | 690 for cl in GetCLs(): |
| 677 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), | 691 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), |
| 678 fail_on_not_found=True, update_status=False) | 692 fail_on_not_found=True, update_status=False) |
| 679 for status, filename in change_info.GetFiles(): | 693 for status, filename in change_info.GetFiles(): |
| 680 files_in_cl[filename] = change_info.name | 694 files_in_cl[filename] = change_info.name |
| 681 | 695 |
| 682 # Get all the modified files. | 696 # Get all the modified files down the current directory. |
| 683 status_result = SVN.CaptureStatus(None, GetRepositoryRoot()) | 697 for line in SVN.CaptureStatus(None, os.getcwd()): |
| 684 for line in status_result: | |
| 685 status = line[0] | 698 status = line[0] |
| 686 filename = line[1] | 699 filename = line[1] |
| 687 if status[0] == "?": | 700 if status[0] == "?": |
| 688 continue | 701 continue |
| 689 if dir_prefix: | 702 if dir_prefix: |
| 690 filename = os.path.join(dir_prefix, filename) | 703 filename = os.path.join(dir_prefix, filename) |
| 691 change_list_name = "" | 704 change_list_name = "" |
| 692 if filename in files_in_cl: | 705 if filename in files_in_cl: |
| 693 change_list_name = files_in_cl[filename] | 706 change_list_name = files_in_cl[filename] |
| 694 files.setdefault(change_list_name, []).append((status, filename)) | 707 files.setdefault(change_list_name, []).append((status, filename)) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 cc_list = ','.join(filter(None, [cc_list] + watchers)) | 890 cc_list = ','.join(filter(None, [cc_list] + watchers)) |
| 878 if cc_list: | 891 if cc_list: |
| 879 upload_arg.append("--cc=" + cc_list) | 892 upload_arg.append("--cc=" + cc_list) |
| 880 upload_arg.append("--description_file=" + desc_file + "") | 893 upload_arg.append("--description_file=" + desc_file + "") |
| 881 if change_info.subject: | 894 if change_info.subject: |
| 882 upload_arg.append("--message=" + change_info.subject) | 895 upload_arg.append("--message=" + change_info.subject) |
| 883 | 896 |
| 884 if GetCodeReviewSetting("PRIVATE") == "True": | 897 if GetCodeReviewSetting("PRIVATE") == "True": |
| 885 upload_arg.append("--private") | 898 upload_arg.append("--private") |
| 886 | 899 |
| 900 # If we have a lot of files with long paths, then we won't be able to fit |
| 901 # the command to "svn diff". Instead, we generate the diff manually for |
| 902 # each file and concatenate them before passing it to upload.py. |
| 903 if change_info.patch is None: |
| 904 change_info.patch = GenerateDiff(change_info.GetFileNames()) |
| 905 |
| 887 # Change the current working directory before calling upload.py so that it | 906 # Change the current working directory before calling upload.py so that it |
| 888 # shows the correct base. | 907 # shows the correct base. |
| 889 previous_cwd = os.getcwd() | 908 previous_cwd = os.getcwd() |
| 890 os.chdir(change_info.GetLocalRoot()) | 909 os.chdir(change_info.GetLocalRoot()) |
| 891 # If we have a lot of files with long paths, then we won't be able to fit | |
| 892 # the command to "svn diff". Instead, we generate the diff manually for | |
| 893 # each file and concatenate them before passing it to upload.py. | |
| 894 if change_info.patch is None: | |
| 895 change_info.patch = GenerateDiff(change_info.GetFileNames()) | |
| 896 try: | 910 try: |
| 897 issue, patchset = upload.RealMain(upload_arg, change_info.patch) | 911 try: |
| 898 except KeyboardInterrupt: | 912 issue, patchset = upload.RealMain(upload_arg, change_info.patch) |
| 899 sys.exit(1) | 913 except KeyboardInterrupt: |
| 900 if issue and patchset: | 914 sys.exit(1) |
| 901 change_info.issue = int(issue) | 915 if issue and patchset: |
| 902 change_info.patchset = int(patchset) | 916 change_info.issue = int(issue) |
| 903 change_info.Save() | 917 change_info.patchset = int(patchset) |
| 918 change_info.Save() |
| 904 | 919 |
| 905 if desc_file: | 920 if desc_file: |
| 906 os.remove(desc_file) | 921 os.remove(desc_file) |
| 907 change_info.PrimeLint() | 922 change_info.PrimeLint() |
| 908 os.chdir(previous_cwd) | 923 finally: |
| 924 os.chdir(previous_cwd) |
| 909 print "*** Upload does not submit a try; use gcl try to submit a try. ***" | 925 print "*** Upload does not submit a try; use gcl try to submit a try. ***" |
| 910 return 0 | 926 return 0 |
| 911 | 927 |
| 912 | 928 |
| 913 @need_change_and_args | 929 @need_change_and_args |
| 914 @attrs(usage='[--upload]') | 930 @attrs(usage='[--upload]') |
| 915 def CMDpresubmit(change_info, args): | 931 def CMDpresubmit(change_info, args): |
| 916 """Runs presubmit checks on the change. | 932 """Runs presubmit checks on the change. |
| 917 | 933 |
| 918 The actual presubmit code is implemented in presubmit_support.py and looks | 934 The actual presubmit code is implemented in presubmit_support.py and looks |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 os.write(handle, commit_message) | 1020 os.write(handle, commit_message) |
| 1005 os.close(handle) | 1021 os.close(handle) |
| 1006 try: | 1022 try: |
| 1007 handle, targets_filename = tempfile.mkstemp(text=True) | 1023 handle, targets_filename = tempfile.mkstemp(text=True) |
| 1008 os.write(handle, "\n".join(change_info.GetFileNames())) | 1024 os.write(handle, "\n".join(change_info.GetFileNames())) |
| 1009 os.close(handle) | 1025 os.close(handle) |
| 1010 try: | 1026 try: |
| 1011 commit_cmd += ['--file=' + commit_filename] | 1027 commit_cmd += ['--file=' + commit_filename] |
| 1012 commit_cmd += ['--targets=' + targets_filename] | 1028 commit_cmd += ['--targets=' + targets_filename] |
| 1013 # Change the current working directory before calling commit. | 1029 # Change the current working directory before calling commit. |
| 1014 previous_cwd = os.getcwd() | |
| 1015 os.chdir(change_info.GetLocalRoot()) | |
| 1016 output = '' | 1030 output = '' |
| 1017 try: | 1031 try: |
| 1018 output = RunShell(commit_cmd, True) | 1032 output = RunShell(commit_cmd, True) |
| 1019 except subprocess2.CalledProcessError, e: | 1033 except subprocess2.CalledProcessError, e: |
| 1020 ErrorExit('Commit failed.\n%s' % e) | 1034 ErrorExit('Commit failed.\n%s' % e) |
| 1021 finally: | 1035 finally: |
| 1022 os.remove(commit_filename) | 1036 os.remove(commit_filename) |
| 1023 finally: | 1037 finally: |
| 1024 os.remove(targets_filename) | 1038 os.remove(targets_filename) |
| 1025 if output.find("Committed revision") != -1: | 1039 if output.find("Committed revision") != -1: |
| 1026 change_info.Delete() | 1040 change_info.Delete() |
| 1027 | 1041 |
| 1028 if change_info.issue: | 1042 if change_info.issue: |
| 1029 revision = re.compile(".*?\nCommitted revision (\d+)", | 1043 revision = re.compile(".*?\nCommitted revision (\d+)", |
| 1030 re.DOTALL).match(output).group(1) | 1044 re.DOTALL).match(output).group(1) |
| 1031 viewvc_url = GetCodeReviewSetting("VIEW_VC") | 1045 viewvc_url = GetCodeReviewSetting("VIEW_VC") |
| 1032 change_info.description += '\n' | 1046 change_info.description += '\n' |
| 1033 if viewvc_url: | 1047 if viewvc_url: |
| 1034 change_info.description += "\nCommitted: " + viewvc_url + revision | 1048 change_info.description += "\nCommitted: " + viewvc_url + revision |
| 1035 change_info.CloseIssue() | 1049 change_info.CloseIssue() |
| 1036 os.chdir(previous_cwd) | |
| 1037 return 0 | 1050 return 0 |
| 1038 | 1051 |
| 1039 | 1052 |
| 1040 def CMDchange(args): | 1053 def CMDchange(args): |
| 1041 """Creates or edits a changelist. | 1054 """Creates or edits a changelist. |
| 1042 | 1055 |
| 1043 Only scans the current directory and subdirectories. | 1056 Only scans the current directory and subdirectories. |
| 1044 """ | 1057 """ |
| 1045 # Verify the user is running the change command from a read-write checkout. | 1058 # Verify the user is running the change command from a read-write checkout. |
| 1046 svn_info = SVN.CaptureLocalInfo([], '.') | 1059 svn_info = SVN.CaptureLocalInfo([], '.') |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 change_info.Save() | 1168 change_info.Save() |
| 1156 return 0 | 1169 return 0 |
| 1157 | 1170 |
| 1158 | 1171 |
| 1159 @need_change_and_args | 1172 @need_change_and_args |
| 1160 def CMDlint(change_info, args): | 1173 def CMDlint(change_info, args): |
| 1161 """Runs cpplint.py on all the files in the change list. | 1174 """Runs cpplint.py on all the files in the change list. |
| 1162 | 1175 |
| 1163 Checks all the files in the changelist for possible style violations. | 1176 Checks all the files in the changelist for possible style violations. |
| 1164 """ | 1177 """ |
| 1178 # Access to a protected member _XX of a client class |
| 1179 # pylint: disable=W0212 |
| 1165 try: | 1180 try: |
| 1166 import cpplint | 1181 import cpplint |
| 1167 import cpplint_chromium | 1182 import cpplint_chromium |
| 1168 except ImportError: | 1183 except ImportError: |
| 1169 ErrorExit("You need to install cpplint.py to lint C++ files.") | 1184 ErrorExit("You need to install cpplint.py to lint C++ files.") |
| 1170 # Change the current working directory before calling lint so that it | 1185 # Change the current working directory before calling lint so that it |
| 1171 # shows the correct base. | 1186 # shows the correct base. |
| 1172 previous_cwd = os.getcwd() | 1187 previous_cwd = os.getcwd() |
| 1173 os.chdir(change_info.GetLocalRoot()) | 1188 os.chdir(change_info.GetLocalRoot()) |
| 1174 # Process cpplints arguments if any. | 1189 try: |
| 1175 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) | 1190 # Process cpplints arguments if any. |
| 1191 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) |
| 1176 | 1192 |
| 1177 white_list = GetCodeReviewSetting("LINT_REGEX") | 1193 white_list = GetCodeReviewSetting("LINT_REGEX") |
| 1178 if not white_list: | 1194 if not white_list: |
| 1179 white_list = DEFAULT_LINT_REGEX | 1195 white_list = DEFAULT_LINT_REGEX |
| 1180 white_regex = re.compile(white_list) | 1196 white_regex = re.compile(white_list) |
| 1181 black_list = GetCodeReviewSetting("LINT_IGNORE_REGEX") | 1197 black_list = GetCodeReviewSetting("LINT_IGNORE_REGEX") |
| 1182 if not black_list: | 1198 if not black_list: |
| 1183 black_list = DEFAULT_LINT_IGNORE_REGEX | 1199 black_list = DEFAULT_LINT_IGNORE_REGEX |
| 1184 black_regex = re.compile(black_list) | 1200 black_regex = re.compile(black_list) |
| 1185 extra_check_functions = [cpplint_chromium.CheckPointerDeclarationWhitespace] | 1201 extra_check_functions = [cpplint_chromium.CheckPointerDeclarationWhitespace] |
| 1186 # Access to a protected member _XX of a client class | 1202 for filename in filenames: |
| 1187 # pylint: disable=W0212 | 1203 if white_regex.match(filename): |
| 1188 for filename in filenames: | 1204 if black_regex.match(filename): |
| 1189 if white_regex.match(filename): | 1205 print "Ignoring file %s" % filename |
| 1190 if black_regex.match(filename): | 1206 else: |
| 1191 print "Ignoring file %s" % filename | 1207 cpplint.ProcessFile(filename, cpplint._cpplint_state.verbose_level, |
| 1208 extra_check_functions) |
| 1192 else: | 1209 else: |
| 1193 cpplint.ProcessFile(filename, cpplint._cpplint_state.verbose_level, | 1210 print "Skipping file %s" % filename |
| 1194 extra_check_functions) | 1211 finally: |
| 1195 else: | 1212 os.chdir(previous_cwd) |
| 1196 print "Skipping file %s" % filename | |
| 1197 | 1213 |
| 1198 print "Total errors found: %d\n" % cpplint._cpplint_state.error_count | 1214 print "Total errors found: %d\n" % cpplint._cpplint_state.error_count |
| 1199 os.chdir(previous_cwd) | |
| 1200 return 1 | 1215 return 1 |
| 1201 | 1216 |
| 1202 | 1217 |
| 1203 def DoPresubmitChecks(change_info, committing, may_prompt): | 1218 def DoPresubmitChecks(change_info, committing, may_prompt): |
| 1204 """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" | 1219 """Imports presubmit, then calls presubmit.DoPresubmitChecks.""" |
| 1205 root_presubmit = GetCachedFile('PRESUBMIT.py', use_root=True) | 1220 root_presubmit = GetCachedFile('PRESUBMIT.py', use_root=True) |
| 1206 change = presubmit_support.SvnChange(change_info.name, | 1221 change = presubmit_support.SvnChange(change_info.name, |
| 1207 change_info.description, | 1222 change_info.description, |
| 1208 change_info.GetLocalRoot(), | 1223 change_info.GetLocalRoot(), |
| 1209 change_info.GetFiles(), | 1224 change_info.GetFiles(), |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1449 raise | 1464 raise |
| 1450 print >> sys.stderr, ( | 1465 print >> sys.stderr, ( |
| 1451 'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' | 1466 'AppEngine is misbehaving and returned HTTP %d, again. Keep faith ' |
| 1452 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) | 1467 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e)) |
| 1453 return 1 | 1468 return 1 |
| 1454 | 1469 |
| 1455 | 1470 |
| 1456 if __name__ == "__main__": | 1471 if __name__ == "__main__": |
| 1457 fix_encoding.fix_encoding() | 1472 fix_encoding.fix_encoding() |
| 1458 sys.exit(main(sys.argv[1:])) | 1473 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |