OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 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 """Wrapper script around Rietveld's upload.py that groups files into | 6 """Wrapper script around Rietveld's upload.py that groups files into |
7 changelists.""" | 7 changelists.""" |
8 | 8 |
9 import getpass | 9 import getpass |
10 import os | 10 import os |
11 import random | 11 import random |
12 import re | 12 import re |
13 import shutil | 13 import shutil |
14 import string | 14 import string |
15 import subprocess | 15 import subprocess |
16 import sys | 16 import sys |
17 import tempfile | 17 import tempfile |
18 import time | 18 import time |
19 from third_party import upload | 19 from third_party import upload |
20 import urllib2 | 20 import urllib2 |
21 | 21 |
22 __pychecker__ = 'unusednames=breakpad' | 22 __pychecker__ = 'unusednames=breakpad' |
23 import breakpad | 23 import breakpad |
24 __pychecker__ = '' | 24 __pychecker__ = '' |
25 | 25 |
26 # gcl now depends on gclient. | 26 # gcl now depends on gclient. |
27 from scm import SVN | 27 from scm import SVN |
28 import gclient_utils | 28 import gclient_utils |
29 | 29 |
30 __version__ = '1.1.3' | 30 __version__ = '1.1.4' |
31 | 31 |
32 | 32 |
33 CODEREVIEW_SETTINGS = { | 33 CODEREVIEW_SETTINGS = { |
34 # Ideally, we want to set |CODE_REVIEW_SERVER| to a generic server like | 34 # Ideally, we want to set |CODE_REVIEW_SERVER| to a generic server like |
35 # codereview.appspot.com and remove |CC_LIST| and |VIEW_VC|. In practice, we | 35 # codereview.appspot.com and remove |CC_LIST| and |VIEW_VC|. In practice, we |
36 # need these settings so developers making changes in directories such as | 36 # need these settings so developers making changes in directories such as |
37 # Chromium's src/third_party/WebKit will send change lists to the correct | 37 # Chromium's src/third_party/WebKit will send change lists to the correct |
38 # server. | 38 # server. |
39 # | 39 # |
40 # To make gcl send reviews to a different server, check in a file named | 40 # To make gcl send reviews to a different server, check in a file named |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
74 if sys.platform in ('cygwin', 'win32'): | 74 if sys.platform in ('cygwin', 'win32'): |
75 home_vars.append('USERPROFILE') | 75 home_vars.append('USERPROFILE') |
76 for home_var in home_vars: | 76 for home_var in home_vars: |
77 home = os.getenv(home_var) | 77 home = os.getenv(home_var) |
78 if home != None: | 78 if home != None: |
79 full_path = os.path.join(home, filename) | 79 full_path = os.path.join(home, filename) |
80 if os.path.exists(full_path): | 80 if os.path.exists(full_path): |
81 return full_path | 81 return full_path |
82 return None | 82 return None |
83 | 83 |
| 84 |
84 def UnknownFiles(extra_args): | 85 def UnknownFiles(extra_args): |
85 """Runs svn status and returns unknown files. | 86 """Runs svn status and returns unknown files. |
86 | 87 |
87 Any args in |extra_args| are passed to the tool to support giving alternate | 88 Any args in |extra_args| are passed to the tool to support giving alternate |
88 code locations. | 89 code locations. |
89 """ | 90 """ |
90 return [item[1] for item in SVN.CaptureStatus(extra_args) | 91 return [item[1] for item in SVN.CaptureStatus(extra_args) |
91 if item[0][0] == '?'] | 92 if item[0][0] == '?'] |
92 | 93 |
93 | 94 |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 if (files.get('') or (show_unknown_files and len(unknown_files))): | 616 if (files.get('') or (show_unknown_files and len(unknown_files))): |
616 print "\n--- Not in any changelist:" | 617 print "\n--- Not in any changelist:" |
617 for item in files.get('', []): | 618 for item in files.get('', []): |
618 print "".join(item) | 619 print "".join(item) |
619 if show_unknown_files: | 620 if show_unknown_files: |
620 for filename in unknown_files: | 621 for filename in unknown_files: |
621 print "? %s" % filename | 622 print "? %s" % filename |
622 return 0 | 623 return 0 |
623 | 624 |
624 | 625 |
625 def CMDopened(argv): | 626 def CMDopened(args): |
626 """Lists modified files in the current directory down.""" | 627 """Lists modified files in the current directory down.""" |
627 __pychecker__ = 'unusednames=argv' | 628 if args: |
| 629 ErrorExit("Doesn't support arguments") |
628 return ListFiles(False) | 630 return ListFiles(False) |
629 | 631 |
630 | 632 |
631 def CMDstatus(argv): | 633 def CMDstatus(args): |
632 """Lists modified and unknown files in the current directory down.""" | 634 """Lists modified and unknown files in the current directory down.""" |
633 __pychecker__ = 'unusednames=argv' | 635 if args: |
| 636 ErrorExit("Doesn't support arguments") |
634 return ListFiles(True) | 637 return ListFiles(True) |
635 | 638 |
636 | 639 |
637 def CMDhelp(argv=None): | 640 def CMDhelp(args): |
638 """Prints this help or help for the given command.""" | 641 """Prints this help or help for the given command.""" |
639 if argv and len(argv) > 2: | 642 if args and len(args) > 2: |
640 if argv[2] == 'try': | 643 if args[2] == 'try': |
641 TryChange(None, ['--help'], swallow_exception=False) | 644 return TryChange(None, ['--help'], swallow_exception=False) |
642 return 0 | 645 if args[2] == 'upload': |
643 if argv[2] == 'upload': | |
644 upload.RealMain(['upload.py', '--help']) | 646 upload.RealMain(['upload.py', '--help']) |
645 return 0 | 647 return 0 |
646 | 648 |
647 print ( | 649 print ( |
648 """GCL is a wrapper for Subversion that simplifies working with groups of files. | 650 """GCL is a wrapper for Subversion that simplifies working with groups of files. |
649 version """ + __version__ + """ | 651 version """ + __version__ + """ |
650 | 652 |
651 Basic commands: | 653 Basic commands: |
652 ----------------------------------------- | 654 ----------------------------------------- |
653 gcl change change_name | 655 gcl change change_name |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 def GenerateDiff(files, root=None): | 739 def GenerateDiff(files, root=None): |
738 return SVN.GenerateDiff(files, root=root) | 740 return SVN.GenerateDiff(files, root=root) |
739 | 741 |
740 | 742 |
741 def OptionallyDoPresubmitChecks(change_info, committing, args): | 743 def OptionallyDoPresubmitChecks(change_info, committing, args): |
742 if FilterFlag(args, "--no_presubmit") or FilterFlag(args, "--force"): | 744 if FilterFlag(args, "--no_presubmit") or FilterFlag(args, "--force"): |
743 return True | 745 return True |
744 return DoPresubmitChecks(change_info, committing, True) | 746 return DoPresubmitChecks(change_info, committing, True) |
745 | 747 |
746 | 748 |
747 def CMDupload(change_info, args): | 749 def need_change(function): |
| 750 """Converts args -> change_info.""" |
| 751 def hook(args): |
| 752 if not len(args) == 1: |
| 753 ErrorExit("You need to pass a change list name") |
| 754 change_info = ChangeInfo.Load(args[0], GetRepositoryRoot(), True, True) |
| 755 return function(change_info) |
| 756 return hook |
| 757 |
| 758 |
| 759 def CMDupload(args): |
| 760 if not args: |
| 761 ErrorExit("You need to pass a change list name") |
| 762 change_info = ChangeInfo.Load(args.pop(0), GetRepositoryRoot(), True, True) |
748 if not change_info.GetFiles(): | 763 if not change_info.GetFiles(): |
749 print "Nothing to upload, changelist is empty." | 764 print "Nothing to upload, changelist is empty." |
750 return | 765 return 0 |
751 if not OptionallyDoPresubmitChecks(change_info, False, args): | 766 if not OptionallyDoPresubmitChecks(change_info, False, args): |
752 return | 767 return 1 |
753 # Might want to support GetInfoDir()/GetRepositoryRoot() like | 768 # Might want to support GetInfoDir()/GetRepositoryRoot() like |
754 # CheckHomeForFile() so the skip of tries can be per tree basis instead | 769 # CheckHomeForFile() so the skip of tries can be per tree basis instead |
755 # of user global. | 770 # of user global. |
756 no_try = FilterFlag(args, "--no_try") or \ | 771 no_try = FilterFlag(args, "--no_try") or \ |
757 FilterFlag(args, "--no-try") or \ | 772 FilterFlag(args, "--no-try") or \ |
758 not (CheckHomeForFile(".gcl_upload_no_try") is None) | 773 not (CheckHomeForFile(".gcl_upload_no_try") is None) |
759 no_watchlists = FilterFlag(args, "--no_watchlists") or \ | 774 no_watchlists = FilterFlag(args, "--no_watchlists") or \ |
760 FilterFlag(args, "--no-watchlists") | 775 FilterFlag(args, "--no-watchlists") |
761 | 776 |
762 # Map --send-mail to --send_mail | 777 # Map --send-mail to --send_mail |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 # consistent. | 864 # consistent. |
850 os.chdir(previous_cwd) | 865 os.chdir(previous_cwd) |
851 | 866 |
852 # Once uploaded to Rietveld, send it to the try server. | 867 # Once uploaded to Rietveld, send it to the try server. |
853 if not no_try: | 868 if not no_try: |
854 try_on_upload = GetCodeReviewSetting('TRY_ON_UPLOAD') | 869 try_on_upload = GetCodeReviewSetting('TRY_ON_UPLOAD') |
855 if try_on_upload and try_on_upload.lower() == 'true': | 870 if try_on_upload and try_on_upload.lower() == 'true': |
856 trychange_args = [] | 871 trychange_args = [] |
857 if clobber: | 872 if clobber: |
858 trychange_args.append('--clobber') | 873 trychange_args.append('--clobber') |
859 TryChange(change_info, trychange_args, swallow_exception=True) | 874 return TryChange(change_info, trychange_args, swallow_exception=True) |
| 875 return 0 |
860 | 876 |
861 | 877 |
862 | 878 @need_change |
863 def CMDpresubmit(change_info, argv): | 879 def CMDpresubmit(change_info): |
864 """Runs presubmit checks on the change.""" | 880 """Runs presubmit checks on the change.""" |
865 __pychecker__ = 'unusednames=argv' | |
866 if not change_info.GetFiles(): | 881 if not change_info.GetFiles(): |
867 print "Nothing to presubmit check, changelist is empty." | 882 print "Nothing to presubmit check, changelist is empty." |
868 return 0 | 883 return 0 |
869 | 884 |
870 print "*** Presubmit checks for UPLOAD would report: ***" | 885 print "*** Presubmit checks for UPLOAD would report: ***" |
871 result = DoPresubmitChecks(change_info, False, False) | 886 result = DoPresubmitChecks(change_info, False, False) |
872 | 887 |
873 print "\n*** Presubmit checks for COMMIT would report: ***" | 888 print "\n*** Presubmit checks for COMMIT would report: ***" |
874 result &= DoPresubmitChecks(change_info, True, False) | 889 result &= DoPresubmitChecks(change_info, True, False) |
875 return not result | 890 return not result |
876 | 891 |
877 | 892 |
878 def TryChange(change_info, args, swallow_exception): | 893 def TryChange(change_info, args, swallow_exception): |
879 """Create a diff file of change_info and send it to the try server.""" | 894 """Create a diff file of change_info and send it to the try server.""" |
880 try: | 895 try: |
881 import trychange | 896 import trychange |
882 except ImportError: | 897 except ImportError: |
883 if swallow_exception: | 898 if swallow_exception: |
884 return | 899 return 1 |
885 ErrorExit("You need to install trychange.py to use the try server.") | 900 ErrorExit("You need to install trychange.py to use the try server.") |
886 | 901 |
887 trychange_args = [] | 902 trychange_args = [] |
888 if change_info: | 903 if change_info: |
889 trychange_args.extend(['--name', change_info.name]) | 904 trychange_args.extend(['--name', change_info.name]) |
890 if change_info.issue: | 905 if change_info.issue: |
891 trychange_args.extend(["--issue", str(change_info.issue)]) | 906 trychange_args.extend(["--issue", str(change_info.issue)]) |
892 if change_info.patchset: | 907 if change_info.patchset: |
893 trychange_args.extend(["--patchset", str(change_info.patchset)]) | 908 trychange_args.extend(["--patchset", str(change_info.patchset)]) |
894 trychange_args.extend(args) | 909 trychange_args.extend(args) |
895 file_list = change_info.GetFileNames() | 910 file_list = change_info.GetFileNames() |
896 else: | 911 else: |
897 trychange_args.extend(args) | 912 trychange_args.extend(args) |
898 file_list = None | 913 file_list = None |
899 trychange.TryChange(trychange_args, | 914 return trychange.TryChange(trychange_args, |
900 file_list=file_list, | 915 file_list=file_list, |
901 swallow_exception=swallow_exception, | 916 swallow_exception=swallow_exception, |
902 prog='gcl try') | 917 prog='gcl try') |
903 | 918 |
904 | 919 |
905 def CMDcommit(change_info, args): | 920 @need_change |
| 921 def CMDcommit(change_info): |
906 if not change_info.GetFiles(): | 922 if not change_info.GetFiles(): |
907 print "Nothing to commit, changelist is empty." | 923 print "Nothing to commit, changelist is empty." |
908 return 1 | 924 return 1 |
909 if not OptionallyDoPresubmitChecks(change_info, True, args): | 925 if not OptionallyDoPresubmitChecks(change_info, True, args): |
910 return 1 | 926 return 1 |
911 | 927 |
912 # We face a problem with svn here: Let's say change 'bleh' modifies | 928 # We face a problem with svn here: Let's say change 'bleh' modifies |
913 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies | 929 # svn:ignore on dir1\. but another unrelated change 'pouet' modifies |
914 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. | 930 # dir1\foo.cc. When the user `gcl commit bleh`, foo.cc is *also committed*. |
915 # The only fix is to use --non-recursive but that has its issues too: | 931 # The only fix is to use --non-recursive but that has its issues too: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 re.DOTALL).match(output).group(1) | 968 re.DOTALL).match(output).group(1) |
953 viewvc_url = GetCodeReviewSetting("VIEW_VC") | 969 viewvc_url = GetCodeReviewSetting("VIEW_VC") |
954 change_info.description = change_info.description + '\n' | 970 change_info.description = change_info.description + '\n' |
955 if viewvc_url: | 971 if viewvc_url: |
956 change_info.description += "\nCommitted: " + viewvc_url + revision | 972 change_info.description += "\nCommitted: " + viewvc_url + revision |
957 change_info.CloseIssue() | 973 change_info.CloseIssue() |
958 os.chdir(previous_cwd) | 974 os.chdir(previous_cwd) |
959 return 0 | 975 return 0 |
960 | 976 |
961 | 977 |
962 def CMDchange(change_info, args): | 978 def CMDchange(args): |
963 """Creates/edits a changelist.""" | 979 """Creates/edits a changelist.""" |
| 980 if len(args) == 0: |
| 981 # Generate a random changelist name. |
| 982 changename = GenerateChangeName() |
| 983 elif args[0] == '--force': |
| 984 changename = GenerateChangeName() |
| 985 else: |
| 986 changename = args[0] |
| 987 change_info = ChangeInfo.Load(changename, GetRepositoryRoot(), False, True) |
964 silent = FilterFlag(args, "--silent") | 988 silent = FilterFlag(args, "--silent") |
965 | 989 |
966 # Verify the user is running the change command from a read-write checkout. | 990 # Verify the user is running the change command from a read-write checkout. |
967 svn_info = SVN.CaptureInfo('.') | 991 svn_info = SVN.CaptureInfo('.') |
968 if not svn_info: | 992 if not svn_info: |
969 ErrorExit("Current checkout is unversioned. Please retry with a versioned " | 993 ErrorExit("Current checkout is unversioned. Please retry with a versioned " |
970 "directory.") | 994 "directory.") |
971 | 995 |
972 if (len(args) == 1): | 996 if len(args) == 2: |
973 filename = args[0] | 997 f = open(args[1], 'rU') |
974 f = open(filename, 'rU') | |
975 override_description = f.read() | 998 override_description = f.read() |
976 f.close() | 999 f.close() |
977 else: | 1000 else: |
978 override_description = None | 1001 override_description = None |
979 | 1002 |
980 if change_info.issue and not change_info.NeedsUpload(): | 1003 if change_info.issue and not change_info.NeedsUpload(): |
981 try: | 1004 try: |
982 description = GetIssueDescription(change_info.issue) | 1005 description = GetIssueDescription(change_info.issue) |
983 except urllib2.HTTPError, err: | 1006 except urllib2.HTTPError, err: |
984 if err.code == 404: | 1007 if err.code == 404: |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 Warn("WARNING: " + MISSING_TEST_MSG) | 1089 Warn("WARNING: " + MISSING_TEST_MSG) |
1067 | 1090 |
1068 # Update the Rietveld issue. | 1091 # Update the Rietveld issue. |
1069 if change_info.issue and change_info.NeedsUpload(): | 1092 if change_info.issue and change_info.NeedsUpload(): |
1070 change_info.UpdateRietveldDescription() | 1093 change_info.UpdateRietveldDescription() |
1071 change_info.needs_upload = False | 1094 change_info.needs_upload = False |
1072 change_info.Save() | 1095 change_info.Save() |
1073 return 0 | 1096 return 0 |
1074 | 1097 |
1075 | 1098 |
1076 def CMDlint(change_info, args): | 1099 @need_change |
| 1100 def CMDlint(change_info): |
1077 """Runs cpplint.py on all the files in |change_info|""" | 1101 """Runs cpplint.py on all the files in |change_info|""" |
1078 try: | 1102 try: |
1079 import cpplint | 1103 import cpplint |
1080 except ImportError: | 1104 except ImportError: |
1081 ErrorExit("You need to install cpplint.py to lint C++ files.") | 1105 ErrorExit("You need to install cpplint.py to lint C++ files.") |
1082 | |
1083 # Change the current working directory before calling lint so that it | 1106 # Change the current working directory before calling lint so that it |
1084 # shows the correct base. | 1107 # shows the correct base. |
1085 previous_cwd = os.getcwd() | 1108 previous_cwd = os.getcwd() |
1086 os.chdir(change_info.GetLocalRoot()) | 1109 os.chdir(change_info.GetLocalRoot()) |
1087 | 1110 |
1088 # Process cpplints arguments if any. | 1111 # Process cpplints arguments if any. |
1089 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) | 1112 filenames = cpplint.ParseArguments(args + change_info.GetFileNames()) |
1090 | 1113 |
1091 white_list = GetCodeReviewSetting("LINT_REGEX") | 1114 white_list = GetCodeReviewSetting("LINT_REGEX") |
1092 if not white_list: | 1115 if not white_list: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 verbose=False, | 1149 verbose=False, |
1127 output_stream=sys.stdout, | 1150 output_stream=sys.stdout, |
1128 input_stream=sys.stdin, | 1151 input_stream=sys.stdin, |
1129 default_presubmit=root_presubmit, | 1152 default_presubmit=root_presubmit, |
1130 may_prompt=may_prompt) | 1153 may_prompt=may_prompt) |
1131 if not result and may_prompt: | 1154 if not result and may_prompt: |
1132 print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" | 1155 print "\nPresubmit errors, can't continue (use --no_presubmit to bypass)" |
1133 return result | 1156 return result |
1134 | 1157 |
1135 | 1158 |
1136 def CMDchanges(argv): | 1159 def CMDchanges(args): |
1137 """Lists all the changelists and their files.""" | 1160 """Lists all the changelists and their files.""" |
1138 __pychecker__ = 'unusednames=argv' | 1161 if args: |
| 1162 ErrorExit("Doesn't support arguments") |
1139 for cl in GetCLs(): | 1163 for cl in GetCLs(): |
1140 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), True, True) | 1164 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), True, True) |
1141 print "\n--- Changelist " + change_info.name + ":" | 1165 print "\n--- Changelist " + change_info.name + ":" |
1142 for filename in change_info.GetFiles(): | 1166 for filename in change_info.GetFiles(): |
1143 print "".join(filename) | 1167 print "".join(filename) |
1144 return 0 | 1168 return 0 |
1145 | 1169 |
1146 | 1170 |
1147 def CMDdeleteempties(argv): | 1171 def CMDdeleteempties(args): |
1148 """Delete all changelists that have no files.""" | 1172 """Delete all changelists that have no files.""" |
1149 __pychecker__ = 'unusednames=argv' | 1173 if args: |
| 1174 ErrorExit("Doesn't support arguments") |
1150 print "\n--- Deleting:" | 1175 print "\n--- Deleting:" |
1151 for cl in GetCLs(): | 1176 for cl in GetCLs(): |
1152 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), True, True) | 1177 change_info = ChangeInfo.Load(cl, GetRepositoryRoot(), True, True) |
1153 if not len(change_info._files): | 1178 if not len(change_info._files): |
1154 print change_info.name | 1179 print change_info.name |
1155 change_info.Delete() | 1180 change_info.Delete() |
1156 return 0 | 1181 return 0 |
1157 | 1182 |
1158 | 1183 |
1159 def CMDnothave(argv): | 1184 def CMDnothave(args): |
1160 """Lists files unknown to Subversion.""" | 1185 """Lists files unknown to Subversion.""" |
1161 __pychecker__ = 'unusednames=argv' | 1186 if args: |
1162 for filename in UnknownFiles(argv[2:]): | 1187 ErrorExit("Doesn't support arguments") |
| 1188 for filename in UnknownFiles(args): |
1163 print "? " + "".join(filename) | 1189 print "? " + "".join(filename) |
1164 return 0 | 1190 return 0 |
1165 | 1191 |
1166 | 1192 |
1167 def CMDdiff(argv): | 1193 def CMDdiff(args): |
1168 """Diffs all files in the changelist.""" | 1194 """Diffs all files in the changelist.""" |
1169 __pychecker__ = 'unusednames=argv' | 1195 files = None |
1170 files = GetFilesNotInCL() | 1196 if args: |
1171 print GenerateDiff([x[1] for x in files]) | 1197 change_info = ChangeInfo.Load(args[0], GetRepositoryRoot(), True, True) |
1172 return 0 | 1198 args.pop(0) |
| 1199 files = change_info.GetFileNames() |
| 1200 else: |
| 1201 files = GetFilesNotInCL() |
| 1202 return RunShellWithReturnCode(['svn', 'diff'] + files + args, |
| 1203 print_output=True)[1] |
1173 | 1204 |
1174 | 1205 |
1175 def CMDsettings(argv): | 1206 def CMDsettings(args): |
1176 """Prints code review settings.""" | 1207 """Prints code review settings.""" |
1177 __pychecker__ = 'unusednames=argv' | 1208 __pychecker__ = 'unusednames=args' |
1178 # Force load settings | 1209 # Force load settings |
1179 GetCodeReviewSetting("UNKNOWN"); | 1210 GetCodeReviewSetting("UNKNOWN"); |
1180 del CODEREVIEW_SETTINGS['__just_initialized'] | 1211 del CODEREVIEW_SETTINGS['__just_initialized'] |
1181 print '\n'.join(("%s: %s" % (str(k), str(v)) | 1212 print '\n'.join(("%s: %s" % (str(k), str(v)) |
1182 for (k,v) in CODEREVIEW_SETTINGS.iteritems())) | 1213 for (k,v) in CODEREVIEW_SETTINGS.iteritems())) |
1183 return 0 | 1214 return 0 |
1184 | 1215 |
1185 | 1216 |
1186 def CMDdescription(change_info, argv): | 1217 @need_change |
| 1218 def CMDdescription(change_info): |
1187 """Prints the description of the specified change to stdout.""" | 1219 """Prints the description of the specified change to stdout.""" |
1188 __pychecker__ = 'unusednames=argv' | |
1189 print change_info.description | 1220 print change_info.description |
1190 return 0 | 1221 return 0 |
1191 | 1222 |
1192 | 1223 |
1193 def CMDdelete(change_info, argv): | 1224 @need_change |
| 1225 def CMDdelete(change_info): |
1194 """Deletes a changelist.""" | 1226 """Deletes a changelist.""" |
1195 __pychecker__ = 'unusednames=argv' | |
1196 change_info.Delete() | 1227 change_info.Delete() |
1197 return 0 | 1228 return 0 |
1198 | 1229 |
1199 | 1230 |
1200 def CMDtry(change_info, argv): | 1231 def CMDtry(args): |
1201 """Sends the change to the tryserver so a trybot can do a test run on your | 1232 """Sends the change to the tryserver so a trybot can do a test run on your |
1202 code. | 1233 code. |
1203 | 1234 |
1204 To send multiple changes as one path, use a comma-separated list of | 1235 To send multiple changes as one path, use a comma-separated list of |
1205 changenames. Use 'gcl help try' for more information!""" | 1236 changenames. Use 'gcl help try' for more information!""" |
1206 # When the change contains no file, send the "changename" positional | 1237 # When the change contains no file, send the "changename" positional |
1207 # argument to trychange.py. | 1238 # argument to trychange.py. |
1208 __pychecker__ = 'unusednames=argv' | 1239 # When the command is 'try' and --patchset is used, the patch to try |
| 1240 # is on the Rietveld server. |
| 1241 if not args: |
| 1242 ErrorExit("You need to pass a change list name") |
| 1243 if args[0].find(',') != -1: |
| 1244 change_info = LoadChangelistInfoForMultiple(args[0], GetRepositoryRoot(), |
| 1245 True, True) |
| 1246 else: |
| 1247 change_info = ChangeInfo.Load(args[0], GetRepositoryRoot(), |
| 1248 False, True) |
1209 if change_info.GetFiles(): | 1249 if change_info.GetFiles(): |
1210 args = argv[3:] | 1250 args = args[1:] |
1211 else: | 1251 else: |
1212 change_info = None | 1252 change_info = None |
1213 args = argv[2:] | 1253 return TryChange(change_info, args, swallow_exception=False) |
1214 TryChange(change_info, args, swallow_exception=False) | |
1215 return 0 | |
1216 | 1254 |
1217 | 1255 |
1218 def CMDrename(argv): | 1256 def CMDrename(args): |
1219 """Renames an existing change.""" | 1257 """Renames an existing change.""" |
1220 if len(argv) != 4: | 1258 if len(args) != 2: |
1221 ErrorExit("Usage: gcl rename <old-name> <new-name>.") | 1259 ErrorExit("Usage: gcl rename <old-name> <new-name>.") |
1222 src, dst = argv[2:4] | 1260 src, dst = args |
1223 src_file = GetChangelistInfoFile(src) | 1261 src_file = GetChangelistInfoFile(src) |
1224 if not os.path.isfile(src_file): | 1262 if not os.path.isfile(src_file): |
1225 ErrorExit("Change '%s' does not exist." % src) | 1263 ErrorExit("Change '%s' does not exist." % src) |
1226 dst_file = GetChangelistInfoFile(dst) | 1264 dst_file = GetChangelistInfoFile(dst) |
1227 if os.path.isfile(dst_file): | 1265 if os.path.isfile(dst_file): |
1228 ErrorExit("Change '%s' already exists; pick a new name." % dst) | 1266 ErrorExit("Change '%s' already exists; pick a new name." % dst) |
1229 os.rename(src_file, dst_file) | 1267 os.rename(src_file, dst_file) |
1230 print "Change '%s' renamed '%s'." % (src, dst) | 1268 print "Change '%s' renamed '%s'." % (src, dst) |
1231 return 0 | 1269 return 0 |
1232 | 1270 |
1233 | 1271 |
1234 def main(argv=None): | 1272 def CMDpassthru(args): |
| 1273 # Everything else that is passed into gcl we redirect to svn, after adding |
| 1274 # the files. |
| 1275 # args is guaranteed to be len(args) >= 1 |
| 1276 args = ["svn", args[0]] |
| 1277 if len(args) > 1: |
| 1278 root = GetRepositoryRoot() |
| 1279 change_info = ChangeInfo.Load(args[1], root, True, True) |
| 1280 args.extend([os.path.join(root, x) for x in change_info.GetFileNames()]) |
| 1281 return RunShellWithReturnCode(args, print_output=True)[1] |
| 1282 |
| 1283 |
| 1284 def main(argv): |
1235 __pychecker__ = 'maxreturns=0' | 1285 __pychecker__ = 'maxreturns=0' |
1236 if argv is None: | |
1237 argv = sys.argv | |
1238 | |
1239 if len(argv) == 1: | |
1240 return CMDhelp() | |
1241 | |
1242 try: | 1286 try: |
1243 # Create the directories where we store information about changelists if it | 1287 # Create the directories where we store information about changelists if it |
1244 # doesn't exist. | 1288 # doesn't exist. |
1245 if not os.path.exists(GetInfoDir()): | 1289 if not os.path.exists(GetInfoDir()): |
1246 os.mkdir(GetInfoDir()) | 1290 os.mkdir(GetInfoDir()) |
1247 if not os.path.exists(GetChangesDir()): | 1291 if not os.path.exists(GetChangesDir()): |
1248 os.mkdir(GetChangesDir()) | 1292 os.mkdir(GetChangesDir()) |
1249 if not os.path.exists(GetCacheDir()): | 1293 if not os.path.exists(GetCacheDir()): |
1250 os.mkdir(GetCacheDir()) | 1294 os.mkdir(GetCacheDir()) |
1251 except gclient_utils.Error: | 1295 except gclient_utils.Error: |
1252 # Will throw an exception if not run in a svn checkout. | 1296 # Will throw an exception if not run in a svn checkout. |
1253 pass | 1297 pass |
1254 | 1298 |
| 1299 if not argv: |
| 1300 argv = ['help'] |
1255 # Commands that don't require an argument. | 1301 # Commands that don't require an argument. |
1256 command = argv[1] | 1302 command = argv[0] |
1257 if command == "opened": | 1303 if command == "opened": |
1258 return CMDopened(argv) | 1304 return CMDopened(argv[1:]) |
1259 if command == "status": | 1305 if command == "status": |
1260 return CMDstatus(argv) | 1306 return CMDstatus(argv[1:]) |
1261 if command == "nothave": | 1307 if command == "nothave": |
1262 return CMDnothave(argv) | 1308 return CMDnothave(argv[1:]) |
1263 if command == "changes": | 1309 if command == "changes": |
1264 return CMDchanges(argv) | 1310 return CMDchanges(argv[1:]) |
1265 if command == "help": | 1311 if command == "help": |
1266 return CMDhelp(argv) | 1312 return CMDhelp(argv[1:]) |
1267 if command == "diff" and len(argv) == 2: | 1313 if command == "diff": |
1268 return CMDdiff(argv) | 1314 return CMDdiff(argv[1:]) |
1269 if command == "settings": | 1315 if command == "settings": |
1270 return CMDsettings(argv) | 1316 return CMDsettings(argv[1:]) |
1271 if command == "deleteempties": | 1317 if command == "deleteempties": |
1272 return CMDdeleteempties(argv) | 1318 return CMDdeleteempties(argv[1:]) |
1273 if command == "rename": | 1319 if command == "rename": |
1274 return CMDrename(argv) | 1320 return CMDrename(argv[1:]) |
1275 if command == "change": | 1321 elif command == "change": |
1276 if len(argv) == 2: | 1322 return CMDchange(argv[1:]) |
1277 # Generate a random changelist name. | 1323 elif command == "description": |
1278 changename = GenerateChangeName() | 1324 return CMDdescription(argv[1:]) |
1279 elif argv[2] == '--force': | 1325 elif command == "lint": |
1280 changename = GenerateChangeName() | 1326 return CMDlint(argv[1:]) |
1281 # argv[3:] is passed to Change() as |args| later. Change() should receive | 1327 elif command == "upload": |
1282 # |args| which includes '--force'. | 1328 return CMDupload(argv[1:]) |
1283 argv.insert(2, changename) | 1329 elif command == "presubmit": |
1284 else: | 1330 return CMDpresubmit(argv[1:]) |
1285 changename = argv[2] | 1331 elif command in ("commit", "submit"): |
1286 elif len(argv) == 2: | 1332 return CMDcommit(argv[1:]) |
1287 ErrorExit("Need a changelist name.") | 1333 elif command == "delete": |
| 1334 return CMDdelete(argv[1:]) |
| 1335 elif command == "try": |
| 1336 return CMDtry(argv[1:]) |
1288 else: | 1337 else: |
1289 changename = argv[2] | 1338 return CMDpassthru(argv) |
1290 | |
1291 # When the command is 'try' and --patchset is used, the patch to try | |
1292 # is on the Rietveld server. 'change' creates a change so it's fine if the | |
1293 # change didn't exist. All other commands require an existing change. | |
1294 fail_on_not_found = command != "try" and command != "change" | |
1295 if command == "try" and changename.find(',') != -1: | |
1296 change_info = LoadChangelistInfoForMultiple(changename, GetRepositoryRoot(), | |
1297 True, True) | |
1298 else: | |
1299 change_info = ChangeInfo.Load(changename, GetRepositoryRoot(), | |
1300 fail_on_not_found, True) | |
1301 | |
1302 if command == "change": | |
1303 return CMDchange(change_info, argv[3:]) | |
1304 elif command == "description": | |
1305 return CMDdescription(change_info, argv[3:]) | |
1306 elif command == "lint": | |
1307 return CMDlint(change_info, argv[3:]) | |
1308 elif command == "upload": | |
1309 return CMDupload(change_info, argv[3:]) | |
1310 elif command == "presubmit": | |
1311 return CMDpresubmit(change_info, argv[3:]) | |
1312 elif command in ("commit", "submit"): | |
1313 return CMDcommit(change_info, argv[3:]) | |
1314 elif command == "delete": | |
1315 return CMDdelete(change_info, argv[3:]) | |
1316 elif command == "try": | |
1317 return CMDtry(change_info, argv) | |
1318 else: | |
1319 # Everything else that is passed into gcl we redirect to svn, after adding | |
1320 # the files. This allows commands such as 'gcl diff xxx' to work. | |
1321 if command == "diff" and not change_info.GetFileNames(): | |
1322 return 0 | |
1323 args =["svn", command] | |
1324 root = GetRepositoryRoot() | |
1325 args.extend([os.path.join(root, x) for x in change_info.GetFileNames()]) | |
1326 RunShell(args, True) | |
1327 return 0 | |
1328 | 1339 |
1329 | 1340 |
1330 if __name__ == "__main__": | 1341 if __name__ == "__main__": |
1331 sys.exit(main()) | 1342 sys.exit(main(sys.argv[1:])) |
OLD | NEW |