| Index: gclient.py
|
| diff --git a/gclient.py b/gclient.py
|
| index 9721c55ff50db194276929c98a02c467dee42916..a50935daa332bab657f5130deb0c6e08a919072d 100644
|
| --- a/gclient.py
|
| +++ b/gclient.py
|
| @@ -3,13 +3,7 @@
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| -"""A wrapper script to manage a set of client modules in different SCM.
|
| -
|
| -This script is intended to be used to help basic management of client
|
| -program sources residing in one or more Subversion modules and Git
|
| -repositories, along with other modules it depends on, also in Subversion or Git,
|
| -but possibly on multiple respositories, making a wrapper system apparently
|
| -necessary.
|
| +"""Meta checkout manager supporting both Subversion and GIT.
|
|
|
| Files
|
| .gclient : Current client configuration, written by 'config' command.
|
| @@ -28,7 +22,7 @@ Hooks
|
| .gclient and DEPS files may optionally contain a list named "hooks" to
|
| allow custom actions to be performed based on files that have changed in the
|
| working copy as a result of a "sync"/"update" or "revert" operation. This
|
| - could be prevented by using --nohooks (hooks run by default). Hooks can also
|
| + can be prevented by using --nohooks (hooks run by default). Hooks can also
|
| be forced to run with the "runhooks" operation. If "sync" is run with
|
| --force, all known hooks will run regardless of the state of the working
|
| copy.
|
| @@ -55,7 +49,7 @@ Hooks
|
| ]
|
| """
|
|
|
| -__version__ = "0.4"
|
| +__version__ = "0.4.1"
|
|
|
| import errno
|
| import logging
|
| @@ -158,8 +152,9 @@ class GClientKeywords(object):
|
| class Dependency(GClientKeywords):
|
| """Object that represents a dependency checkout."""
|
| DEPS_FILE = 'DEPS'
|
| +
|
| def __init__(self, parent, name, url, safesync_url=None, custom_deps=None,
|
| - custom_vars=None, deps_file=None):
|
| + custom_vars=None, deps_file=None):
|
| GClientKeywords.__init__(self)
|
| self.parent = parent
|
| self.name = name
|
| @@ -168,9 +163,9 @@ class Dependency(GClientKeywords):
|
| self.safesync_url = safesync_url
|
| self.custom_vars = custom_vars or {}
|
| self.custom_deps = custom_deps or {}
|
| + self.deps_hooks = []
|
| self.dependencies = []
|
| self.deps_file = deps_file or self.DEPS_FILE
|
| - self._deps_hooks = []
|
|
|
| # Sanity checks
|
| if not self.name and self.parent:
|
| @@ -238,6 +233,7 @@ solutions = [
|
| self.config_content = None
|
|
|
| def SetConfig(self, content):
|
| + assert self.dependencies == []
|
| config_dict = {}
|
| self.config_content = content
|
| try:
|
| @@ -262,37 +258,23 @@ solutions = [
|
| s.get('custom_deps', {}),
|
| s.get('custom_vars', {})))
|
| # .gclient can have hooks.
|
| - self._deps_hooks = config_dict.get('hooks', [])
|
| + self.deps_hooks = config_dict.get('hooks', [])
|
|
|
| def SaveConfig(self):
|
| gclient_utils.FileWrite(os.path.join(self.root_dir(),
|
| self._options.config_filename),
|
| self.config_content)
|
|
|
| - def _LoadConfig(self):
|
| - client_source = gclient_utils.FileRead(
|
| - os.path.join(self.root_dir(), self._options.config_filename))
|
| - self.SetConfig(client_source)
|
| -
|
| @staticmethod
|
| - def LoadCurrentConfig(options, from_dir=None):
|
| + def LoadCurrentConfig(options):
|
| """Searches for and loads a .gclient file relative to the current working
|
| - dir.
|
| -
|
| - Returns:
|
| - A dict representing the contents of the .gclient file or an empty dict if
|
| - the .gclient file doesn't exist.
|
| - """
|
| - if not from_dir:
|
| - from_dir = os.curdir
|
| - path = os.path.realpath(from_dir)
|
| - while not os.path.exists(os.path.join(path, options.config_filename)):
|
| - split_path = os.path.split(path)
|
| - if not split_path[1]:
|
| - return None
|
| - path = split_path[0]
|
| + dir. Returns a GClient object."""
|
| + path = gclient_utils.FindGclientRoot(os.getcwd(), options.config_filename)
|
| + if not path:
|
| + return None
|
| client = GClient(path, options)
|
| - client._LoadConfig()
|
| + client.SetConfig(gclient_utils.FileRead(
|
| + os.path.join(path, options.config_filename)))
|
| return client
|
|
|
| def SetDefaultConfig(self, solution_name, solution_url, safesync_url):
|
| @@ -322,9 +304,6 @@ solutions = [
|
| def _ReadEntries(self):
|
| """Read the .gclient_entries file for the given client.
|
|
|
| - Args:
|
| - client: The client for which the entries file should be read.
|
| -
|
| Returns:
|
| A sequence of solution names, which will be empty if there is the
|
| entries file hasn't been created yet.
|
| @@ -334,7 +313,7 @@ solutions = [
|
| if not os.path.exists(filename):
|
| return []
|
| exec(gclient_utils.FileRead(filename), scope)
|
| - return scope["entries"]
|
| + return scope['entries']
|
|
|
| def _ParseSolutionDeps(self, solution_name, solution_deps_content,
|
| custom_vars, parse_hooks):
|
| @@ -391,7 +370,7 @@ solutions = [
|
| # right 'self' to add the hooks.
|
| for d in self.dependencies:
|
| if d.name == solution_name:
|
| - d._deps_hooks.extend(local_scope['hooks'])
|
| + d.deps_hooks.extend(local_scope['hooks'])
|
| break
|
|
|
| # If use_relative_paths is set in the DEPS file, regenerate
|
| @@ -515,10 +494,10 @@ solutions = [
|
| return
|
|
|
| # Get any hooks from the .gclient file.
|
| - hooks = self._deps_hooks[:]
|
| + hooks = self.deps_hooks[:]
|
| # Add any hooks found in DEPS files.
|
| for d in self.dependencies:
|
| - hooks.extend(d._deps_hooks)
|
| + hooks.extend(d.deps_hooks)
|
|
|
| # If "--force" was specified, run all hooks regardless of what files have
|
| # changed. If the user is using git, then we don't know what files have
|
| @@ -571,14 +550,9 @@ solutions = [
|
| def RunOnDeps(self, command, args):
|
| """Runs a command on each dependency in a client and its dependencies.
|
|
|
| - The module's dependencies are specified in its top-level DEPS files.
|
| -
|
| Args:
|
| command: The command to use (e.g., 'status' or 'diff')
|
| args: list of str - extra arguments to add to the command line.
|
| -
|
| - Raises:
|
| - Error: If the client has conflicting entries.
|
| """
|
| if not command in self.SUPPORTED_COMMANDS:
|
| raise gclient_utils.Error("'%s' is an unsupported command" % command)
|
| @@ -834,14 +808,14 @@ def CMDcleanup(parser, args):
|
|
|
| Mostly svn-specific. Simply runs 'svn cleanup' for each module.
|
| """
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| (options, args) = parser.parse_args(args)
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| # client dict, but more legible, and it might contain helpful comments.
|
| @@ -859,19 +833,19 @@ modules to operate on as well. If optional [url] parameter is
|
| provided, then configuration is read from a specified Subversion server
|
| URL.
|
| """
|
| - 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")
|
| + 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 ((options.spec and args) or len(args) > 2 or
|
| (not options.spec and not args)):
|
| parser.error('Inconsistent arguments. Use either --spec or one or 2 args')
|
|
|
| if os.path.exists(options.config_filename):
|
| - raise gclient_utils.Error("%s file already exists in the current directory"
|
| + raise gclient_utils.Error('%s file already exists in the current directory'
|
| % options.config_filename)
|
| client = GClient('.', options)
|
| if options.spec:
|
| @@ -879,11 +853,11 @@ URL.
|
| else:
|
| base_url = args[0].rstrip('/')
|
| if not options.name:
|
| - name = base_url.split("/")[-1]
|
| + name = base_url.split('/')[-1]
|
| else:
|
| # specify an alternate relpath for the given URL.
|
| name = options.name
|
| - safesync_url = ""
|
| + safesync_url = ''
|
| if len(args) > 1:
|
| safesync_url = args[1]
|
| client.SetDefaultConfig(name, base_url, safesync_url)
|
| @@ -893,17 +867,17 @@ URL.
|
|
|
| def CMDexport(parser, args):
|
| """Wrapper for svn export for all managed directories."""
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| (options, args) = parser.parse_args(args)
|
| if len(args) != 1:
|
| - raise gclient_utils.Error("Need directory name")
|
| + raise gclient_utils.Error('Need directory name')
|
| client = GClient.LoadCurrentConfig(options)
|
|
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
|
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| @@ -924,14 +898,14 @@ 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'.
|
| """
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| (options, args) = parser.parse_args(args)
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| # client dict, but more legible, and it might contain helpful comments.
|
| @@ -941,14 +915,14 @@ checked out tree via 'patch -p0 < patchfile'.
|
|
|
| def CMDstatus(parser, args):
|
| """Show modification status for every dependencies."""
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| (options, args) = parser.parse_args(args)
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| # client dict, but more legible, and it might contain helpful comments.
|
| @@ -968,41 +942,41 @@ def CMDstatus(parser, args):
|
| """)
|
| def CMDsync(parser, args):
|
| """Checkout/update all modules."""
|
| - parser.add_option("-f", "--force", action="store_true",
|
| - help="force update even for unchanged modules")
|
| - parser.add_option("-n", "--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="Enforces revision/hash for the solutions with the "
|
| - "format src@rev. The src@ part is optional and can be "
|
| - "skipped. -r can be used multiple times when .gclient "
|
| - "has multiple solutions configured and will work even "
|
| - "if the src@ part is skipped.")
|
| - parser.add_option("-H", "--head", action="store_true",
|
| - help="skips any safesync_urls specified in "
|
| - "configured solutions and sync to head instead")
|
| - parser.add_option("-D", "--delete_unversioned_trees", action="store_true",
|
| - help="delete any unexpected unversioned trees "
|
| - "that are in the checkout")
|
| - parser.add_option("-R", "--reset", action="store_true",
|
| - help="resets any local changes before updating (git only)")
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| - parser.add_option("-m", "--manually_grab_svn_rev", action="store_true",
|
| - help="Skip svn up whenever possible by requesting "
|
| - "actual HEAD revision from the repository")
|
| + parser.add_option('-f', '--force', action='store_true',
|
| + help='force update even for unchanged modules')
|
| + parser.add_option('-n', '--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='Enforces revision/hash for the solutions with the '
|
| + 'format src@rev. The src@ part is optional and can be '
|
| + 'skipped. -r can be used multiple times when .gclient '
|
| + 'has multiple solutions configured and will work even '
|
| + 'if the src@ part is skipped.')
|
| + parser.add_option('-H', '--head', action='store_true',
|
| + help='skips any safesync_urls specified in '
|
| + 'configured solutions and sync to head instead')
|
| + parser.add_option('-D', '--delete_unversioned_trees', action='store_true',
|
| + help='delete any unexpected unversioned trees '
|
| + 'that are in the checkout')
|
| + parser.add_option('-R', '--reset', action='store_true',
|
| + help='resets any local changes before updating (git only)')
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| + parser.add_option('-m', '--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:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
|
|
| if options.revisions and options.head:
|
| # TODO(maruel): Make it a parser.error if it doesn't break any builder.
|
| - print("Warning: you cannot use both --head and --revision")
|
| + print('Warning: you cannot use both --head and --revision')
|
|
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| @@ -1017,14 +991,14 @@ def CMDupdate(parser, args):
|
|
|
| def CMDdiff(parser, args):
|
| """Displays local diff for every dependencies."""
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| (options, args) = parser.parse_args(args)
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| # client dict, but more legible, and it might contain helpful comments.
|
| @@ -1034,33 +1008,33 @@ def CMDdiff(parser, args):
|
|
|
| def CMDrevert(parser, args):
|
| """Revert all modifications in every dependencies."""
|
| - parser.add_option("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| - parser.add_option("-n", "--nohooks", action="store_true",
|
| - help="don't run hooks after the revert is complete")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| + parser.add_option('-n', '--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
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + 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("--deps", dest="deps_os", metavar="OS_LIST",
|
| - help="override deps for the specified (comma-separated) "
|
| - "platform(s); 'all' will process all deps_os "
|
| - "references")
|
| - parser.add_option("-f", "--force", action="store_true", default=True,
|
| - help="Deprecated. No effect.")
|
| + parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| + help='override deps for the specified (comma-separated) '
|
| + 'platform(s); \'all\' will process all deps_os '
|
| + 'references')
|
| + parser.add_option('-f', '--force', action='store_true', default=True,
|
| + help='Deprecated. No effect.')
|
| (options, args) = parser.parse_args(args)
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
| if options.verbose:
|
| # Print out the .gclient file. This is longer than if we just printed the
|
| # client dict, but more legible, and it might contain helpful comments.
|
| @@ -1073,10 +1047,10 @@ def CMDrunhooks(parser, args):
|
| def CMDrevinfo(parser, args):
|
| """Output revision info mapping for the client and its dependencies.
|
|
|
| - This allows the capture of an overall "revision" for the source tree that
|
| + This allows the capture of an overall 'revision' for the source tree that
|
| can be used to reproduce the same tree in the future. It is only useful for
|
| - "unpinned dependencies", i.e. DEPS/deps references without a svn revision
|
| - number or a git hash. A git branch name isn't "pinned" since the actual
|
| + 'unpinned dependencies', i.e. DEPS/deps references without a svn revision
|
| + number or a git hash. A git branch name isn't 'pinned' since the actual
|
| commit can change.
|
| """
|
| parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
|
| @@ -1090,7 +1064,7 @@ def CMDrevinfo(parser, args):
|
| (options, args) = parser.parse_args(args)
|
| client = GClient.LoadCurrentConfig(options)
|
| if not client:
|
| - raise gclient_utils.Error("client not configured; see 'gclient config'")
|
| + raise gclient_utils.Error('client not configured; see \'gclient config\'')
|
| client.PrintRevInfo()
|
| return 0
|
|
|
|
|