Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(155)

Side by Side Diff: gclient.py

Issue 2285002: Revert "Reapply 48271 with fix." (Closed)
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « PRESUBMIT.py ('k') | tests/fake_repos.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2010 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 """A wrapper script to manage a set of client modules in different SCM. 6 """A wrapper script to manage a set of client modules in different SCM.
7 7
8 This script is intended to be used to help basic management of client 8 This script is intended to be used to help basic management of client
9 program sources residing in one or more Subversion modules and Git 9 program sources residing in one or more Subversion modules and Git
10 repositories, along with other modules it depends on, also in Subversion or Git, 10 repositories, along with other modules it depends on, also in Subversion or Git,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 it will be removed from the list and the list will be extended 48 it will be removed from the list and the list will be extended
49 by the list of matching files. 49 by the list of matching files.
50 50
51 Example: 51 Example:
52 hooks = [ 52 hooks = [
53 { "pattern": "\\.(gif|jpe?g|pr0n|png)$", 53 { "pattern": "\\.(gif|jpe?g|pr0n|png)$",
54 "action": ["python", "image_indexer.py", "--all"]}, 54 "action": ["python", "image_indexer.py", "--all"]},
55 ] 55 ]
56 """ 56 """
57 57
58 __version__ = "0.4" 58 __version__ = "0.3.7"
59 59
60 import errno 60 import errno
61 import logging 61 import logging
62 import optparse 62 import optparse
63 import os 63 import os
64 import pprint 64 import pprint
65 import re 65 import re
66 import sys 66 import sys
67 import urlparse 67 import urlparse
68 import urllib 68 import urllib
69 69
70 import breakpad 70 import breakpad
71 71
72 import gclient_scm 72 import gclient_scm
73 import gclient_utils 73 import gclient_utils
74 from third_party.repo.progress import Progress 74 from third_party.repo.progress import Progress
75 75
76 # default help text
77 DEFAULT_USAGE_TEXT = (
78 """%prog <subcommand> [options] [--] [SCM options/args...]
79 a wrapper for managing a set of svn client modules and/or git repositories.
80 Version """ + __version__ + """
81
82 Options and extra arguments can be passed to invoked SCM commands by
83 appending them to the command line. Note that if the first such
84 appended option starts with a dash (-) then the options must be
85 preceded by -- to distinguish them from gclient options.
86
87 For additional help on a subcommand or examples of usage, try
88 %prog help <subcommand>
89 %prog help files
90 """)
91
76 92
77 def attr(attr, data): 93 def attr(attr, data):
78 """Sets an attribute on a function.""" 94 """Sets an attribute on a function."""
79 def hook(fn): 95 def hook(fn):
80 setattr(fn, attr, data) 96 setattr(fn, attr, data)
81 return fn 97 return fn
82 return hook 98 return hook
83 99
84 100
85 ## GClient implementation. 101 ## GClient implementation.
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 if d in solution_urls and solution_urls[d] != url: 463 if d in solution_urls and solution_urls[d] != url:
448 raise gclient_utils.Error( 464 raise gclient_utils.Error(
449 "Dependency \"%s\" conflicts with specified solution" % d) 465 "Dependency \"%s\" conflicts with specified solution" % d)
450 # Grab the dependency. 466 # Grab the dependency.
451 deps[d] = url 467 deps[d] = url
452 return deps 468 return deps
453 469
454 def _RunHookAction(self, hook_dict, matching_file_list): 470 def _RunHookAction(self, hook_dict, matching_file_list):
455 """Runs the action from a single hook. 471 """Runs the action from a single hook.
456 """ 472 """
457 logging.info(hook_dict)
458 logging.info(matching_file_list)
459 command = hook_dict['action'][:] 473 command = hook_dict['action'][:]
460 if command[0] == 'python': 474 if command[0] == 'python':
461 # If the hook specified "python" as the first item, the action is a 475 # If the hook specified "python" as the first item, the action is a
462 # Python script. Run it by starting a new copy of the same 476 # Python script. Run it by starting a new copy of the same
463 # interpreter. 477 # interpreter.
464 command[0] = sys.executable 478 command[0] = sys.executable
465 479
466 if '$matching_files' in command: 480 if '$matching_files' in command:
467 splice_index = command.index('$matching_files') 481 splice_index = command.index('$matching_files')
468 command[splice_index:splice_index + 1] = matching_file_list 482 command[splice_index:splice_index + 1] = matching_file_list
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 for x in sorted(entries.keys())])) 806 for x in sorted(entries.keys())]))
793 807
794 # Print the snapshot configuration file 808 # Print the snapshot configuration file
795 if self._options.snapshot: 809 if self._options.snapshot:
796 config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient} 810 config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}
797 snapclient = GClient(self._root_dir, self._options) 811 snapclient = GClient(self._root_dir, self._options)
798 snapclient.SetConfig(config) 812 snapclient.SetConfig(config)
799 print(snapclient._config_content) 813 print(snapclient._config_content)
800 814
801 815
802 #### gclient commands. 816 ## gclient commands.
803 817
804 818
805 def CMDcleanup(parser, args): 819 def CMDcleanup(parser, options, args):
806 """Cleans up all working copies. 820 """Clean up all working copies, using 'svn cleanup' for each module.
807 821
808 Mostly svn-specific. Simply runs 'svn cleanup' for each module. 822 Additional options and args may be passed to 'svn cleanup'.
823
824 usage: cleanup [options] [--] [svn cleanup args/options]
825
826 Valid options:
827 --verbose : output additional diagnostics
809 """ 828 """
810 (options, args) = parser.parse_args(args)
811 client = GClient.LoadCurrentConfig(options) 829 client = GClient.LoadCurrentConfig(options)
812 if not client: 830 if not client:
813 raise gclient_utils.Error("client not configured; see 'gclient config'") 831 raise gclient_utils.Error("client not configured; see 'gclient config'")
814 if options.verbose: 832 if options.verbose:
815 # Print out the .gclient file. This is longer than if we just printed the 833 # Print out the .gclient file. This is longer than if we just printed the
816 # client dict, but more legible, and it might contain helpful comments. 834 # client dict, but more legible, and it might contain helpful comments.
817 print(client.ConfigContent()) 835 print(client.ConfigContent())
818 return client.RunOnDeps('cleanup', args) 836 return client.RunOnDeps('cleanup', args)
819 837
820 838
821 @attr('usage', '[url] [safesync url]') 839 def CMDconfig(parser, options, args):
822 def CMDconfig(parser, args):
823 """Create a .gclient file in the current directory. 840 """Create a .gclient file in the current directory.
824 841
825 This specifies the configuration for further commands. After update/sync, 842 This specifies the configuration for further commands. After update/sync,
826 top-level DEPS files in each module are read to determine dependent 843 top-level DEPS files in each module are read to determine dependent
827 modules to operate on as well. If optional [url] parameter is 844 modules to operate on as well. If optional [url] parameter is
828 provided, then configuration is read from a specified Subversion server 845 provided, then configuration is read from a specified Subversion server
829 URL. 846 URL. Otherwise, a --spec option must be provided. A --name option overrides
847 the default name for the solutions.
848
849 usage: config [option | url] [safesync url]
850
851 Valid options:
852 --name path : alternate relative path for the solution
853 --spec=GCLIENT_SPEC : contents of .gclient are read from string parameter.
854 *Note that due to Cygwin/Python brokenness, it
855 probably can't contain any newlines.*
856
857 Examples:
858 gclient config https://gclient.googlecode.com/svn/trunk/gclient
859 configure a new client to check out gclient.py tool sources
860 gclient config --name tools https://gclient.googlecode.com/svn/trunk/gclient
861 gclient config --spec='solutions=[{"name":"gclient",
862 '"url":"https://gclient.googlecode.com/svn/trunk/gclient",'
863 '"custom_deps":{}}]'
830 """ 864 """
831 parser.add_option("--spec",
832 help="create a gclient file containing the provided "
833 "string. Due to Cygwin/Python brokenness, it "
834 "probably can't contain any newlines.")
835 parser.add_option("--name",
836 help="overrides the default name for the solution")
837 (options, args) = parser.parse_args(args)
838 if len(args) < 1 and not options.spec: 865 if len(args) < 1 and not options.spec:
839 raise gclient_utils.Error("required argument missing; see 'gclient help " 866 raise gclient_utils.Error("required argument missing; see 'gclient help "
840 "config'") 867 "config'")
841 if os.path.exists(options.config_filename): 868 if os.path.exists(options.config_filename):
842 raise gclient_utils.Error("%s file already exists in the current directory" 869 raise gclient_utils.Error("%s file already exists in the current directory"
843 % options.config_filename) 870 % options.config_filename)
844 client = GClient('.', options) 871 client = GClient('.', options)
845 if options.spec: 872 if options.spec:
846 client.SetConfig(options.spec) 873 client.SetConfig(options.spec)
847 else: 874 else:
848 base_url = args[0].rstrip('/') 875 base_url = args[0].rstrip('/')
849 if not options.name: 876 if not options.name:
850 name = base_url.split("/")[-1] 877 name = base_url.split("/")[-1]
851 else: 878 else:
852 # specify an alternate relpath for the given URL. 879 # specify an alternate relpath for the given URL.
853 name = options.name 880 name = options.name
854 safesync_url = "" 881 safesync_url = ""
855 if len(args) > 1: 882 if len(args) > 1:
856 safesync_url = args[1] 883 safesync_url = args[1]
857 client.SetDefaultConfig(name, base_url, safesync_url) 884 client.SetDefaultConfig(name, base_url, safesync_url)
858 client.SaveConfig() 885 client.SaveConfig()
859 return 0 886 return 0
860 887
861 888
862 def CMDexport(parser, args): 889 def CMDexport(parser, options, args):
863 """Wrapper for svn export for all managed directories.""" 890 """Wrapper for svn export for all managed directories."""
864 (options, args) = parser.parse_args(args)
865 if len(args) != 1: 891 if len(args) != 1:
866 raise gclient_utils.Error("Need directory name") 892 raise gclient_utils.Error("Need directory name")
867 client = GClient.LoadCurrentConfig(options) 893 client = GClient.LoadCurrentConfig(options)
868 894
869 if not client: 895 if not client:
870 raise gclient_utils.Error("client not configured; see 'gclient config'") 896 raise gclient_utils.Error("client not configured; see 'gclient config'")
871 897
872 if options.verbose: 898 if options.verbose:
873 # Print out the .gclient file. This is longer than if we just printed the 899 # Print out the .gclient file. This is longer than if we just printed the
874 # client dict, but more legible, and it might contain helpful comments. 900 # client dict, but more legible, and it might contain helpful comments.
875 print(client.ConfigContent()) 901 print(client.ConfigContent())
876 return client.RunOnDeps('export', args) 902 return client.RunOnDeps('export', args)
877 903
878 904
879 @attr('epilog', """Example: 905 def CMDpack(parser, options, args):
880 gclient pack > patch.txt
881 generate simple patch for configured client and dependences
882 """)
883 def CMDpack(parser, args):
884 """Generate a patch which can be applied at the root of the tree. 906 """Generate a patch which can be applied at the root of the tree.
885 907
886 Internally, runs 'svn diff'/'git diff' on each checked out module and 908 Internally, runs 'svn diff' on each checked out module and
887 dependencies, and performs minimal postprocessing of the output. The 909 dependencies, and performs minimal postprocessing of the output. The
888 resulting patch is printed to stdout and can be applied to a freshly 910 resulting patch is printed to stdout and can be applied to a freshly
889 checked out tree via 'patch -p0 < patchfile'. 911 checked out tree via 'patch -p0 < patchfile'. Additional args and
912 options to 'svn diff' can be passed after gclient options.
913
914 usage: pack [options] [--] [svn args/options]
915
916 Valid options:
917 --verbose : output additional diagnostics
918
919 Examples:
920 gclient pack > patch.txt
921 generate simple patch for configured client and dependences
922 gclient pack -- -x -b > patch.txt
923 generate patch using 'svn diff -x -b' to suppress
924 whitespace-only differences
925 gclient pack -- -r HEAD -x -b > patch.txt
926 generate patch, diffing each file versus the latest version of
927 each module
890 """ 928 """
891 (options, args) = parser.parse_args(args)
892 client = GClient.LoadCurrentConfig(options) 929 client = GClient.LoadCurrentConfig(options)
893 if not client: 930 if not client:
894 raise gclient_utils.Error("client not configured; see 'gclient config'") 931 raise gclient_utils.Error("client not configured; see 'gclient config'")
895 if options.verbose: 932 if options.verbose:
896 # Print out the .gclient file. This is longer than if we just printed the 933 # Print out the .gclient file. This is longer than if we just printed the
897 # client dict, but more legible, and it might contain helpful comments. 934 # client dict, but more legible, and it might contain helpful comments.
898 print(client.ConfigContent()) 935 print(client.ConfigContent())
899 return client.RunOnDeps('pack', args) 936 return client.RunOnDeps('pack', args)
900 937
901 938
902 def CMDstatus(parser, args): 939 def CMDstatus(parser, options, args):
903 """Show modification status for every dependencies.""" 940 """Show the modification status of for every dependencies.
904 (options, args) = parser.parse_args(args) 941
942 Additional options and args may be passed to 'svn status'.
943
944 usage: status [options] [--] [svn diff args/options]
945
946 Valid options:
947 --verbose : output additional diagnostics
948 --nohooks : don't run the hooks after the update is complete
949 """
905 client = GClient.LoadCurrentConfig(options) 950 client = GClient.LoadCurrentConfig(options)
906 if not client: 951 if not client:
907 raise gclient_utils.Error("client not configured; see 'gclient config'") 952 raise gclient_utils.Error("client not configured; see 'gclient config'")
908 if options.verbose: 953 if options.verbose:
909 # Print out the .gclient file. This is longer than if we just printed the 954 # Print out the .gclient file. This is longer than if we just printed the
910 # client dict, but more legible, and it might contain helpful comments. 955 # client dict, but more legible, and it might contain helpful comments.
911 print(client.ConfigContent()) 956 print(client.ConfigContent())
912 return client.RunOnDeps('status', args) 957 return client.RunOnDeps('status', args)
913 958
914 959
915 @attr('epilog', """Examples: 960 def CMDsync(parser, options, args):
961 """Checkout/update the modules specified by the gclient configuration.
962
963 Unless --revision is specified, then the latest revision of the root solutions
964 is checked out, with dependent submodule versions updated according to DEPS
965 files. If --revision is specified, then the given revision is used in place
966 of the latest, either for a single solution or for all solutions.
967 Unless the --force option is provided, solutions and modules whose
968 local revision matches the one to update (i.e., they have not changed
969 in the repository) are *not* modified. Unless --nohooks is provided,
970 the hooks are run. See 'help config' for more information.
971
972 usage: gclient sync [options] [--] [SCM update options/args]
973
974 Valid options:
975 --force : force update even for unchanged modules
976 --nohooks : don't run the hooks after the update is complete
977 --revision SOLUTION@REV : update given solution to specified revision
978 --deps PLATFORM(S) : sync deps for the given platform(s), or 'all'
979 --verbose : output additional diagnostics
980 --head : update to latest revision, instead of last good
981 revision
982 --reset : resets any local changes before updating (git only)
983
984 Examples:
916 gclient sync 985 gclient sync
917 update files from SCM according to current configuration, 986 update files from SCM according to current configuration,
918 *for modules which have changed since last update or sync* 987 *for modules which have changed since last update or sync*
919 gclient sync --force 988 gclient sync --force
920 update files from SCM according to current configuration, for 989 update files from SCM according to current configuration, for
921 all modules (useful for recovering files deleted from local copy) 990 all modules (useful for recovering files deleted from local copy)
922 gclient sync --revision src@31000 991 gclient sync --revision src@31000
923 update src directory to r31000 992 update src directory to r31000
924 """) 993 """
925 def CMDsync(parser, args):
926 """Checkout/update all modules."""
927 parser.add_option("--force", action="store_true",
928 help="force update even for unchanged modules")
929 parser.add_option("--nohooks", action="store_true",
930 help="don't run hooks after the update is complete")
931 parser.add_option("-r", "--revision", action="append",
932 dest="revisions", metavar="REV", default=[],
933 help="update given solution to specified revision, "
934 "can be used multiple times for each solution, "
935 "e.g. -r src@123, -r internal@32")
936 parser.add_option("--head", action="store_true",
937 help="skips any safesync_urls specified in "
938 "configured solutions and sync to head instead")
939 parser.add_option("--delete_unversioned_trees", action="store_true",
940 help="delete any unexpected unversioned trees "
941 "that are in the checkout")
942 parser.add_option("--reset", action="store_true",
943 help="resets any local changes before updating (git only)")
944 parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
945 help="sync deps for the specified (comma-separated) "
946 "platform(s); 'all' will sync all platforms")
947 parser.add_option("--manually_grab_svn_rev", action="store_true",
948 help="Skip svn up whenever possible by requesting "
949 "actual HEAD revision from the repository")
950 (options, args) = parser.parse_args(args)
951 client = GClient.LoadCurrentConfig(options) 994 client = GClient.LoadCurrentConfig(options)
952 995
953 if not client: 996 if not client:
954 raise gclient_utils.Error("client not configured; see 'gclient config'") 997 raise gclient_utils.Error("client not configured; see 'gclient config'")
955 998
956 if not options.head: 999 if not options.head:
957 solutions = client.GetVar('solutions') 1000 solutions = client.GetVar('solutions')
958 if solutions: 1001 if solutions:
959 for s in solutions: 1002 for s in solutions:
960 if s.get('safesync_url', ''): 1003 if s.get('safesync_url', ''):
(...skipping 12 matching lines...) Expand all
973 if len(rev): 1016 if len(rev):
974 options.revisions.append(s['name']+'@'+rev) 1017 options.revisions.append(s['name']+'@'+rev)
975 1018
976 if options.verbose: 1019 if options.verbose:
977 # Print out the .gclient file. This is longer than if we just printed the 1020 # Print out the .gclient file. This is longer than if we just printed the
978 # client dict, but more legible, and it might contain helpful comments. 1021 # client dict, but more legible, and it might contain helpful comments.
979 print(client.ConfigContent()) 1022 print(client.ConfigContent())
980 return client.RunOnDeps('update', args) 1023 return client.RunOnDeps('update', args)
981 1024
982 1025
983 def CMDupdate(parser, args): 1026 def CMDupdate(parser, options, args):
984 """Alias for the sync command. Deprecated.""" 1027 """Alias for the sync command. Deprecated."""
985 return CMDsync(parser, args) 1028 return CMDsync(parser, options, args)
986 1029
987 def CMDdiff(parser, args): 1030
988 """Displays local diff for every dependencies.""" 1031 def CMDdiff(parser, options, args):
989 (options, args) = parser.parse_args(args) 1032 """Display the differences between two revisions of modules.
1033
1034 (Does 'svn diff' for each checked out module and dependences.)
1035 Additional args and options to 'svn diff' can be passed after
1036 gclient options.
1037
1038 usage: diff [options] [--] [svn args/options]
1039
1040 Valid options:
1041 --verbose : output additional diagnostics
1042
1043 Examples:
1044 gclient diff
1045 simple 'svn diff' for configured client and dependences
1046 gclient diff -- -x -b
1047 use 'svn diff -x -b' to suppress whitespace-only differences
1048 gclient diff -- -r HEAD -x -b
1049 diff versus the latest version of each module
1050 """
990 client = GClient.LoadCurrentConfig(options) 1051 client = GClient.LoadCurrentConfig(options)
991 if not client: 1052 if not client:
992 raise gclient_utils.Error("client not configured; see 'gclient config'") 1053 raise gclient_utils.Error("client not configured; see 'gclient config'")
993 if options.verbose: 1054 if options.verbose:
994 # Print out the .gclient file. This is longer than if we just printed the 1055 # Print out the .gclient file. This is longer than if we just printed the
995 # client dict, but more legible, and it might contain helpful comments. 1056 # client dict, but more legible, and it might contain helpful comments.
996 print(client.ConfigContent()) 1057 print(client.ConfigContent())
997 return client.RunOnDeps('diff', args) 1058 return client.RunOnDeps('diff', args)
998 1059
999 1060
1000 def CMDrevert(parser, args): 1061 def CMDrevert(parser, options, args):
1001 """Revert all modifications in every dependencies.""" 1062 """Revert every file in every managed directory in the client view."""
1002 parser.add_option("--nohooks", action="store_true",
1003 help="don't run hooks after the revert is complete")
1004 (options, args) = parser.parse_args(args)
1005 # --force is implied.
1006 options.force = True
1007 client = GClient.LoadCurrentConfig(options) 1063 client = GClient.LoadCurrentConfig(options)
1008 if not client: 1064 if not client:
1009 raise gclient_utils.Error("client not configured; see 'gclient config'") 1065 raise gclient_utils.Error("client not configured; see 'gclient config'")
1010 return client.RunOnDeps('revert', args) 1066 return client.RunOnDeps('revert', args)
1011 1067
1012 1068
1013 def CMDrunhooks(parser, args): 1069 def CMDrunhooks(parser, options, args):
1014 """Runs hooks for files that have been modified in the local working copy.""" 1070 """Runs hooks for files that have been modified in the local working copy.
1015 parser.add_option("--force", action="store_true", default=True, 1071
1016 help="Deprecated. No effect.") 1072 Implies --force.
1017 (options, args) = parser.parse_args(args) 1073
1074 usage: runhooks [options]
1075
1076 Valid options:
1077 --verbose : output additional diagnostics
1078 """
1018 client = GClient.LoadCurrentConfig(options) 1079 client = GClient.LoadCurrentConfig(options)
1019 if not client: 1080 if not client:
1020 raise gclient_utils.Error("client not configured; see 'gclient config'") 1081 raise gclient_utils.Error("client not configured; see 'gclient config'")
1021 if options.verbose: 1082 if options.verbose:
1022 # Print out the .gclient file. This is longer than if we just printed the 1083 # Print out the .gclient file. This is longer than if we just printed the
1023 # client dict, but more legible, and it might contain helpful comments. 1084 # client dict, but more legible, and it might contain helpful comments.
1024 print(client.ConfigContent()) 1085 print(client.ConfigContent())
1025 options.force = True 1086 options.force = True
1026 options.nohooks = False
1027 return client.RunOnDeps('runhooks', args) 1087 return client.RunOnDeps('runhooks', args)
1028 1088
1029 1089
1030 def CMDrevinfo(parser, args): 1090 def CMDrevinfo(parser, options, args):
1031 """Outputs details for every dependencies.""" 1091 """Outputs defails for every dependencies.
1032 parser.add_option("--snapshot", action="store_true", 1092
1033 help="create a snapshot file of the current " 1093 This includes source path, server URL and revision information for every
1034 "version of all repositories") 1094 dependency in all solutions.
1035 (options, args) = parser.parse_args(args) 1095
1096 usage: revinfo [options]
1097 """
1098 __pychecker__ = 'unusednames=args'
1036 client = GClient.LoadCurrentConfig(options) 1099 client = GClient.LoadCurrentConfig(options)
1037 if not client: 1100 if not client:
1038 raise gclient_utils.Error("client not configured; see 'gclient config'") 1101 raise gclient_utils.Error("client not configured; see 'gclient config'")
1039 client.PrintRevInfo() 1102 client.PrintRevInfo()
1040 return 0 1103 return 0
1041 1104
1042 1105
1043 def Command(name): 1106 def CMDhelp(parser, options, args):
1044 return getattr(sys.modules[__name__], 'CMD' + name, None) 1107 """Prints general help or command-specific documentation."""
1045
1046
1047 def CMDhelp(parser, args):
1048 """Prints list of commands or help for a specific command."""
1049 (options, args) = parser.parse_args(args)
1050 if len(args) == 1: 1108 if len(args) == 1:
1051 return Main(args + ['--help']) 1109 command = Command(args[0])
1110 if command:
1111 print getattr(sys.modules[__name__], 'CMD' + args[0]).__doc__
1112 return 0
1113 parser.usage = (DEFAULT_USAGE_TEXT + '\nCommands are:\n' + '\n'.join([
1114 ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip())
1115 for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')]))
1052 parser.print_help() 1116 parser.print_help()
1053 return 0 1117 return 0
1054 1118
1055 1119
1056 def GenUsage(parser, command): 1120 def Command(command):
1057 """Modify an OptParse object with the function's documentation.""" 1121 return getattr(sys.modules[__name__], 'CMD' + command, CMDhelp)
1058 obj = Command(command)
1059 if command == 'help':
1060 command = '<command>'
1061 # OptParser.description prefer nicely non-formatted strings.
1062 parser.description = re.sub('[\r\n ]{2,}', ' ', obj.__doc__)
1063 usage = getattr(obj, 'usage', '')
1064 parser.set_usage('%%prog %s [options] %s' % (command, usage))
1065 parser.epilog = getattr(obj, 'epilog', None)
1066 1122
1067 1123
1068 def Main(argv): 1124 def Main(argv):
1069 """Doesn't parse the arguments here, just find the right subcommand to 1125 parser = optparse.OptionParser(usage=DEFAULT_USAGE_TEXT,
1070 execute.""" 1126 version='%prog ' + __version__)
1071 # Do it late so all commands are listed.
1072 CMDhelp.usage = ('\n\nCommands are:\n' + '\n'.join([
1073 ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip())
1074 for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')]))
1075 parser = optparse.OptionParser(version='%prog ' + __version__)
1076 parser.add_option("-v", "--verbose", action="count", default=0, 1127 parser.add_option("-v", "--verbose", action="count", default=0,
1077 help="Produces additional output for diagnostics. Can be " 1128 help="Produces additional output for diagnostics. Can be "
1078 "used up to three times for more logging info.") 1129 "used up to three times for more logging info.")
1079 parser.add_option("--gclientfile", metavar="FILENAME", dest="config_filename", 1130 parser.add_option("--gclientfile", metavar="FILENAME", dest="config_filename",
1080 default=os.environ.get("GCLIENT_FILE", ".gclient"), 1131 default=os.environ.get("GCLIENT_FILE", ".gclient"),
1081 help="Specify an alternate .gclient file") 1132 help="Specify an alternate .gclient file")
1133 # The other options will be moved eventually.
1134 parser.add_option("--force", action="store_true",
1135 help="(update/sync only) force update even "
1136 "for modules which haven't changed")
1137 parser.add_option("--nohooks", action="store_true",
1138 help="(update/sync/revert only) prevent the hooks "
1139 "from running")
1140 parser.add_option("--revision", action="append", dest="revisions",
1141 metavar="REV", default=[],
1142 help="(update/sync only) sync to a specific "
1143 "revision, can be used multiple times for "
1144 "each solution, e.g. --revision=src@123, "
1145 "--revision=internal@32")
1146 parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
1147 help="(update/sync only) sync deps for the "
1148 "specified (comma-separated) platform(s); "
1149 "'all' will sync all platforms")
1150 parser.add_option("--reset", action="store_true",
1151 help="(update/sync only) resets any local changes "
1152 "before updating (git only)")
1153 parser.add_option("--spec",
1154 help="(config only) create a gclient file "
1155 "containing the provided string")
1156 parser.add_option("--manually_grab_svn_rev", action="store_true",
1157 help="Skip svn up whenever possible by requesting "
1158 "actual HEAD revision from the repository")
1159 parser.add_option("--head", action="store_true",
1160 help="skips any safesync_urls specified in "
1161 "configured solutions")
1162 parser.add_option("--delete_unversioned_trees", action="store_true",
1163 help="on update, delete any unexpected "
1164 "unversioned trees that are in the checkout")
1165 parser.add_option("--snapshot", action="store_true",
1166 help="(revinfo only), create a snapshot file "
1167 "of the current version of all repositories")
1168 parser.add_option("--name",
1169 help="specify alternate relative solution path")
1082 # Integrate standard options processing. 1170 # Integrate standard options processing.
1083 old_parser = parser.parse_args 1171 old_parser = parser.parse_args
1084 def Parse(args): 1172 def Parse(args):
1085 (options, args) = old_parser(args) 1173 (options, args) = old_parser(args)
1086 if options.verbose == 2: 1174 if options.verbose == 2:
1087 logging.basicConfig(level=logging.INFO) 1175 logging.basicConfig(level=logging.INFO)
1088 elif options.verbose > 2: 1176 elif options.verbose > 2:
1089 logging.basicConfig(level=logging.DEBUG) 1177 logging.basicConfig(level=logging.DEBUG)
1090 options.entries_filename = options.config_filename + "_entries" 1178 options.entries_filename = options.config_filename + "_entries"
1091 if not hasattr(options, 'revisions'):
1092 # GClient.RunOnDeps expects it even if not applicable.
1093 options.revisions = []
1094 return (options, args) 1179 return (options, args)
1095 parser.parse_args = Parse 1180 parser.parse_args = Parse
1096 # We don't want wordwrapping in epilog (usually examples) 1181 # We don't want wordwrapping in epilog (usually examples)
1097 parser.format_epilog = lambda _: parser.epilog or '' 1182 parser.format_epilog = lambda _: parser.epilog or ''
1098 if argv: 1183
1099 command = Command(argv[0]) 1184 if not len(argv):
1100 if command: 1185 argv = ['help']
1101 # "fix" the usage and the description now that we know the subcommand. 1186 # Add manual support for --version as first argument.
1102 GenUsage(parser, argv[0]) 1187 if argv[0] == '--version':
1103 return command(parser, argv[1:]) 1188 parser.print_version()
1104 # Not a known command. Default to help. 1189 return 0
1105 GenUsage(parser, 'help') 1190 # Add manual support for --help as first argument.
1106 return CMDhelp(parser, argv) 1191 if argv[0] == '--help':
1192 argv[0] = 'help'
1193 options, args = parser.parse_args(argv[1:])
1194 return Command(argv[0])(parser, options, args)
1107 1195
1108 1196
1109 if "__main__" == __name__: 1197 if "__main__" == __name__:
1110 try: 1198 try:
1111 sys.exit(Main(sys.argv[1:])) 1199 sys.exit(Main(sys.argv[1:]))
1112 except gclient_utils.Error, e: 1200 except gclient_utils.Error, e:
1113 print >> sys.stderr, "Error: %s" % str(e) 1201 print >> sys.stderr, "Error: %s" % str(e)
1114 sys.exit(1) 1202 sys.exit(1)
1115 1203
1116 # vim: ts=2:sw=2:tw=80:et: 1204 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « PRESUBMIT.py ('k') | tests/fake_repos.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698