| 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 |