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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « PRESUBMIT.py ('k') | tests/fake_repos.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gclient.py
diff --git a/gclient.py b/gclient.py
index f425d1da33c804a285e6369a3c36bfe3cbebe471..e7672a14b5de59ba8b63e08b00f9cab7a64b1e5a 100644
--- a/gclient.py
+++ b/gclient.py
@@ -55,7 +55,7 @@ Hooks
]
"""
-__version__ = "0.4"
+__version__ = "0.3.7"
import errno
import logging
@@ -73,6 +73,22 @@ import gclient_scm
import gclient_utils
from third_party.repo.progress import Progress
+# default help text
+DEFAULT_USAGE_TEXT = (
+"""%prog <subcommand> [options] [--] [SCM options/args...]
+a wrapper for managing a set of svn client modules and/or git repositories.
+Version """ + __version__ + """
+
+Options and extra arguments can be passed to invoked SCM commands by
+appending them to the command line. Note that if the first such
+appended option starts with a dash (-) then the options must be
+preceded by -- to distinguish them from gclient options.
+
+For additional help on a subcommand or examples of usage, try
+ %prog help <subcommand>
+ %prog help files
+""")
+
def attr(attr, data):
"""Sets an attribute on a function."""
@@ -454,8 +470,6 @@ solutions = [
def _RunHookAction(self, hook_dict, matching_file_list):
"""Runs the action from a single hook.
"""
- logging.info(hook_dict)
- logging.info(matching_file_list)
command = hook_dict['action'][:]
if command[0] == 'python':
# If the hook specified "python" as the first item, the action is a
@@ -799,15 +813,19 @@ solutions = [
print(snapclient._config_content)
-#### gclient commands.
+## gclient commands.
+
+def CMDcleanup(parser, options, args):
+ """Clean up all working copies, using 'svn cleanup' for each module.
-def CMDcleanup(parser, args):
- """Cleans up all working copies.
+Additional options and args may be passed to 'svn cleanup'.
-Mostly svn-specific. Simply runs 'svn cleanup' for each module.
+usage: cleanup [options] [--] [svn cleanup args/options]
+
+Valid options:
+ --verbose : output additional diagnostics
"""
- (options, args) = parser.parse_args(args)
client = GClient.LoadCurrentConfig(options)
if not client:
raise gclient_utils.Error("client not configured; see 'gclient config'")
@@ -818,23 +836,32 @@ Mostly svn-specific. Simply runs 'svn cleanup' for each module.
return client.RunOnDeps('cleanup', args)
-@attr('usage', '[url] [safesync url]')
-def CMDconfig(parser, args):
+def CMDconfig(parser, options, args):
"""Create a .gclient file in the current directory.
-This specifies the configuration for further commands. After update/sync,
+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
+modules to operate on as well. If optional [url] parameter is
provided, then configuration is read from a specified Subversion server
-URL.
+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":{}}]'
"""
- parser.add_option("--spec",
- help="create a gclient file containing the provided "
- "string. Due to Cygwin/Python brokenness, it "
- "probably can't contain any newlines.")
- parser.add_option("--name",
- help="overrides the default name for the solution")
- (options, args) = parser.parse_args(args)
if len(args) < 1 and not options.spec:
raise gclient_utils.Error("required argument missing; see 'gclient help "
"config'")
@@ -859,9 +886,8 @@ URL.
return 0
-def CMDexport(parser, args):
+def CMDexport(parser, options, args):
"""Wrapper for svn export for all managed directories."""
- (options, args) = parser.parse_args(args)
if len(args) != 1:
raise gclient_utils.Error("Need directory name")
client = GClient.LoadCurrentConfig(options)
@@ -876,19 +902,30 @@ def CMDexport(parser, args):
return client.RunOnDeps('export', args)
-@attr('epilog', """Example:
- gclient pack > patch.txt
- generate simple patch for configured client and dependences
-""")
-def CMDpack(parser, args):
+def CMDpack(parser, options, args):
"""Generate a patch which can be applied at the root of the tree.
-Internally, runs 'svn diff'/'git diff' on each checked out module and
+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'.
+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
"""
- (options, args) = parser.parse_args(args)
client = GClient.LoadCurrentConfig(options)
if not client:
raise gclient_utils.Error("client not configured; see 'gclient config'")
@@ -899,9 +936,17 @@ checked out tree via 'patch -p0 < patchfile'.
return client.RunOnDeps('pack', args)
-def CMDstatus(parser, args):
- """Show modification status for every dependencies."""
- (options, args) = parser.parse_args(args)
+def CMDstatus(parser, options, args):
+ """Show the modification status of for every dependencies.
+
+Additional options and args may be passed to 'svn status'.
+
+usage: status [options] [--] [svn diff args/options]
+
+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'")
@@ -912,7 +957,31 @@ def CMDstatus(parser, args):
return client.RunOnDeps('status', args)
-@attr('epilog', """Examples:
+def CMDsync(parser, options, args):
+ """Checkout/update the modules specified by the gclient configuration.
+
+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. See 'help config' for more information.
+
+usage: gclient sync [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 sync
update files from SCM according to current configuration,
*for modules which have changed since last update or sync*
@@ -921,33 +990,7 @@ def CMDstatus(parser, args):
all modules (useful for recovering files deleted from local copy)
gclient sync --revision src@31000
update src directory to r31000
-""")
-def CMDsync(parser, args):
- """Checkout/update all modules."""
- parser.add_option("--force", action="store_true",
- help="force update even for unchanged modules")
- parser.add_option("--nohooks", action="store_true",
- help="don't run hooks after the update is complete")
- parser.add_option("-r", "--revision", action="append",
- dest="revisions", metavar="REV", default=[],
- help="update given solution to specified revision, "
- "can be used multiple times for each solution, "
- "e.g. -r src@123, -r internal@32")
- parser.add_option("--head", action="store_true",
- help="skips any safesync_urls specified in "
- "configured solutions and sync to head instead")
- parser.add_option("--delete_unversioned_trees", action="store_true",
- help="delete any unexpected unversioned trees "
- "that are in the checkout")
- parser.add_option("--reset", action="store_true",
- help="resets any local changes before updating (git only)")
- parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
- help="sync deps for the specified (comma-separated) "
- "platform(s); 'all' will sync all platforms")
- parser.add_option("--manually_grab_svn_rev", action="store_true",
- help="Skip svn up whenever possible by requesting "
- "actual HEAD revision from the repository")
- (options, args) = parser.parse_args(args)
+"""
client = GClient.LoadCurrentConfig(options)
if not client:
@@ -980,13 +1023,31 @@ def CMDsync(parser, args):
return client.RunOnDeps('update', args)
-def CMDupdate(parser, args):
+def CMDupdate(parser, options, args):
"""Alias for the sync command. Deprecated."""
- return CMDsync(parser, args)
+ return CMDsync(parser, options, args)
+
+
+def CMDdiff(parser, options, args):
+ """Display the differences between two revisions of modules.
-def CMDdiff(parser, args):
- """Displays local diff for every dependencies."""
- (options, args) = parser.parse_args(args)
+(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'")
@@ -997,24 +1058,24 @@ def CMDdiff(parser, args):
return client.RunOnDeps('diff', args)
-def CMDrevert(parser, args):
- """Revert all modifications in every dependencies."""
- parser.add_option("--nohooks", action="store_true",
- help="don't run hooks after the revert is complete")
- (options, args) = parser.parse_args(args)
- # --force is implied.
- options.force = True
+def CMDrevert(parser, 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 CMDrunhooks(parser, args):
- """Runs hooks for files that have been modified in the local working copy."""
- parser.add_option("--force", action="store_true", default=True,
- help="Deprecated. No effect.")
- (options, args) = parser.parse_args(args)
+def CMDrunhooks(parser, options, args):
+ """Runs hooks for files that have been modified in the local working copy.
+
+Implies --force.
+
+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'")
@@ -1023,16 +1084,18 @@ def CMDrunhooks(parser, args):
# client dict, but more legible, and it might contain helpful comments.
print(client.ConfigContent())
options.force = True
- options.nohooks = False
return client.RunOnDeps('runhooks', args)
-def CMDrevinfo(parser, args):
- """Outputs details for every dependencies."""
- parser.add_option("--snapshot", action="store_true",
- help="create a snapshot file of the current "
- "version of all repositories")
- (options, args) = parser.parse_args(args)
+def CMDrevinfo(parser, options, args):
+ """Outputs defails for every dependencies.
+
+This includes source path, server URL and revision information for every
+dependency in all solutions.
+
+usage: revinfo [options]
+"""
+ __pychecker__ = 'unusednames=args'
client = GClient.LoadCurrentConfig(options)
if not client:
raise gclient_utils.Error("client not configured; see 'gclient config'")
@@ -1040,45 +1103,70 @@ def CMDrevinfo(parser, args):
return 0
-def Command(name):
- return getattr(sys.modules[__name__], 'CMD' + name, None)
-
-
-def CMDhelp(parser, args):
- """Prints list of commands or help for a specific command."""
- (options, args) = parser.parse_args(args)
+def CMDhelp(parser, options, args):
+ """Prints general help or command-specific documentation."""
if len(args) == 1:
- return Main(args + ['--help'])
+ command = Command(args[0])
+ if command:
+ print getattr(sys.modules[__name__], 'CMD' + args[0]).__doc__
+ return 0
+ parser.usage = (DEFAULT_USAGE_TEXT + '\nCommands are:\n' + '\n'.join([
+ ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip())
+ for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')]))
parser.print_help()
return 0
-def GenUsage(parser, command):
- """Modify an OptParse object with the function's documentation."""
- obj = Command(command)
- if command == 'help':
- command = '<command>'
- # OptParser.description prefer nicely non-formatted strings.
- parser.description = re.sub('[\r\n ]{2,}', ' ', obj.__doc__)
- usage = getattr(obj, 'usage', '')
- parser.set_usage('%%prog %s [options] %s' % (command, usage))
- parser.epilog = getattr(obj, 'epilog', None)
+def Command(command):
+ return getattr(sys.modules[__name__], 'CMD' + command, CMDhelp)
def Main(argv):
- """Doesn't parse the arguments here, just find the right subcommand to
- execute."""
- # Do it late so all commands are listed.
- CMDhelp.usage = ('\n\nCommands are:\n' + '\n'.join([
- ' %-10s %s' % (fn[3:], Command(fn[3:]).__doc__.split('\n')[0].strip())
- for fn in dir(sys.modules[__name__]) if fn.startswith('CMD')]))
- parser = optparse.OptionParser(version='%prog ' + __version__)
+ parser = optparse.OptionParser(usage=DEFAULT_USAGE_TEXT,
+ version='%prog ' + __version__)
parser.add_option("-v", "--verbose", action="count", default=0,
help="Produces additional output for diagnostics. Can be "
"used up to three times for more logging info.")
parser.add_option("--gclientfile", metavar="FILENAME", dest="config_filename",
default=os.environ.get("GCLIENT_FILE", ".gclient"),
help="Specify an alternate .gclient file")
+ # The other options will be moved eventually.
+ parser.add_option("--force", action="store_true",
+ help="(update/sync only) force update even "
+ "for modules which haven't changed")
+ parser.add_option("--nohooks", action="store_true",
+ help="(update/sync/revert only) prevent the hooks "
+ "from running")
+ parser.add_option("--revision", action="append", dest="revisions",
+ metavar="REV", default=[],
+ help="(update/sync only) sync to a specific "
+ "revision, can be used multiple times for "
+ "each solution, e.g. --revision=src@123, "
+ "--revision=internal@32")
+ parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
+ help="(update/sync only) sync deps for the "
+ "specified (comma-separated) platform(s); "
+ "'all' will sync all platforms")
+ parser.add_option("--reset", action="store_true",
+ help="(update/sync only) resets any local changes "
+ "before updating (git only)")
+ parser.add_option("--spec",
+ help="(config only) create a gclient file "
+ "containing the provided string")
+ parser.add_option("--manually_grab_svn_rev", action="store_true",
+ help="Skip svn up whenever possible by requesting "
+ "actual HEAD revision from the repository")
+ parser.add_option("--head", action="store_true",
+ help="skips any safesync_urls specified in "
+ "configured solutions")
+ parser.add_option("--delete_unversioned_trees", action="store_true",
+ help="on update, delete any unexpected "
+ "unversioned trees that are in the checkout")
+ parser.add_option("--snapshot", action="store_true",
+ help="(revinfo only), create a snapshot file "
+ "of the current version of all repositories")
+ parser.add_option("--name",
+ help="specify alternate relative solution path")
# Integrate standard options processing.
old_parser = parser.parse_args
def Parse(args):
@@ -1088,22 +1176,22 @@ def Main(argv):
elif options.verbose > 2:
logging.basicConfig(level=logging.DEBUG)
options.entries_filename = options.config_filename + "_entries"
- if not hasattr(options, 'revisions'):
- # GClient.RunOnDeps expects it even if not applicable.
- options.revisions = []
return (options, args)
parser.parse_args = Parse
# We don't want wordwrapping in epilog (usually examples)
parser.format_epilog = lambda _: parser.epilog or ''
- if argv:
- command = Command(argv[0])
- if command:
- # "fix" the usage and the description now that we know the subcommand.
- GenUsage(parser, argv[0])
- return command(parser, argv[1:])
- # Not a known command. Default to help.
- GenUsage(parser, 'help')
- return CMDhelp(parser, argv)
+
+ if not len(argv):
+ argv = ['help']
+ # Add manual support for --version as first argument.
+ if argv[0] == '--version':
+ parser.print_version()
+ return 0
+ # Add manual support for --help as first argument.
+ if argv[0] == '--help':
+ argv[0] = 'help'
+ options, args = parser.parse_args(argv[1:])
+ return Command(argv[0])(parser, options, args)
if "__main__" == __name__:
« 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