Index: gclient.py |
diff --git a/gclient.py b/gclient.py |
index 48a940fa31ac020c3102517398c8a3aee49a8912..8cf21d86b014b36ec2a4498265eca82d154d6de1 100644 |
--- a/gclient.py |
+++ b/gclient.py |
@@ -55,8 +55,7 @@ Hooks |
] |
""" |
-__author__ = "darinf@gmail.com (Darin Fisher)" |
-__version__ = "0.3.4" |
+__version__ = "0.3.5" |
import errno |
import logging |
@@ -103,159 +102,6 @@ For additional help on a subcommand or examples of usage, try |
%prog help files |
""") |
-GENERIC_UPDATE_USAGE_TEXT = ( |
- """Perform a checkout/update of the modules specified by the gclient |
-configuration; see 'help config'. Unless --revision is specified, |
-then the latest revision of the root solutions is checked out, with |
-dependent submodule versions updated according to DEPS files. |
-If --revision is specified, then the given revision is used in place |
-of the latest, either for a single solution or for all solutions. |
-Unless the --force option is provided, solutions and modules whose |
-local revision matches the one to update (i.e., they have not changed |
-in the repository) are *not* modified. Unless --nohooks is provided, |
-the hooks are run. |
-This a synonym for 'gclient %(alias)s' |
- |
-usage: gclient %(cmd)s [options] [--] [SCM update options/args] |
- |
-Valid options: |
- --force : force update even for unchanged modules |
- --nohooks : don't run the hooks after the update is complete |
- --revision SOLUTION@REV : update given solution to specified revision |
- --deps PLATFORM(S) : sync deps for the given platform(s), or 'all' |
- --verbose : output additional diagnostics |
- --head : update to latest revision, instead of last good revision |
- --reset : resets any local changes before updating (git only) |
- |
-Examples: |
- gclient %(cmd)s |
- update files from SCM according to current configuration, |
- *for modules which have changed since last update or sync* |
- gclient %(cmd)s --force |
- update files from SCM according to current configuration, for |
- all modules (useful for recovering files deleted from local copy) |
- gclient %(cmd)s --revision src@31000 |
- update src directory to r31000 |
-""") |
- |
-COMMAND_USAGE_TEXT = { |
- "cleanup": |
- """Clean up all working copies, using 'svn cleanup' for each module. |
-Additional options and args may be passed to 'svn cleanup'. |
- |
-usage: cleanup [options] [--] [svn cleanup args/options] |
- |
-Valid options: |
- --verbose : output additional diagnostics |
-""", |
- "config": """Create a .gclient file in the current directory; this |
-specifies the configuration for further commands. After update/sync, |
-top-level DEPS files in each module are read to determine dependent |
-modules to operate on as well. If optional [url] parameter is |
-provided, then configuration is read from a specified Subversion server |
-URL. Otherwise, a --spec option must be provided. A --name option overrides |
-the default name for the solutions. |
- |
-usage: config [option | url] [safesync url] |
- |
-Valid options: |
- --name path : alternate relative path for the solution |
- --spec=GCLIENT_SPEC : contents of .gclient are read from string parameter. |
- *Note that due to Cygwin/Python brokenness, it |
- probably can't contain any newlines.* |
- |
-Examples: |
- gclient config https://gclient.googlecode.com/svn/trunk/gclient |
- configure a new client to check out gclient.py tool sources |
- gclient config --name tools https://gclient.googlecode.com/svn/trunk/gclient |
- gclient config --spec='solutions=[{"name":"gclient",""" |
- '"url":"https://gclient.googlecode.com/svn/trunk/gclient",' |
- '"custom_deps":{}}]', |
- "diff": """Display the differences between two revisions of modules. |
-(Does 'svn diff' for each checked out module and dependences.) |
-Additional args and options to 'svn diff' can be passed after |
-gclient options. |
- |
-usage: diff [options] [--] [svn args/options] |
- |
-Valid options: |
- --verbose : output additional diagnostics |
- |
-Examples: |
- gclient diff |
- simple 'svn diff' for configured client and dependences |
- gclient diff -- -x -b |
- use 'svn diff -x -b' to suppress whitespace-only differences |
- gclient diff -- -r HEAD -x -b |
- diff versus the latest version of each module |
-""", |
- "export": |
- """Wrapper for svn export for all managed directories |
-""", |
- "pack": |
- |
- """Generate a patch which can be applied at the root of the tree. |
-Internally, runs 'svn diff' on each checked out module and |
-dependencies, and performs minimal postprocessing of the output. The |
-resulting patch is printed to stdout and can be applied to a freshly |
-checked out tree via 'patch -p0 < patchfile'. Additional args and |
-options to 'svn diff' can be passed after gclient options. |
- |
-usage: pack [options] [--] [svn args/options] |
- |
-Valid options: |
- --verbose : output additional diagnostics |
- |
-Examples: |
- gclient pack > patch.txt |
- generate simple patch for configured client and dependences |
- gclient pack -- -x -b > patch.txt |
- generate patch using 'svn diff -x -b' to suppress |
- whitespace-only differences |
- gclient pack -- -r HEAD -x -b > patch.txt |
- generate patch, diffing each file versus the latest version of |
- each module |
-""", |
- "revert": |
- """Revert every file in every managed directory in the client view. |
- |
-usage: revert |
-""", |
- "status": |
- """Show the status of client and dependent modules, using 'svn diff' |
-for each module. Additional options and args may be passed to 'svn diff'. |
- |
-usage: status [options] [--] [svn diff args/options] |
- |
-Valid options: |
- --verbose : output additional diagnostics |
- --nohooks : don't run the hooks after the update is complete |
-""", |
- "sync": GENERIC_UPDATE_USAGE_TEXT % {"cmd": "sync", "alias": "update"}, |
- "update": GENERIC_UPDATE_USAGE_TEXT % {"cmd": "update", "alias": "sync"}, |
- "help": """Describe the usage of this program or its subcommands. |
- |
-usage: help [options] [subcommand] |
- |
-Valid options: |
- --verbose : output additional diagnostics |
-""", |
- "runhooks": |
- """Runs hooks for files that have been modified in the local working copy, |
-according to 'svn status'. Implies --force. |
- |
-usage: runhooks [options] |
- |
-Valid options: |
- --verbose : output additional diagnostics |
-""", |
- "revinfo": |
- """Outputs source path, server URL and revision information for every |
-dependency in all solutions. |
- |
-usage: revinfo [options] |
-""", |
-} |
DEFAULT_CLIENT_FILE_TEXT = ("""\ |
# An element of this array (a "solution") describes a repository directory |
@@ -792,7 +638,7 @@ class GClient(object): |
scm = gclient_scm.CreateSCM(file.GetPath(), self._root_dir, d) |
scm.RunCommand("updatesingle", self._options, |
args + [file.GetFilename()], file_list) |
- |
+ |
if command == 'update' and not self._options.verbose: |
pm.end() |
@@ -995,12 +841,15 @@ class GClient(object): |
## gclient commands. |
-def DoCleanup(options, args): |
- """Handle the cleanup subcommand. |
+def CMDcleanup(options, args): |
+ """Clean up all working copies, using 'svn cleanup' for each module. |
+Additional options and args may be passed to 'svn cleanup'. |
+ |
+usage: cleanup [options] [--] [svn cleanup args/options] |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+Valid options: |
+ --verbose : output additional diagnostics |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
@@ -1011,17 +860,31 @@ def DoCleanup(options, args): |
return client.RunOnDeps('cleanup', args) |
-def DoConfig(options, args): |
- """Handle the config subcommand. |
+def CMDconfig(options, args): |
+ """Create a .gclient file in the current directory; this |
+specifies the configuration for further commands. After update/sync, |
+top-level DEPS files in each module are read to determine dependent |
+modules to operate on as well. If optional [url] parameter is |
+provided, then configuration is read from a specified Subversion server |
+URL. Otherwise, a --spec option must be provided. A --name option overrides |
+the default name for the solutions. |
- Args: |
- options: If options.spec set, a string providing contents of config file. |
- args: The command line args. If spec is not set, |
- then args[0] is a string URL to get for config file. |
+usage: config [option | url] [safesync url] |
- Raises: |
- Error: on usage error |
- """ |
+Valid options: |
+ --name path : alternate relative path for the solution |
+ --spec=GCLIENT_SPEC : contents of .gclient are read from string parameter. |
+ *Note that due to Cygwin/Python brokenness, it |
+ probably can't contain any newlines.* |
+ |
+Examples: |
+ gclient config https://gclient.googlecode.com/svn/trunk/gclient |
+ configure a new client to check out gclient.py tool sources |
+ gclient config --name tools https://gclient.googlecode.com/svn/trunk/gclient |
+ gclient config --spec='solutions=[{"name":"gclient", |
+ '"url":"https://gclient.googlecode.com/svn/trunk/gclient",' |
+ '"custom_deps":{}}]' |
+""" |
if len(args) < 1 and not options.spec: |
raise gclient_utils.Error("required argument missing; see 'gclient help " |
"config'") |
@@ -1043,14 +906,12 @@ def DoConfig(options, args): |
safesync_url = args[1] |
client.SetDefaultConfig(name, base_url, safesync_url) |
client.SaveConfig() |
+ return 0 |
-def DoExport(options, args): |
- """Handle the export subcommand. |
- |
- Raises: |
- Error: on usage error |
- """ |
+def CMDexport(options, args): |
+ """Wrapper for svn export for all managed directories |
+""" |
if len(args) != 1: |
raise gclient_utils.Error("Need directory name") |
client = GClient.LoadCurrentConfig(options) |
@@ -1064,26 +925,49 @@ def DoExport(options, args): |
print(client.ConfigContent()) |
return client.RunOnDeps('export', args) |
-def DoHelp(options, args): |
- """Handle the help subcommand giving help for another subcommand. |
- Raises: |
- Error: if the command is unknown. |
- """ |
+def CMDhelp(options, args): |
+ """Describe the usage of this program or its subcommands. |
+ |
+usage: help [options] [subcommand] |
+ |
+Valid options: |
+ --verbose : output additional diagnostics |
+""" |
__pychecker__ = 'unusednames=options' |
- if len(args) == 1 and args[0] in COMMAND_USAGE_TEXT: |
- print(COMMAND_USAGE_TEXT[args[0]]) |
+ module = sys.modules[__name__] |
+ commands = [x[3:] for x in dir(module) if x.startswith('CMD')] |
+ if len(args) == 1 and args[0] in commands: |
+ print getattr(module, 'CMD' + args[0]).__doc__ |
else: |
raise gclient_utils.Error("unknown subcommand '%s'; see 'gclient help'" % |
args[0]) |
+ return 0 |
+ |
+ |
+def CMDpack(options, args): |
+ """Generate a patch which can be applied at the root of the tree. |
+Internally, runs 'svn diff' on each checked out module and |
+dependencies, and performs minimal postprocessing of the output. The |
+resulting patch is printed to stdout and can be applied to a freshly |
+checked out tree via 'patch -p0 < patchfile'. Additional args and |
+options to 'svn diff' can be passed after gclient options. |
+usage: pack [options] [--] [svn args/options] |
-def DoPack(options, args): |
- """Handle the pack subcommand. |
+Valid options: |
+ --verbose : output additional diagnostics |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+Examples: |
+ gclient pack > patch.txt |
+ generate simple patch for configured client and dependences |
+ gclient pack -- -x -b > patch.txt |
+ generate patch using 'svn diff -x -b' to suppress |
+ whitespace-only differences |
+ gclient pack -- -r HEAD -x -b > patch.txt |
+ generate patch, diffing each file versus the latest version of |
+ each module |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
@@ -1094,12 +978,16 @@ def DoPack(options, args): |
return client.RunOnDeps('pack', args) |
-def DoStatus(options, args): |
- """Handle the status subcommand. |
+def CMDstatus(options, args): |
+ """Show the status of client and dependent modules, using 'svn diff' |
+for each module. Additional options and args may be passed to 'svn diff'. |
+ |
+usage: status [options] [--] [svn diff args/options] |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+Valid options: |
+ --verbose : output additional diagnostics |
+ --nohooks : don't run the hooks after the update is complete |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
@@ -1110,12 +998,40 @@ def DoStatus(options, args): |
return client.RunOnDeps('status', args) |
-def DoUpdate(options, args): |
- """Handle the update and sync subcommands. |
+def CMDsync(options, args): |
+ """Perform a checkout/update of the modules specified by the gclient |
+configuration; see 'help config'. Unless --revision is specified, |
+then the latest revision of the root solutions is checked out, with |
+dependent submodule versions updated according to DEPS files. |
+If --revision is specified, then the given revision is used in place |
+of the latest, either for a single solution or for all solutions. |
+Unless the --force option is provided, solutions and modules whose |
+local revision matches the one to update (i.e., they have not changed |
+in the repository) are *not* modified. Unless --nohooks is provided, |
+the hooks are run. |
+ |
+usage: gclient sync [options] [--] [SCM update options/args] |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+Valid options: |
+ --force : force update even for unchanged modules |
+ --nohooks : don't run the hooks after the update is complete |
+ --revision SOLUTION@REV : update given solution to specified revision |
+ --deps PLATFORM(S) : sync deps for the given platform(s), or 'all' |
+ --verbose : output additional diagnostics |
+ --head : update to latest revision, instead of last good |
+ revision |
+ --reset : resets any local changes before updating (git only) |
+ |
+Examples: |
+ gclient sync |
+ update files from SCM according to current configuration, |
+ *for modules which have changed since last update or sync* |
+ gclient sync --force |
+ update files from SCM according to current configuration, for |
+ all modules (useful for recovering files deleted from local copy) |
+ gclient sync --revision src@31000 |
+ update src directory to r31000 |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
@@ -1148,12 +1064,31 @@ def DoUpdate(options, args): |
return client.RunOnDeps('update', args) |
-def DoDiff(options, args): |
- """Handle the diff subcommand. |
+def CMDupdate(options, args): |
+ """Alias for the sync command. Deprecated. |
+""" |
+ return CMDsync(options, args) |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+ |
+def CMDdiff(options, args): |
+ """Display the differences between two revisions of modules. |
+(Does 'svn diff' for each checked out module and dependences.) |
+Additional args and options to 'svn diff' can be passed after |
+gclient options. |
+ |
+usage: diff [options] [--] [svn args/options] |
+ |
+Valid options: |
+ --verbose : output additional diagnostics |
+ |
+Examples: |
+ gclient diff |
+ simple 'svn diff' for configured client and dependences |
+ gclient diff -- -x -b |
+ use 'svn diff -x -b' to suppress whitespace-only differences |
+ gclient diff -- -r HEAD -x -b |
+ diff versus the latest version of each module |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
@@ -1164,24 +1099,24 @@ def DoDiff(options, args): |
return client.RunOnDeps('diff', args) |
-def DoRevert(options, args): |
- """Handle the revert subcommand. |
- |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+def CMDrevert(options, args): |
+ """Revert every file in every managed directory in the client view. |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
return client.RunOnDeps('revert', args) |
-def DoRunHooks(options, args): |
- """Handle the runhooks subcommand. |
+def CMDrunhooks(options, args): |
+ """Runs hooks for files that have been modified in the local working copy, |
+according to 'svn status'. Implies --force. |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+usage: runhooks [options] |
+ |
+Valid options: |
+ --verbose : output additional diagnostics |
+""" |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
@@ -1193,50 +1128,33 @@ def DoRunHooks(options, args): |
return client.RunOnDeps('runhooks', args) |
-def DoRevInfo(options, args): |
- """Handle the revinfo subcommand. |
+def CMDrevinfo(options, args): |
+ """Outputs source path, server URL and revision information for every |
+dependency in all solutions. |
- Raises: |
- Error: if client isn't configured properly. |
- """ |
+usage: revinfo [options] |
+""" |
__pychecker__ = 'unusednames=args' |
client = GClient.LoadCurrentConfig(options) |
if not client: |
raise gclient_utils.Error("client not configured; see 'gclient config'") |
client.PrintRevInfo() |
+ return 0 |
-gclient_command_map = { |
- "cleanup": DoCleanup, |
- "config": DoConfig, |
- "diff": DoDiff, |
- "export": DoExport, |
- "help": DoHelp, |
- "pack": DoPack, |
- "status": DoStatus, |
- "sync": DoUpdate, |
- "update": DoUpdate, |
- "revert": DoRevert, |
- "runhooks": DoRunHooks, |
- "revinfo" : DoRevInfo, |
-} |
- |
- |
-def DispatchCommand(command, options, args, command_map=None): |
- """Dispatches the appropriate subcommand based on command line arguments.""" |
- if command_map is None: |
- command_map = gclient_command_map |
- |
- if command in command_map: |
- return command_map[command](options, args) |
+def DispatchCommand(command, options, args): |
+ """Dispatches the appropriate subcommand based on command line arguments. |
+""" |
+ module = sys.modules[__name__] |
+ command = getattr(module, 'CMD' + command, None) |
+ if command: |
+ return command(options, args) |
else: |
raise gclient_utils.Error("unknown subcommand '%s'; see 'gclient help'" % |
command) |
def Main(argv): |
- """Parse command line arguments and dispatch command.""" |
- |
option_parser = optparse.OptionParser(usage=DEFAULT_USAGE_TEXT, |
version=__version__) |
option_parser.disable_interspersed_args() |