OLD | NEW |
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 # Copyright (C) 2008 Evan Martin <martine@danga.com> | 6 # Copyright (C) 2008 Evan Martin <martine@danga.com> |
7 | 7 |
8 """A git-command for integrating reviews on Rietveld.""" | 8 """A git-command for integrating reviews on Rietveld.""" |
9 | 9 |
10 import logging | 10 import logging |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 def __init__(self): | 140 def __init__(self): |
141 self.default_server = None | 141 self.default_server = None |
142 self.cc = None | 142 self.cc = None |
143 self.root = None | 143 self.root = None |
144 self.is_git_svn = None | 144 self.is_git_svn = None |
145 self.svn_branch = None | 145 self.svn_branch = None |
146 self.tree_status_url = None | 146 self.tree_status_url = None |
147 self.viewvc_url = None | 147 self.viewvc_url = None |
148 self.updated = False | 148 self.updated = False |
149 self.did_migrate_check = False | 149 self.did_migrate_check = False |
| 150 self.is_gerrit = None |
150 | 151 |
151 def LazyUpdateIfNeeded(self): | 152 def LazyUpdateIfNeeded(self): |
152 """Updates the settings from a codereview.settings file, if available.""" | 153 """Updates the settings from a codereview.settings file, if available.""" |
153 if not self.updated: | 154 if not self.updated: |
154 cr_settings_file = FindCodereviewSettingsFile() | 155 cr_settings_file = FindCodereviewSettingsFile() |
155 if cr_settings_file: | 156 if cr_settings_file: |
156 LoadCodereviewSettingsFromFile(cr_settings_file) | 157 LoadCodereviewSettingsFromFile(cr_settings_file) |
157 self.updated = True | 158 self.updated = True |
158 | 159 |
159 def GetDefaultServerUrl(self, error_ok=False): | 160 def GetDefaultServerUrl(self, error_ok=False): |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 | 258 |
258 def GetViewVCUrl(self): | 259 def GetViewVCUrl(self): |
259 if not self.viewvc_url: | 260 if not self.viewvc_url: |
260 self.viewvc_url = gclient_utils.UpgradeToHttps( | 261 self.viewvc_url = gclient_utils.UpgradeToHttps( |
261 self._GetConfig('rietveld.viewvc-url', error_ok=True)) | 262 self._GetConfig('rietveld.viewvc-url', error_ok=True)) |
262 return self.viewvc_url | 263 return self.viewvc_url |
263 | 264 |
264 def GetDefaultCCList(self): | 265 def GetDefaultCCList(self): |
265 return self._GetConfig('rietveld.cc', error_ok=True) | 266 return self._GetConfig('rietveld.cc', error_ok=True) |
266 | 267 |
| 268 def GetIsGerrit(self): |
| 269 """Return true if this repo is assosiated with gerrit code review system.""" |
| 270 if self.is_gerrit is None: |
| 271 self.is_gerrit = self._GetConfig('gerrit.host', error_ok=True) |
| 272 return self.is_gerrit |
| 273 |
267 def _GetConfig(self, param, **kwargs): | 274 def _GetConfig(self, param, **kwargs): |
268 self.LazyUpdateIfNeeded() | 275 self.LazyUpdateIfNeeded() |
269 return RunGit(['config', param], **kwargs).strip() | 276 return RunGit(['config', param], **kwargs).strip() |
270 | 277 |
271 | 278 |
272 def CheckForMigration(): | 279 def CheckForMigration(): |
273 """Migrate from the old issue format, if found. | 280 """Migrate from the old issue format, if found. |
274 | 281 |
275 We used to store the branch<->issue mapping in a file in .git, but it's | 282 We used to store the branch<->issue mapping in a file in .git, but it's |
276 better to store it in the .git/config, since deleting a branch deletes that | 283 better to store it in the .git/config, since deleting a branch deletes that |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 """Return the git setting that stores this change's most recent patchset.""" | 604 """Return the git setting that stores this change's most recent patchset.""" |
598 return 'branch.%s.rietveldpatchset' % self.GetBranch() | 605 return 'branch.%s.rietveldpatchset' % self.GetBranch() |
599 | 606 |
600 def _RietveldServer(self): | 607 def _RietveldServer(self): |
601 """Returns the git setting that stores this change's rietveld server.""" | 608 """Returns the git setting that stores this change's rietveld server.""" |
602 return 'branch.%s.rietveldserver' % self.GetBranch() | 609 return 'branch.%s.rietveldserver' % self.GetBranch() |
603 | 610 |
604 | 611 |
605 def GetCodereviewSettingsInteractively(): | 612 def GetCodereviewSettingsInteractively(): |
606 """Prompt the user for settings.""" | 613 """Prompt the user for settings.""" |
| 614 # TODO(ukai): ask code review system is rietveld or gerrit? |
607 server = settings.GetDefaultServerUrl(error_ok=True) | 615 server = settings.GetDefaultServerUrl(error_ok=True) |
608 prompt = 'Rietveld server (host[:port])' | 616 prompt = 'Rietveld server (host[:port])' |
609 prompt += ' [%s]' % (server or DEFAULT_SERVER) | 617 prompt += ' [%s]' % (server or DEFAULT_SERVER) |
610 newserver = ask_for_data(prompt + ':') | 618 newserver = ask_for_data(prompt + ':') |
611 if not server and not newserver: | 619 if not server and not newserver: |
612 newserver = DEFAULT_SERVER | 620 newserver = DEFAULT_SERVER |
613 if newserver: | 621 if newserver: |
614 newserver = gclient_utils.UpgradeToHttps(newserver) | 622 newserver = gclient_utils.UpgradeToHttps(newserver) |
615 if newserver != server: | 623 if newserver != server: |
616 RunGit(['config', 'rietveld.server', newserver]) | 624 RunGit(['config', 'rietveld.server', newserver]) |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 initial_text += '\nBUG=' | 667 initial_text += '\nBUG=' |
660 if '\nTEST=' not in self.description: | 668 if '\nTEST=' not in self.description: |
661 initial_text += '\nTEST=' | 669 initial_text += '\nTEST=' |
662 initial_text = initial_text.rstrip('\n') + '\n' | 670 initial_text = initial_text.rstrip('\n') + '\n' |
663 content = gclient_utils.RunEditor(initial_text, True) | 671 content = gclient_utils.RunEditor(initial_text, True) |
664 if not content: | 672 if not content: |
665 DieWithError('Running editor failed') | 673 DieWithError('Running editor failed') |
666 content = re.compile(r'^#.*$', re.MULTILINE).sub('', content).strip() | 674 content = re.compile(r'^#.*$', re.MULTILINE).sub('', content).strip() |
667 if not content: | 675 if not content: |
668 DieWithError('No CL description, aborting') | 676 DieWithError('No CL description, aborting') |
669 self._ParseDescription(content) | 677 self.ParseDescription(content) |
670 | 678 |
671 def _ParseDescription(self, description): | 679 def ParseDescription(self, description): |
672 """Updates the list of reviewers and subject from the description.""" | 680 """Updates the list of reviewers and subject from the description.""" |
673 if not description: | 681 if not description: |
674 self.description = description | 682 self.description = description |
675 return | 683 return |
676 | 684 |
677 self.description = description.strip('\n') + '\n' | 685 self.description = description.strip('\n') + '\n' |
678 self.subject = description.split('\n', 1)[0] | 686 self.subject = description.split('\n', 1)[0] |
679 # Retrieves all reviewer lines | 687 # Retrieves all reviewer lines |
680 regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE) | 688 regexp = re.compile(r'^\s*(TBR|R)=(.+)$', re.MULTILINE) |
681 self.reviewers = ','.join( | 689 self.reviewers = ','.join( |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 else: | 724 else: |
717 RunGit(['config', '--unset-all', fullname], error_ok=unset_error_ok) | 725 RunGit(['config', '--unset-all', fullname], error_ok=unset_error_ok) |
718 | 726 |
719 SetProperty('server', 'CODE_REVIEW_SERVER') | 727 SetProperty('server', 'CODE_REVIEW_SERVER') |
720 # Only server setting is required. Other settings can be absent. | 728 # Only server setting is required. Other settings can be absent. |
721 # In that case, we ignore errors raised during option deletion attempt. | 729 # In that case, we ignore errors raised during option deletion attempt. |
722 SetProperty('cc', 'CC_LIST', unset_error_ok=True) | 730 SetProperty('cc', 'CC_LIST', unset_error_ok=True) |
723 SetProperty('tree-status-url', 'STATUS', unset_error_ok=True) | 731 SetProperty('tree-status-url', 'STATUS', unset_error_ok=True) |
724 SetProperty('viewvc-url', 'VIEW_VC', unset_error_ok=True) | 732 SetProperty('viewvc-url', 'VIEW_VC', unset_error_ok=True) |
725 | 733 |
| 734 if 'GERRIT_HOST' in keyvals and 'GERRIT_PORT' in keyvals: |
| 735 RunGit(['config', 'gerrit.host', keyvals['GERRIT_HOST']]) |
| 736 RunGit(['config', 'gerrit.port', keyvals['GERRIT_PORT']]) |
| 737 # Install the standard commit-msg hook. |
| 738 RunCommand(['scp', '-p', '-P', keyvals['GERRIT_PORT'], |
| 739 '%s:hooks/commit-msg' % keyvals['GERRIT_HOST'], |
| 740 os.path.join(settings.GetRoot(), |
| 741 '.git', 'hooks', 'commit-msg')]) |
| 742 |
726 if 'PUSH_URL_CONFIG' in keyvals and 'ORIGIN_URL_CONFIG' in keyvals: | 743 if 'PUSH_URL_CONFIG' in keyvals and 'ORIGIN_URL_CONFIG' in keyvals: |
727 #should be of the form | 744 #should be of the form |
728 #PUSH_URL_CONFIG: url.ssh://gitrw.chromium.org.pushinsteadof | 745 #PUSH_URL_CONFIG: url.ssh://gitrw.chromium.org.pushinsteadof |
729 #ORIGIN_URL_CONFIG: http://src.chromium.org/git | 746 #ORIGIN_URL_CONFIG: http://src.chromium.org/git |
730 RunGit(['config', keyvals['PUSH_URL_CONFIG'], | 747 RunGit(['config', keyvals['PUSH_URL_CONFIG'], |
731 keyvals['ORIGIN_URL_CONFIG']]) | 748 keyvals['ORIGIN_URL_CONFIG']]) |
732 | 749 |
733 | 750 |
734 @usage('[repo root containing codereview.settings]') | 751 @usage('[repo root containing codereview.settings]') |
735 def CMDconfig(parser, args): | 752 def CMDconfig(parser, args): |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 else: | 873 else: |
857 # Default to diffing against the "upstream" branch. | 874 # Default to diffing against the "upstream" branch. |
858 base_branch = cl.GetUpstreamBranch() | 875 base_branch = cl.GetUpstreamBranch() |
859 | 876 |
860 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, | 877 cl.RunHook(committing=not options.upload, upstream_branch=base_branch, |
861 may_prompt=False, verbose=options.verbose, | 878 may_prompt=False, verbose=options.verbose, |
862 author=None) | 879 author=None) |
863 return 0 | 880 return 0 |
864 | 881 |
865 | 882 |
866 @usage('[args to "git diff"]') | 883 def GerritUpload(options, args, cl): |
867 def CMDupload(parser, args): | 884 """upload the current branch to gerrit.""" |
868 """upload the current changelist to codereview""" | 885 # We assume the remote called "origin" is the one we want. |
869 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 886 # It is probably not worthwhile to support different workflows. |
870 help='bypass upload presubmit hook') | 887 remote = 'origin' |
871 parser.add_option('-f', action='store_true', dest='force', | 888 branch = 'master' |
872 help="force yes to questions (don't prompt)") | 889 if options.target_branch: |
873 parser.add_option('-m', dest='message', help='message for patch') | 890 branch = options.target_branch |
874 parser.add_option('-r', '--reviewers', | |
875 help='reviewer email addresses') | |
876 parser.add_option('--cc', | |
877 help='cc email addresses') | |
878 parser.add_option('--send-mail', action='store_true', | |
879 help='send email to reviewer immediately') | |
880 parser.add_option("--emulate_svn_auto_props", action="store_true", | |
881 dest="emulate_svn_auto_props", | |
882 help="Emulate Subversion's auto properties feature.") | |
883 parser.add_option("--desc_from_logs", action="store_true", | |
884 dest="from_logs", | |
885 help="""Squashes git commit logs into change description and | |
886 uses message as subject""") | |
887 parser.add_option('-c', '--use-commit-queue', action='store_true', | |
888 help='tell the commit queue to commit this patchset') | |
889 (options, args) = parser.parse_args(args) | |
890 | 891 |
891 # Make sure index is up-to-date before running diff-index. | 892 log_desc = CreateDescriptionFromLog(args) |
892 RunGit(['update-index', '--refresh', '-q'], error_ok=True) | 893 if options.reviewers: |
893 if RunGit(['diff-index', 'HEAD']): | 894 log_desc += '\nR=' + options.reviewers |
894 print 'Cannot upload with a dirty tree. You must commit locally first.' | 895 change_desc = ChangeDescription(options.message, log_desc, |
| 896 options.reviewers) |
| 897 change_desc.ParseDescription(log_desc) |
| 898 if change_desc.IsEmpty(): |
| 899 print "Description is empty; aborting." |
895 return 1 | 900 return 1 |
896 | 901 |
897 cl = Changelist() | 902 receive_options = [] |
898 if args: | 903 cc = cl.GetCCList().split(',') |
899 base_branch = args[0] | 904 if options.cc: |
900 else: | 905 cc += options.cc.split(',') |
901 # Default to diffing against the "upstream" branch. | 906 cc = filter(None, cc) |
902 base_branch = cl.GetUpstreamBranch() | 907 if cc: |
903 args = [base_branch + "..."] | 908 receive_options += ['--cc=' + email for email in cc] |
| 909 if change_desc.reviewers: |
| 910 reviewers = filter(None, change_desc.reviewers.split(',')) |
| 911 if reviewers: |
| 912 receive_options += ['--reviewer=' + email for email in reviewers] |
904 | 913 |
905 if not options.bypass_hooks: | 914 git_command = ['push'] |
906 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, | 915 if receive_options: |
907 may_prompt=not options.force, | 916 git_command.append('--receive-pack="git receive-pack %s"' % |
908 verbose=options.verbose, | 917 ' '.join(receive_options)) |
909 author=None) | 918 git_command += [remote, 'HEAD:refs/for/' + branch] |
910 if not hook_results.should_continue(): | 919 RunGit(git_command) |
911 return 1 | 920 # TODO(ukai): parse Change-Id: and set issue number? |
912 if not options.reviewers and hook_results.reviewers: | 921 return 0 |
913 options.reviewers = hook_results.reviewers | |
914 | 922 |
915 # --no-ext-diff is broken in some versions of Git, so try to work around | |
916 # this by overriding the environment (but there is still a problem if the | |
917 # git config key "diff.external" is used). | |
918 env = os.environ.copy() | |
919 if 'GIT_EXTERNAL_DIFF' in env: | |
920 del env['GIT_EXTERNAL_DIFF'] | |
921 subprocess2.call( | |
922 ['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, env=env) | |
923 | 923 |
| 924 def RietveldUpload(options, args, cl): |
| 925 """upload the patch to rietveld.""" |
924 upload_args = ['--assume_yes'] # Don't ask about untracked files. | 926 upload_args = ['--assume_yes'] # Don't ask about untracked files. |
925 upload_args.extend(['--server', cl.GetRietveldServer()]) | 927 upload_args.extend(['--server', cl.GetRietveldServer()]) |
926 if options.emulate_svn_auto_props: | 928 if options.emulate_svn_auto_props: |
927 upload_args.append('--emulate_svn_auto_props') | 929 upload_args.append('--emulate_svn_auto_props') |
928 if options.from_logs and not options.message: | 930 if options.from_logs and not options.message: |
929 print 'Must set message for subject line if using desc_from_logs' | 931 print 'Must set message for subject line if using desc_from_logs' |
930 return 1 | 932 return 1 |
931 | 933 |
932 change_desc = None | 934 change_desc = None |
933 | 935 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 | 997 |
996 if not cl.GetIssue(): | 998 if not cl.GetIssue(): |
997 cl.SetIssue(issue) | 999 cl.SetIssue(issue) |
998 cl.SetPatchset(patchset) | 1000 cl.SetPatchset(patchset) |
999 | 1001 |
1000 if options.use_commit_queue: | 1002 if options.use_commit_queue: |
1001 cl.SetFlag('commit', '1') | 1003 cl.SetFlag('commit', '1') |
1002 return 0 | 1004 return 0 |
1003 | 1005 |
1004 | 1006 |
| 1007 @usage('[args to "git diff"]') |
| 1008 def CMDupload(parser, args): |
| 1009 """upload the current changelist to codereview""" |
| 1010 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
| 1011 help='bypass upload presubmit hook') |
| 1012 parser.add_option('-f', action='store_true', dest='force', |
| 1013 help="force yes to questions (don't prompt)") |
| 1014 parser.add_option('-m', dest='message', help='message for patch') |
| 1015 parser.add_option('-r', '--reviewers', |
| 1016 help='reviewer email addresses') |
| 1017 parser.add_option('--cc', |
| 1018 help='cc email addresses') |
| 1019 parser.add_option('--send-mail', action='store_true', |
| 1020 help='send email to reviewer immediately') |
| 1021 parser.add_option("--emulate_svn_auto_props", action="store_true", |
| 1022 dest="emulate_svn_auto_props", |
| 1023 help="Emulate Subversion's auto properties feature.") |
| 1024 parser.add_option("--desc_from_logs", action="store_true", |
| 1025 dest="from_logs", |
| 1026 help="""Squashes git commit logs into change description and |
| 1027 uses message as subject""") |
| 1028 parser.add_option('-c', '--use-commit-queue', action='store_true', |
| 1029 help='tell the commit queue to commit this patchset') |
| 1030 if settings.GetIsGerrit(): |
| 1031 parser.add_option('--target_branch', dest='target_branch', default='master', |
| 1032 help='target branch to upload') |
| 1033 (options, args) = parser.parse_args(args) |
| 1034 |
| 1035 # Make sure index is up-to-date before running diff-index. |
| 1036 RunGit(['update-index', '--refresh', '-q'], error_ok=True) |
| 1037 if RunGit(['diff-index', 'HEAD']): |
| 1038 print 'Cannot upload with a dirty tree. You must commit locally first.' |
| 1039 return 1 |
| 1040 |
| 1041 cl = Changelist() |
| 1042 if args: |
| 1043 # TODO(ukai): is it ok for gerrit case? |
| 1044 base_branch = args[0] |
| 1045 else: |
| 1046 # Default to diffing against the "upstream" branch. |
| 1047 base_branch = cl.GetUpstreamBranch() |
| 1048 args = [base_branch + "..."] |
| 1049 |
| 1050 if not options.bypass_hooks: |
| 1051 hook_results = cl.RunHook(committing=False, upstream_branch=base_branch, |
| 1052 may_prompt=not options.force, |
| 1053 verbose=options.verbose, |
| 1054 author=None) |
| 1055 if not hook_results.should_continue(): |
| 1056 return 1 |
| 1057 if not options.reviewers and hook_results.reviewers: |
| 1058 options.reviewers = hook_results.reviewers |
| 1059 |
| 1060 # --no-ext-diff is broken in some versions of Git, so try to work around |
| 1061 # this by overriding the environment (but there is still a problem if the |
| 1062 # git config key "diff.external" is used). |
| 1063 env = os.environ.copy() |
| 1064 if 'GIT_EXTERNAL_DIFF' in env: |
| 1065 del env['GIT_EXTERNAL_DIFF'] |
| 1066 subprocess2.call( |
| 1067 ['git', 'diff', '--no-ext-diff', '--stat', '-M'] + args, env=env) |
| 1068 |
| 1069 if settings.GetIsGerrit(): |
| 1070 return GerritUpload(options, args, cl) |
| 1071 return RietveldUpload(options, args, cl) |
| 1072 |
| 1073 |
1005 def SendUpstream(parser, args, cmd): | 1074 def SendUpstream(parser, args, cmd): |
1006 """Common code for CmdPush and CmdDCommit | 1075 """Common code for CmdPush and CmdDCommit |
1007 | 1076 |
1008 Squashed commit into a single. | 1077 Squashed commit into a single. |
1009 Updates changelog with metadata (e.g. pointer to review). | 1078 Updates changelog with metadata (e.g. pointer to review). |
1010 Pushes/dcommits the code upstream. | 1079 Pushes/dcommits the code upstream. |
1011 Updates review and closes. | 1080 Updates review and closes. |
1012 """ | 1081 """ |
1013 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', | 1082 parser.add_option('--bypass-hooks', action='store_true', dest='bypass_hooks', |
1014 help='bypass upload presubmit hook') | 1083 help='bypass upload presubmit hook') |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1222 help='allow failed patches and spew .rej files') | 1291 help='allow failed patches and spew .rej files') |
1223 parser.add_option('-n', '--no-commit', action='store_true', dest='nocommit', | 1292 parser.add_option('-n', '--no-commit', action='store_true', dest='nocommit', |
1224 help="don't commit after patch applies") | 1293 help="don't commit after patch applies") |
1225 (options, args) = parser.parse_args(args) | 1294 (options, args) = parser.parse_args(args) |
1226 if len(args) != 1: | 1295 if len(args) != 1: |
1227 parser.print_help() | 1296 parser.print_help() |
1228 return 1 | 1297 return 1 |
1229 issue_arg = args[0] | 1298 issue_arg = args[0] |
1230 | 1299 |
1231 # TODO(maruel): Use apply_issue.py | 1300 # TODO(maruel): Use apply_issue.py |
| 1301 # TODO(ukai): use gerrit-cherry-pick for gerrit repository? |
1232 | 1302 |
1233 if re.match(r'\d+', issue_arg): | 1303 if re.match(r'\d+', issue_arg): |
1234 # Input is an issue id. Figure out the URL. | 1304 # Input is an issue id. Figure out the URL. |
1235 issue = issue_arg | 1305 issue = issue_arg |
1236 patch_data = Changelist().GetPatchSetDiff(issue) | 1306 patch_data = Changelist().GetPatchSetDiff(issue) |
1237 else: | 1307 else: |
1238 # Assume it's a URL to the patch. Default to https. | 1308 # Assume it's a URL to the patch. Default to https. |
1239 issue_url = gclient_utils.UpgradeToHttps(issue_arg) | 1309 issue_url = gclient_utils.UpgradeToHttps(issue_arg) |
1240 match = re.match(r'.*?/issue(\d+)_\d+.diff', issue_url) | 1310 match = re.match(r'.*?/issue(\d+)_\d+.diff', issue_url) |
1241 if not match: | 1311 if not match: |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1428 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) | 1498 'and retry or visit go/isgaeup.\n%s') % (e.code, str(e))) |
1429 | 1499 |
1430 # Not a known command. Default to help. | 1500 # Not a known command. Default to help. |
1431 GenUsage(parser, 'help') | 1501 GenUsage(parser, 'help') |
1432 return CMDhelp(parser, argv) | 1502 return CMDhelp(parser, argv) |
1433 | 1503 |
1434 | 1504 |
1435 if __name__ == '__main__': | 1505 if __name__ == '__main__': |
1436 fix_encoding.fix_encoding() | 1506 fix_encoding.fix_encoding() |
1437 sys.exit(main(sys.argv[1:])) | 1507 sys.exit(main(sys.argv[1:])) |
OLD | NEW |