#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Meta checkout dependency manager for Git."""
# Files
#   .gclient      : Current client configuration, written by 'config' command.
#                   Format is a Python script defining 'solutions', a list whose
#                   entries each are maps binding the strings "name" and "url"
#                   to strings specifying the name and location of the client
#                   module, as well as "custom_deps" to a map similar to the
#                   deps section of the DEPS file below, as well as
#                   "custom_hooks" to a list similar to the hooks sections of
#                   the DEPS file below.
#   .gclient_entries : A cache constructed by 'update' command.  Format is a
#                   Python script defining 'entries', a list of the names
#                   of all modules in the client
#   <module>/DEPS : Python script defining var 'deps' as a map from each
#                   requisite submodule name to a URL where it can be found (via
#                   one SCM)
#
# 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
#   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 but not suppressed hooks will run regardless of the state
#   of the working copy.
#
#   Each item in a "hooks" list is a dict, containing these two keys:
#     "pattern"  The associated value is a string containing a regular
#                expression.  When a file whose pathname matches the expression
#                is checked out, updated, or reverted, the hook's "action" will
#                run.
#     "action"   A list describing a command to run along with its arguments, if
#                any.  An action command will run at most one time per gclient
#                invocation, regardless of how many files matched the pattern.
#                The action is executed in the same directory as the .gclient
#                file.  If the first item in the list is the string "python",
#                the current Python interpreter (sys.executable) will be used
#                to run the command. If the list contains string
#                "$matching_files" it will be removed from the list and the list
#                will be extended by the list of matching files.
#     "name"     An optional string specifying the group to which a hook belongs
#                for overriding and organizing.
#
#   Example:
#     hooks = [
#       { "pattern": "\\.(gif|jpe?g|pr0n|png)$",
#         "action":  ["python", "image_indexer.py", "--all"]},
#       { "pattern": ".",
#         "name": "gyp",
#         "action":  ["python", "src/build/gyp_chromium"]},
#     ]
#
# Pre-DEPS Hooks
#   DEPS files may optionally contain a list named "pre_deps_hooks".  These are
#   the same as normal hooks, except that they run before the DEPS are
#   processed. Pre-DEPS run with "sync" and "revert" unless the --noprehooks
#   flag is used.
#
# Specifying a target OS
#   An optional key named "target_os" may be added to a gclient file to specify
#   one or more additional operating systems that should be considered when
#   processing the deps_os/hooks_os dict of a DEPS file.
#
#   Example:
#     target_os = [ "android" ]
#
#   If the "target_os_only" key is also present and true, then *only* the
#   operating systems listed in "target_os" will be used.
#
#   Example:
#     target_os = [ "ios" ]
#     target_os_only = True
#
# Specifying a target CPU
#   To specify a target CPU, the variables target_cpu and target_cpu_only
#   are available and are analagous to target_os and target_os_only.

from __future__ import print_function

__version__ = '0.7'

import collections
import copy
import json
import logging
import optparse
import os
import platform
import posixpath
import pprint
import re
import sys
import time
import urlparse

import detect_host_arch
import fix_encoding
import gclient_eval
import gclient_scm
import gclient_utils
import git_cache
import metrics
import metrics_utils
from third_party.repo.progress import Progress
import subcommand
import subprocess2
import setup_color


# Singleton object to represent an unset cache_dir (as opposed to a disabled
# one, e.g. if a spec explicitly says `cache_dir = None`.)
UNSET_CACHE_DIR = object()


class GNException(Exception):
  pass


def ToGNString(value, allow_dicts = True):
  """Returns a stringified GN equivalent of the Python value.

  allow_dicts indicates if this function will allow converting dictionaries
  to GN scopes. This is only possible at the top level, you can't nest a
  GN scope in a list, so this should be set to False for recursive calls."""
  if isinstance(value, basestring):
    if value.find('\n') >= 0:
      raise GNException("Trying to print a string with a newline in it.")
    return '"' + \
        value.replace('\\', '\\\\').replace('"', '\\"').replace('$', '\\$') + \
        '"'

  if isinstance(value, unicode):
    return ToGNString(value.encode('utf-8'))

  if isinstance(value, bool):
    if value:
      return "true"
    return "false"

  # NOTE: some type handling removed compared to chromium/src copy.

  raise GNException("Unsupported type when printing to GN.")


class Hook(object):
  """Descriptor of command ran before/after sync or on demand."""

  def __init__(self, action, pattern=None, name=None, cwd=None, condition=None,
               variables=None, verbose=False, cwd_base=None):
    """Constructor.

    Arguments:
      action (list of basestring): argv of the command to run
      pattern (basestring regex): noop with git; deprecated
      name (basestring): optional name; no effect on operation
      cwd (basestring): working directory to use
      condition (basestring): condition when to run the hook
      variables (dict): variables for evaluating the condition
    """
    self._action = gclient_utils.freeze(action)
    self._pattern = pattern
    self._name = name
    self._cwd = cwd
    self._condition = condition
    self._variables = variables
    self._verbose = verbose
    self._cwd_base = cwd_base

  @staticmethod
  def from_dict(d, variables=None, verbose=False, conditions=None,
                cwd_base=None):
    """Creates a Hook instance from a dict like in the DEPS file."""
    # Merge any local and inherited conditions.
    gclient_eval.UpdateCondition(d, 'and', conditions)
    return Hook(
        d['action'],
        d.get('pattern'),
        d.get('name'),
        d.get('cwd'),
        d.get('condition'),
        variables=variables,
        # Always print the header if not printing to a TTY.
        verbose=verbose or not setup_color.IS_TTY,
        cwd_base=cwd_base)

  @property
  def action(self):
    return self._action

  @property
  def pattern(self):
    return self._pattern

  @property
  def name(self):
    return self._name

  @property
  def condition(self):
    return self._condition

  @property
  def effective_cwd(self):
    cwd = self._cwd_base
    if self._cwd:
      cwd = os.path.join(cwd, self._cwd)
    return cwd

  def matches(self, file_list):
    """Returns true if the pattern matches any of files in the list."""
    if not self._pattern:
      return True
    pattern = re.compile(self._pattern)
    return bool([f for f in file_list if pattern.search(f)])

  def run(self):
    """Executes the hook's command (provided the condition is met)."""
    if (self._condition and
        not gclient_eval.EvaluateCondition(self._condition, self._variables)):
      return

    cmd = [arg for arg in self._action]

    if cmd[0] == 'python':
      # If the hook specified "python" as the first item, the action is a
      # Python script.  Run it by starting a new copy of the same
      # interpreter.
      cmd[0] = sys.executable
    elif cmd[0] == 'vpython' and _detect_host_os() == 'win':
      cmd[0] += '.bat'

    try:
      start_time = time.time()
      gclient_utils.CheckCallAndFilterAndHeader(
          cmd, cwd=self.effective_cwd, always=self._verbose)
    except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
      # Use a discrete exit status code of 2 to indicate that a hook action
      # failed.  Users of this script may wish to treat hook action failures
      # differently from VC failures.
      print('Error: %s' % str(e), file=sys.stderr)
      sys.exit(2)
    finally:
      elapsed_time = time.time() - start_time
      if elapsed_time > 10:
        print("Hook '%s' took %.2f secs" % (
            gclient_utils.CommandToStr(cmd), elapsed_time))


class DependencySettings(object):
  """Immutable configuration settings."""
  def __init__(
      self, parent, url, managed, custom_deps, custom_vars,
      custom_hooks, deps_file, should_process, relative, condition):
    # These are not mutable:
    self._parent = parent
    self._deps_file = deps_file
    self._url = url
    # The condition as string (or None). Useful to keep e.g. for flatten.
    self._condition = condition
    # 'managed' determines whether or not this dependency is synced/updated by
    # gclient after gclient checks it out initially.  The difference between
    # 'managed' and 'should_process' is that the user specifies 'managed' via
    # the --unmanaged command-line flag or a .gclient config, where
    # 'should_process' is dynamically set by gclient if it goes over its
    # recursion limit and controls gclient's behavior so it does not misbehave.
    self._managed = managed
    self._should_process = should_process
    # If this is a recursed-upon sub-dependency, and the parent has
    # use_relative_paths set, then this dependency should check out its own
    # dependencies relative to that parent's path for this, rather than
    # relative to the .gclient file.
    self._relative = relative
    # This is a mutable value which has the list of 'target_os' OSes listed in
    # the current deps file.
    self.local_target_os = None

    # These are only set in .gclient and not in DEPS files.
    self._custom_vars = custom_vars or {}
    self._custom_deps = custom_deps or {}
    self._custom_hooks = custom_hooks or []

    # Post process the url to remove trailing slashes.
    if isinstance(self.url, basestring):
      # urls are sometime incorrectly written as proto://host/path/@rev. Replace
      # it to proto://host/path@rev.
      self.set_url(self.url.replace('/@', '@'))
    elif not isinstance(self.url, (None.__class__)):
      raise gclient_utils.Error(
          ('dependency url must be either string or None, '
           'instead of %s') % self.url.__class__.__name__)

    # Make any deps_file path platform-appropriate.
    if self._deps_file:
      for sep in ['/', '\\']:
        self._deps_file = self._deps_file.replace(sep, os.sep)

  @property
  def deps_file(self):
    return self._deps_file

  @property
  def managed(self):
    return self._managed

  @property
  def parent(self):
    return self._parent

  @property
  def root(self):
    """Returns the root node, a GClient object."""
    if not self.parent:
      # This line is to signal pylint that it could be a GClient instance.
      return self or GClient(None, None)
    return self.parent.root

  @property
  def should_process(self):
    """True if this dependency should be processed, i.e. checked out."""
    return self._should_process

  @property
  def custom_vars(self):
    return self._custom_vars.copy()

  @property
  def custom_deps(self):
    return self._custom_deps.copy()

  @property
  def custom_hooks(self):
    return self._custom_hooks[:]

  @property
  def url(self):
    """URL after variable expansion."""
    return self._url

  @property
  def condition(self):
    return self._condition

  @property
  def target_os(self):
    if self.local_target_os is not None:
      return tuple(set(self.local_target_os).union(self.parent.target_os))
    else:
      return self.parent.target_os

  @property
  def target_cpu(self):
    return self.parent.target_cpu

  def set_url(self, url):
    self._url = url

  def get_custom_deps(self, name, url):
    """Returns a custom deps if applicable."""
    if self.parent:
      url = self.parent.get_custom_deps(name, url)
    # None is a valid return value to disable a dependency.
    return self.custom_deps.get(name, url)


class Dependency(gclient_utils.WorkItem, DependencySettings):
  """Object that represents a dependency checkout."""

  def __init__(self, parent, name, url, managed, custom_deps,
               custom_vars, custom_hooks, deps_file, should_process,
               should_recurse, relative, condition, print_outbuf=False):
    gclient_utils.WorkItem.__init__(self, name)
    DependencySettings.__init__(
        self, parent, url, managed, custom_deps, custom_vars,
        custom_hooks, deps_file, should_process, relative, condition)

    # This is in both .gclient and DEPS files:
    self._deps_hooks = []

    self._pre_deps_hooks = []

    # Calculates properties:
    self._dependencies = []
    self._vars = {}

    # A cache of the files affected by the current operation, necessary for
    # hooks.
    self._file_list = []
    # List of host names from which dependencies are allowed.
    # Default is an empty set, meaning unspecified in DEPS file, and hence all
    # hosts will be allowed. Non-empty set means whitelist of hosts.
    # allowed_hosts var is scoped to its DEPS file, and so it isn't recursive.
    self._allowed_hosts = frozenset()
    self._gn_args_from = None
    # Spec for .gni output to write (if any).
    self._gn_args_file = None
    self._gn_args = []
    # If it is not set to True, the dependency wasn't processed for its child
    # dependency, i.e. its DEPS wasn't read.
    self._deps_parsed = False
    # This dependency has been processed, i.e. checked out
    self._processed = False
    # This dependency had its pre-DEPS hooks run
    self._pre_deps_hooks_ran = False
    # This dependency had its hook run
    self._hooks_ran = False
    # This is the scm used to checkout self.url. It may be used by dependencies
    # to get the datetime of the revision we checked out.
    self._used_scm = None
    self._used_revision = None
    # The actual revision we ended up getting, or None if that information is
    # unavailable
    self._got_revision = None

    # recursedeps is a mutable value that selectively overrides the default
    # 'no recursion' setting on a dep-by-dep basis.
    #
    # It will be a dictionary of {deps_name: depfile_namee}
    self.recursedeps = {}

    # Whether we should process this dependency's DEPS file.
    self._should_recurse = should_recurse

    self._OverrideUrl()
    # This is inherited from WorkItem.  We want the URL to be a resource.
    if self.url and isinstance(self.url, basestring):
      # The url is usually given to gclient either as https://blah@123
      # or just https://blah.  The @123 portion is irrelevant.
      self.resources.append(self.url.split('@')[0])

    # Controls whether we want to print git's output when we first clone the
    # dependency
    self.print_outbuf = print_outbuf

    if not self.name and self.parent:
      raise gclient_utils.Error('Dependency without name')

  def _OverrideUrl(self):
    """Resolves the parsed url from the parent hierarchy."""
    parsed_url = self.get_custom_deps(self._name, self.url)
    if parsed_url != self.url:
      logging.info('Dependency(%s)._OverrideUrl(%s) -> %s', self._name,
                   self.url, parsed_url)
      self.set_url(parsed_url)

    elif isinstance(self.url, basestring):
      parsed_url = urlparse.urlparse(self.url)
      if (not parsed_url[0] and
          not re.match(r'^\w+\@[\w\.-]+\:[\w\/]+', parsed_url[2])):
        path = parsed_url[2]
        if not path.startswith('/'):
          raise gclient_utils.Error(
              'relative DEPS entry \'%s\' must begin with a slash' % self.url)
        # A relative url. Get the parent url, strip from the last '/'
        # (equivalent to unix basename), and append the relative url.
        parent_url = self.parent.url
        parsed_url = parent_url[:parent_url.rfind('/')] + self.url
        logging.info('Dependency(%s)._OverrideUrl(%s) -> %s', self.name,
                     self.url, parsed_url)
        self.set_url(parsed_url)

    elif self.url is None:
      logging.info('Dependency(%s)._OverrideUrl(None) -> None', self._name)

    else:
      raise gclient_utils.Error('Unknown url type')

  def PinToActualRevision(self):
    """Updates self.url to the revision checked out on disk."""
    if self.url is None:
      return
    url = None
    scm = self.CreateSCM()
    if os.path.isdir(scm.checkout_path):
      revision = scm.revinfo(None, None, None)
      url = '%s@%s' % (gclient_utils.SplitUrlRevision(self.url)[0], revision)
    self.set_url(url)

  def ToLines(self):
    s = []
    condition_part = (['    "condition": %r,' % self.condition]
                      if self.condition else [])
    s.extend([
        '  # %s' % self.hierarchy(include_url=False),
        '  "%s": {' % (self.name,),
        '    "url": "%s",' % (self.url,),
    ] + condition_part + [
        '  },',
        '',
    ])
    return s

  @property
  def requirements(self):
    """Calculate the list of requirements."""
    requirements = set()
    # self.parent is implicitly a requirement. This will be recursive by
    # definition.
    if self.parent and self.parent.name:
      requirements.add(self.parent.name)

    # For a tree with at least 2 levels*, the leaf node needs to depend
    # on the level higher up in an orderly way.
    # This becomes messy for >2 depth as the DEPS file format is a dictionary,
    # thus unsorted, while the .gclient format is a list thus sorted.
    #
    # Interestingly enough, the following condition only works in the case we
    # want: self is a 2nd level node. 3nd level node wouldn't need this since
    # they already have their parent as a requirement.
    if self.parent and self.parent.parent and not self.parent.parent.parent:
      requirements |= set(i.name for i in self.root.dependencies if i.name)

    if self.name:
      requirements |= set(
          obj.name for obj in self.root.subtree(False)
          if (obj is not self
              and obj.name and
              self.name.startswith(posixpath.join(obj.name, ''))))
    requirements = tuple(sorted(requirements))
    logging.info('Dependency(%s).requirements = %s' % (self.name, requirements))
    return requirements

  @property
  def should_recurse(self):
    return self._should_recurse

  def verify_validity(self):
    """Verifies that this Dependency is fine to add as a child of another one.

    Returns True if this entry should be added, False if it is a duplicate of
    another entry.
    """
    logging.info('Dependency(%s).verify_validity()' % self.name)
    if self.name in [s.name for s in self.parent.dependencies]:
      raise gclient_utils.Error(
          'The same name "%s" appears multiple times in the deps section' %
              self.name)
    if not self.should_process:
      # Return early, no need to set requirements.
      return not any(d.name == self.name for d in self.root.subtree(True))

    # This require a full tree traversal with locks.
    siblings = [d for d in self.root.subtree(False) if d.name == self.name]
    for sibling in siblings:
      # Allow to have only one to be None or ''.
      if self.url != sibling.url and bool(self.url) == bool(sibling.url):
        raise gclient_utils.Error(
            ('Dependency %s specified more than once:\n'
            '  %s [%s]\n'
            'vs\n'
            '  %s [%s]') % (
              self.name,
              sibling.hierarchy(),
              sibling.url,
              self.hierarchy(),
              self.url))
      # In theory we could keep it as a shadow of the other one. In
      # practice, simply ignore it.
      logging.warn('Won\'t process duplicate dependency %s' % sibling)
      return False
    return True

  def _postprocess_deps(self, deps, rel_prefix):
    """Performs post-processing of deps compared to what's in the DEPS file."""
    # Make sure the dict is mutable, e.g. in case it's frozen.
    deps = dict(deps)

    # If a line is in custom_deps, but not in the solution, we want to append
    # this line to the solution.
    for dep_name, dep_info in self.custom_deps.iteritems():
      if dep_name not in deps:
        deps[dep_name] = {'url': dep_info, 'dep_type': 'git'}

    # Make child deps conditional on any parent conditions. This ensures that,
    # when flattened, recursed entries have the correct restrictions, even if
    # not explicitly set in the recursed DEPS file. For instance, if
    # "src/ios_foo" is conditional on "checkout_ios=True", then anything
    # recursively included by "src/ios_foo/DEPS" should also require
    # "checkout_ios=True".
    if self.condition:
      for value in deps.itervalues():
        gclient_eval.UpdateCondition(value, 'and', self.condition)

    if rel_prefix:
      logging.warning('use_relative_paths enabled.')
      rel_deps = {}
      for d, url in deps.items():
        # normpath is required to allow DEPS to use .. in their
        # dependency local path.
        rel_deps[os.path.normpath(os.path.join(rel_prefix, d))] = url
      logging.warning('Updating deps by prepending %s.', rel_prefix)
      deps = rel_deps

    return deps

  def _deps_to_objects(self, deps, use_relative_paths):
    """Convert a deps dict to a dict of Dependency objects."""
    deps_to_add = []
    for name, dep_value in deps.iteritems():
      should_process = self.should_process
      if dep_value is None:
        continue

      condition = dep_value.get('condition')
      dep_type = dep_value.get('dep_type')

      if condition and not self._get_option('process_all_deps', False):
        should_process = should_process and gclient_eval.EvaluateCondition(
            condition, self.get_vars())

      # The following option is only set by the 'revinfo' command.
      if self._get_option('ignore_dep_type', None) == dep_type:
        continue

      if dep_type == 'cipd':
        cipd_root = self.GetCipdRoot()
        for package in dep_value.get('packages', []):
          deps_to_add.append(
              CipdDependency(
                  parent=self,
                  name=name,
                  dep_value=package,
                  cipd_root=cipd_root,
                  custom_vars=self.custom_vars,
                  should_process=should_process,
                  relative=use_relative_paths,
                  condition=condition))
      else:
        url = dep_value.get('url')
        deps_to_add.append(
            GitDependency(
                parent=self,
                name=name,
                url=url,
                managed=True,
                custom_deps=None,
                custom_vars=self.custom_vars,
                custom_hooks=None,
                deps_file=self.recursedeps.get(name, self.deps_file),
                should_process=should_process,
                should_recurse=name in self.recursedeps,
                relative=use_relative_paths,
                condition=condition))

    deps_to_add.sort(key=lambda x: x.name)
    return deps_to_add

  def ParseDepsFile(self):
    """Parses the DEPS file for this dependency."""
    assert not self.deps_parsed
    assert not self.dependencies

    deps_content = None

    # First try to locate the configured deps file.  If it's missing, fallback
    # to DEPS.
    deps_files = [self.deps_file]
    if 'DEPS' not in deps_files:
      deps_files.append('DEPS')
    for deps_file in deps_files:
      filepath = os.path.join(self.root.root_dir, self.name, deps_file)
      if os.path.isfile(filepath):
        logging.info(
            'ParseDepsFile(%s): %s file found at %s', self.name, deps_file,
            filepath)
        break
      logging.info(
          'ParseDepsFile(%s): No %s file found at %s', self.name, deps_file,
          filepath)

    if os.path.isfile(filepath):
      deps_content = gclient_utils.FileRead(filepath)
      logging.debug('ParseDepsFile(%s) read:\n%s', self.name, deps_content)

    local_scope = {}
    if deps_content:
      try:
        local_scope = gclient_eval.Parse(
            deps_content, self._get_option('validate_syntax', False),
            filepath, self.get_vars(), self.get_builtin_vars())
      except SyntaxError as e:
        gclient_utils.SyntaxErrorToError(filepath, e)

    if 'allowed_hosts' in local_scope:
      try:
        self._allowed_hosts = frozenset(local_scope.get('allowed_hosts'))
      except TypeError:  # raised if non-iterable
        pass
      if not self._allowed_hosts:
        logging.warning("allowed_hosts is specified but empty %s",
                        self._allowed_hosts)
        raise gclient_utils.Error(
            'ParseDepsFile(%s): allowed_hosts must be absent '
            'or a non-empty iterable' % self.name)

    self._gn_args_from = local_scope.get('gclient_gn_args_from')
    self._gn_args_file = local_scope.get('gclient_gn_args_file')
    self._gn_args = local_scope.get('gclient_gn_args', [])
    # It doesn't make sense to set all of these, since setting gn_args_from to
    # another DEPS will make gclient ignore any other local gn_args* settings.
    assert not (self._gn_args_from and self._gn_args_file), \
        'Only specify one of "gclient_gn_args_from" or ' \
        '"gclient_gn_args_file + gclient_gn_args".'

    self._vars = local_scope.get('vars', {})
    if self.parent:
      for key, value in self.parent.get_vars().iteritems():
        if key in self._vars:
          self._vars[key] = value
    # Since we heavily post-process things, freeze ones which should
    # reflect original state of DEPS.
    self._vars = gclient_utils.freeze(self._vars)

    # If use_relative_paths is set in the DEPS file, regenerate
    # the dictionary using paths relative to the directory containing
    # the DEPS file.  Also update recursedeps if use_relative_paths is
    # enabled.
    # If the deps file doesn't set use_relative_paths, but the parent did
    # (and therefore set self.relative on this Dependency object), then we
    # want to modify the deps and recursedeps by prepending the parent
    # directory of this dependency.
    use_relative_paths = local_scope.get('use_relative_paths', False)
    rel_prefix = None
    if use_relative_paths:
      rel_prefix = self.name
    elif self._relative:
      rel_prefix = os.path.dirname(self.name)

    if 'recursion' in local_scope:
      logging.warning(
          '%s: Ignoring recursion = %d.', self.name, local_scope['recursion'])

    if 'recursedeps' in local_scope:
      for ent in local_scope['recursedeps']:
        if isinstance(ent, basestring):
          self.recursedeps[ent] = self.deps_file
        else:  # (depname, depsfilename)
          self.recursedeps[ent[0]] = ent[1]
      logging.warning('Found recursedeps %r.', repr(self.recursedeps))

      if rel_prefix:
        logging.warning('Updating recursedeps by prepending %s.', rel_prefix)
        rel_deps = {}
        for depname, options in self.recursedeps.iteritems():
          rel_deps[
              os.path.normpath(os.path.join(rel_prefix, depname))] = options
        self.recursedeps = rel_deps
    # To get gn_args from another DEPS, that DEPS must be recursed into.
    if self._gn_args_from:
      assert self.recursedeps and self._gn_args_from in self.recursedeps, \
              'The "gclient_gn_args_from" value must be in recursedeps.'

    # If present, save 'target_os' in the local_target_os property.
    if 'target_os' in local_scope:
      self.local_target_os = local_scope['target_os']

    deps = local_scope.get('deps', {})
    deps_to_add = self._deps_to_objects(
        self._postprocess_deps(deps, rel_prefix), use_relative_paths)

    # compute which working directory should be used for hooks
    use_relative_hooks = local_scope.get('use_relative_hooks', False)
    hooks_cwd = self.root.root_dir
    if use_relative_hooks:
      if not use_relative_paths:
        raise gclient_utils.Error(
            'ParseDepsFile(%s): use_relative_hooks must be used with '
            'use_relative_paths' % self.name)
      hooks_cwd = os.path.join(hooks_cwd, self.name)
      logging.warning('Updating hook base working directory to %s.',
                      hooks_cwd)

    # override named sets of hooks by the custom hooks
    hooks_to_run = []
    hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks]
    for hook in local_scope.get('hooks', []):
      if hook.get('name', '') not in hook_names_to_suppress:
        hooks_to_run.append(hook)

    # add the replacements and any additions
    for hook in self.custom_hooks:
      if 'action' in hook:
        hooks_to_run.append(hook)

    if self.should_recurse:
      self._pre_deps_hooks = [
          Hook.from_dict(hook, variables=self.get_vars(), verbose=True,
                         conditions=self.condition, cwd_base=hooks_cwd)
          for hook in local_scope.get('pre_deps_hooks', [])
      ]

    self.add_dependencies_and_close(deps_to_add, hooks_to_run,
                                    hooks_cwd=hooks_cwd)
    logging.info('ParseDepsFile(%s) done' % self.name)

  def _get_option(self, attr, default):
    obj = self
    while not hasattr(obj, '_options'):
      obj = obj.parent
    return getattr(obj._options, attr, default)

  def add_dependencies_and_close(self, deps_to_add, hooks, hooks_cwd=None):
    """Adds the dependencies, hooks and mark the parsing as done."""
    if hooks_cwd == None:
      hooks_cwd = self.root.root_dir

    for dep in deps_to_add:
      if dep.verify_validity():
        self.add_dependency(dep)
    self._mark_as_parsed([
        Hook.from_dict(
            h, variables=self.get_vars(), verbose=self.root._options.verbose,
            conditions=self.condition, cwd_base=hooks_cwd)
        for h in hooks
    ])

  def findDepsFromNotAllowedHosts(self):
    """Returns a list of dependencies from not allowed hosts.

    If allowed_hosts is not set, allows all hosts and returns empty list.
    """
    if not self._allowed_hosts:
      return []
    bad_deps = []
    for dep in self._dependencies:
      # Don't enforce this for custom_deps.
      if dep.name in self._custom_deps:
        continue
      if isinstance(dep.url, basestring):
        parsed_url = urlparse.urlparse(dep.url)
        if parsed_url.netloc and parsed_url.netloc not in self._allowed_hosts:
          bad_deps.append(dep)
    return bad_deps

  def FuzzyMatchUrl(self, candidates):
    """Attempts to find this dependency in the list of candidates.

    It looks first for the URL of this dependency in the list of
    candidates. If it doesn't succeed, and the URL ends in '.git', it will try
    looking for the URL minus '.git'. Finally it will try to look for the name
    of the dependency.

    Args:
      candidates: list, dict. The list of candidates in which to look for this
          dependency. It can contain URLs as above, or dependency names like
          "src/some/dep".

    Returns:
      If this dependency is not found in the list of candidates, returns None.
      Otherwise, it returns under which name did we find this dependency:
       - Its parsed url: "https://example.com/src.git'
       - Its parsed url minus '.git': "https://example.com/src"
       - Its name: "src"
    """
    if self.url:
      origin, _ = gclient_utils.SplitUrlRevision(self.url)
      if origin in candidates:
        return origin
      if origin.endswith('.git') and origin[:-len('.git')] in candidates:
        return origin[:-len('.git')]
      if origin + '.git' in candidates:
        return origin + '.git'
    if self.name in candidates:
      return self.name
    return None

  # Arguments number differs from overridden method
  # pylint: disable=arguments-differ
  def run(self, revision_overrides, command, args, work_queue, options,
          patch_refs, target_branches):
    """Runs |command| then parse the DEPS file."""
    logging.info('Dependency(%s).run()' % self.name)
    assert self._file_list == []
    if not self.should_process:
      return
    # When running runhooks, there's no need to consult the SCM.
    # All known hooks are expected to run unconditionally regardless of working
    # copy state, so skip the SCM status check.
    run_scm = command not in (
        'flatten', 'runhooks', 'recurse', 'validate', None)
    file_list = [] if not options.nohooks else None
    revision_override = revision_overrides.pop(
        self.FuzzyMatchUrl(revision_overrides), None)
    if not revision_override and not self.managed:
      revision_override = 'unmanaged'
    if run_scm and self.url:
      # Create a shallow copy to mutate revision.
      options = copy.copy(options)
      options.revision = revision_override
      self._used_revision = options.revision
      self._used_scm = self.CreateSCM(out_cb=work_queue.out_cb)
      self._got_revision = self._used_scm.RunCommand(command, options, args,
                                                     file_list)

      patch_repo = self.url.split('@')[0]
      patch_ref = patch_refs.pop(self.FuzzyMatchUrl(patch_refs), None)
      target_branch = target_branches.pop(
          self.FuzzyMatchUrl(target_branches), None)
      if command == 'update' and patch_ref is not None:
        self._used_scm.apply_patch_ref(patch_repo, patch_ref, target_branch,
                                       options, file_list)

      if file_list:
        file_list = [os.path.join(self.name, f.strip()) for f in file_list]

      # TODO(phajdan.jr): We should know exactly when the paths are absolute.
      # Convert all absolute paths to relative.
      for i in range(len(file_list or [])):
        # It depends on the command being executed (like runhooks vs sync).
        if not os.path.isabs(file_list[i]):
          continue
        prefix = os.path.commonprefix(
            [self.root.root_dir.lower(), file_list[i].lower()])
        file_list[i] = file_list[i][len(prefix):]
        # Strip any leading path separators.
        while file_list[i].startswith(('\\', '/')):
          file_list[i] = file_list[i][1:]

    if self.should_recurse:
      self.ParseDepsFile()

    self._run_is_done(file_list or [])

    if self.should_recurse:
      if command in ('update', 'revert') and not options.noprehooks:
        self.RunPreDepsHooks()
      # Parse the dependencies of this dependency.
      for s in self.dependencies:
        if s.should_process:
          work_queue.enqueue(s)

    if command == 'recurse':
      # Skip file only checkout.
      scm = self.GetScmName()
      if not options.scm or scm in options.scm:
        cwd = os.path.normpath(os.path.join(self.root.root_dir, self.name))
        # Pass in the SCM type as an env variable.  Make sure we don't put
        # unicode strings in the environment.
        env = os.environ.copy()
        if scm:
          env['GCLIENT_SCM'] = str(scm)
        if self.url:
          env['GCLIENT_URL'] = str(self.url)
        env['GCLIENT_DEP_PATH'] = str(self.name)
        if options.prepend_dir and scm == 'git':
          print_stdout = False
          def filter_fn(line):
            """Git-specific path marshaling. It is optimized for git-grep."""

            def mod_path(git_pathspec):
              match = re.match('^(\\S+?:)?([^\0]+)$', git_pathspec)
              modified_path = os.path.join(self.name, match.group(2))
              branch = match.group(1) or ''
              return '%s%s' % (branch, modified_path)

            match = re.match('^Binary file ([^\0]+) matches$', line)
            if match:
              print('Binary file %s matches\n' % mod_path(match.group(1)))
              return

            items = line.split('\0')
            if len(items) == 2 and items[1]:
              print('%s : %s' % (mod_path(items[0]), items[1]))
            elif len(items) >= 2:
              # Multiple null bytes or a single trailing null byte indicate
              # git is likely displaying filenames only (such as with -l)
              print('\n'.join(mod_path(path) for path in items if path))
            else:
              print(line)
        else:
          print_stdout = True
          filter_fn = None

        if self.url is None:
          print('Skipped omitted dependency %s' % cwd, file=sys.stderr)
        elif os.path.isdir(cwd):
          try:
            gclient_utils.CheckCallAndFilter(
                args, cwd=cwd, env=env, print_stdout=print_stdout,
                filter_fn=filter_fn,
                )
          except subprocess2.CalledProcessError:
            if not options.ignore:
              raise
        else:
          print('Skipped missing %s' % cwd, file=sys.stderr)

  def GetScmName(self):
    raise NotImplementedError()

  def CreateSCM(self, out_cb=None):
    raise NotImplementedError()

  def HasGNArgsFile(self):
    return self._gn_args_file is not None

  def WriteGNArgsFile(self):
    lines = ['# Generated from %r' % self.deps_file]
    variables = self.get_vars()
    for arg in self._gn_args:
      value = variables[arg]
      if isinstance(value, basestring):
        value = gclient_eval.EvaluateCondition(value, variables)
      lines.append('%s = %s' % (arg, ToGNString(value)))
    with open(os.path.join(self.root.root_dir, self._gn_args_file), 'w') as f:
      f.write('\n'.join(lines))

  @gclient_utils.lockedmethod
  def _run_is_done(self, file_list):
    # Both these are kept for hooks that are run as a separate tree traversal.
    self._file_list = file_list
    self._processed = True

  def GetHooks(self, options):
    """Evaluates all hooks, and return them in a flat list.

    RunOnDeps() must have been called before to load the DEPS.
    """
    result = []
    if not self.should_process or not self.should_recurse:
      # Don't run the hook when it is above recursion_limit.
      return result
    # If "--force" was specified, run all hooks regardless of what files have
    # changed.
    if self.deps_hooks:
      # TODO(maruel): If the user is using git, then we don't know
      # what files have changed so we always run all hooks. It'd be nice to fix
      # that.
      result.extend(self.deps_hooks)
    for s in self.dependencies:
      result.extend(s.GetHooks(options))
    return result

  def RunHooksRecursively(self, options, progress):
    assert self.hooks_ran == False
    self._hooks_ran = True
    hooks = self.GetHooks(options)
    if progress:
      progress._total = len(hooks)
    for hook in hooks:
      if progress:
        progress.update(extra=hook.name or '')
      hook.run()
    if progress:
      progress.end()

  def RunPreDepsHooks(self):
    assert self.processed
    assert self.deps_parsed
    assert not self.pre_deps_hooks_ran
    assert not self.hooks_ran
    for s in self.dependencies:
      assert not s.processed
    self._pre_deps_hooks_ran = True
    for hook in self.pre_deps_hooks:
      hook.run()

  def GetCipdRoot(self):
    if self.root is self:
      # Let's not infinitely recurse. If this is root and isn't an
      # instance of GClient, do nothing.
      return None
    return self.root.GetCipdRoot()

  def subtree(self, include_all):
    """Breadth first recursion excluding root node."""
    dependencies = self.dependencies
    for d in dependencies:
      if d.should_process or include_all:
        yield d
    for d in dependencies:
      for i in d.subtree(include_all):
        yield i

  @gclient_utils.lockedmethod
  def add_dependency(self, new_dep):
    self._dependencies.append(new_dep)

  @gclient_utils.lockedmethod
  def _mark_as_parsed(self, new_hooks):
    self._deps_hooks.extend(new_hooks)
    self._deps_parsed = True

  @property
  @gclient_utils.lockedmethod
  def dependencies(self):
    return tuple(self._dependencies)

  @property
  @gclient_utils.lockedmethod
  def deps_hooks(self):
    return tuple(self._deps_hooks)

  @property
  @gclient_utils.lockedmethod
  def pre_deps_hooks(self):
    return tuple(self._pre_deps_hooks)

  @property
  @gclient_utils.lockedmethod
  def deps_parsed(self):
    """This is purely for debugging purposes. It's not used anywhere."""
    return self._deps_parsed

  @property
  @gclient_utils.lockedmethod
  def processed(self):
    return self._processed

  @property
  @gclient_utils.lockedmethod
  def pre_deps_hooks_ran(self):
    return self._pre_deps_hooks_ran

  @property
  @gclient_utils.lockedmethod
  def hooks_ran(self):
    return self._hooks_ran

  @property
  @gclient_utils.lockedmethod
  def allowed_hosts(self):
    return self._allowed_hosts

  @property
  @gclient_utils.lockedmethod
  def file_list(self):
    return tuple(self._file_list)

  @property
  def used_scm(self):
    """SCMWrapper instance for this dependency or None if not processed yet."""
    return self._used_scm

  @property
  @gclient_utils.lockedmethod
  def got_revision(self):
    return self._got_revision

  @property
  def file_list_and_children(self):
    result = list(self.file_list)
    for d in self.dependencies:
      result.extend(d.file_list_and_children)
    return tuple(result)

  def __str__(self):
    out = []
    for i in ('name', 'url', 'custom_deps',
              'custom_vars', 'deps_hooks', 'file_list', 'should_process',
              'processed', 'hooks_ran', 'deps_parsed', 'requirements',
              'allowed_hosts'):
      # First try the native property if it exists.
      if hasattr(self, '_' + i):
        value = getattr(self, '_' + i, False)
      else:
        value = getattr(self, i, False)
      if value:
        out.append('%s: %s' % (i, value))

    for d in self.dependencies:
      out.extend(['  ' + x for x in str(d).splitlines()])
      out.append('')
    return '\n'.join(out)

  def __repr__(self):
    return '%s: %s' % (self.name, self.url)

  def hierarchy(self, include_url=True):
    """Returns a human-readable hierarchical reference to a Dependency."""
    def format_name(d):
      if include_url:
        return '%s(%s)' % (d.name, d.url)
      return d.name
    out = format_name(self)
    i = self.parent
    while i and i.name:
      out = '%s -> %s' % (format_name(i), out)
      i = i.parent
    return out

  def hierarchy_data(self):
    """Returns a machine-readable hierarchical reference to a Dependency."""
    d = self
    out = []
    while d and d.name:
      out.insert(0, (d.name, d.url))
      d = d.parent
    return tuple(out)

  def get_builtin_vars(self):
    return {
        'checkout_android': 'android' in self.target_os,
        'checkout_chromeos': 'chromeos' in self.target_os,
        'checkout_fuchsia': 'fuchsia' in self.target_os,
        'checkout_ios': 'ios' in self.target_os,
        'checkout_linux': 'unix' in self.target_os,
        'checkout_mac': 'mac' in self.target_os,
        'checkout_win': 'win' in self.target_os,
        'host_os': _detect_host_os(),

        'checkout_arm': 'arm' in self.target_cpu,
        'checkout_arm64': 'arm64' in self.target_cpu,
        'checkout_x86': 'x86' in self.target_cpu,
        'checkout_mips': 'mips' in self.target_cpu,
        'checkout_mips64': 'mips64' in self.target_cpu,
        'checkout_ppc': 'ppc' in self.target_cpu,
        'checkout_s390': 's390' in self.target_cpu,
        'checkout_x64': 'x64' in self.target_cpu,
        'host_cpu': detect_host_arch.HostArch(),
    }

  def get_vars(self):
    """Returns a dictionary of effective variable values
    (DEPS file contents with applied custom_vars overrides)."""
    # Variable precedence (last has highest):
    # - DEPS vars
    # - parents, from first to last
    # - built-in
    # - custom_vars overrides
    result = {}
    result.update(self._vars)
    if self.parent:
      parent_vars = self.parent.get_vars()
      result.update(parent_vars)
    # Provide some built-in variables.
    result.update(self.get_builtin_vars())
    result.update(self.custom_vars or {})
    return result


_PLATFORM_MAPPING = {
  'cygwin': 'win',
  'darwin': 'mac',
  'linux2': 'linux',
  'win32': 'win',
  'aix6': 'aix',
}


def _detect_host_os():
  return _PLATFORM_MAPPING[sys.platform]


class GitDependency(Dependency):
  """A Dependency object that represents a single git checkout."""

  #override
  def GetScmName(self):
    """Always 'git'."""
    return 'git'

  #override
  def CreateSCM(self, out_cb=None):
    """Create a Wrapper instance suitable for handling this git dependency."""
    return gclient_scm.GitWrapper(
        self.url, self.root.root_dir, self.name, self.outbuf, out_cb,
        print_outbuf=self.print_outbuf)


class GClient(GitDependency):
  """Object that represent a gclient checkout. A tree of Dependency(), one per
  solution or DEPS entry."""

  DEPS_OS_CHOICES = {
    "aix6": "unix",
    "win32": "win",
    "win": "win",
    "cygwin": "win",
    "darwin": "mac",
    "mac": "mac",
    "unix": "unix",
    "linux": "unix",
    "linux2": "unix",
    "linux3": "unix",
    "android": "android",
    "ios": "ios",
    "fuchsia": "fuchsia",
  }

  DEFAULT_CLIENT_FILE_TEXT = ("""\
solutions = [
  { "name"        : "%(solution_name)s",
    "url"         : "%(solution_url)s",
    "deps_file"   : "%(deps_file)s",
    "managed"     : %(managed)s,
    "custom_deps" : {
    },
    "custom_vars": %(custom_vars)r,
  },
]
""")

  DEFAULT_CLIENT_CACHE_DIR_TEXT = ("""\
cache_dir = %(cache_dir)r
""")


  DEFAULT_SNAPSHOT_FILE_TEXT = ("""\
# Snapshot generated with gclient revinfo --snapshot
solutions = %(solution_list)s
""")

  def __init__(self, root_dir, options):
    # Do not change previous behavior. Only solution level and immediate DEPS
    # are processed.
    self._recursion_limit = 2
    super(GClient, self).__init__(
        parent=None,
        name=None,
        url=None,
        managed=True,
        custom_deps=None,
        custom_vars=None,
        custom_hooks=None,
        deps_file='unused',
        should_process=True,
        should_recurse=True,
        relative=None,
        condition=None,
        print_outbuf=True)

    self._options = options
    if options.deps_os:
      enforced_os = options.deps_os.split(',')
    else:
      enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')]
    if 'all' in enforced_os:
      enforced_os = self.DEPS_OS_CHOICES.itervalues()
    self._enforced_os = tuple(set(enforced_os))
    self._enforced_cpu = detect_host_arch.HostArch(),
    self._root_dir = root_dir
    self._cipd_root = None
    self.config_content = None

  def _CheckConfig(self):
    """Verify that the config matches the state of the existing checked-out
    solutions."""
    for dep in self.dependencies:
      if dep.managed and dep.url:
        scm = dep.CreateSCM()
        actual_url = scm.GetActualRemoteURL(self._options)
        if actual_url and not scm.DoesRemoteURLMatch(self._options):
          mirror = scm.GetCacheMirror()
          if mirror:
            mirror_string = '%s (exists=%s)' % (mirror.mirror_path,
                                                mirror.exists())
          else:
            mirror_string = 'not used'
          raise gclient_utils.Error('''
Your .gclient file seems to be broken. The requested URL is different from what
is actually checked out in %(checkout_path)s.

The .gclient file contains:
URL: %(expected_url)s (%(expected_scm)s)
Cache mirror: %(mirror_string)s

The local checkout in %(checkout_path)s reports:
%(actual_url)s (%(actual_scm)s)

You should ensure that the URL listed in .gclient is correct and either change
it or fix the checkout.
'''  % {'checkout_path': os.path.join(self.root_dir, dep.name),
        'expected_url': dep.url,
        'expected_scm': dep.GetScmName(),
        'mirror_string' : mirror_string,
        'actual_url': actual_url,
        'actual_scm': dep.GetScmName()})

  def SetConfig(self, content):
    assert not self.dependencies
    config_dict = {}
    self.config_content = content
    try:
      exec(content, config_dict)
    except SyntaxError as e:
      gclient_utils.SyntaxErrorToError('.gclient', e)

    # Append any target OS that is not already being enforced to the tuple.
    target_os = config_dict.get('target_os', [])
    if config_dict.get('target_os_only', False):
      self._enforced_os = tuple(set(target_os))
    else:
      self._enforced_os = tuple(set(self._enforced_os).union(target_os))

    # Append any target CPU that is not already being enforced to the tuple.
    target_cpu = config_dict.get('target_cpu', [])
    if config_dict.get('target_cpu_only', False):
      self._enforced_cpu = tuple(set(target_cpu))
    else:
      self._enforced_cpu = tuple(set(self._enforced_cpu).union(target_cpu))

    cache_dir = config_dict.get('cache_dir', UNSET_CACHE_DIR)
    if cache_dir is not UNSET_CACHE_DIR:
      if cache_dir:
        cache_dir = os.path.join(self.root_dir, cache_dir)
        cache_dir = os.path.abspath(cache_dir)

      git_cache.Mirror.SetCachePath(cache_dir)

    if not target_os and config_dict.get('target_os_only', False):
      raise gclient_utils.Error('Can\'t use target_os_only if target_os is '
                                'not specified')

    if not target_cpu and config_dict.get('target_cpu_only', False):
      raise gclient_utils.Error('Can\'t use target_cpu_only if target_cpu is '
                                'not specified')

    deps_to_add = []
    for s in config_dict.get('solutions', []):
      try:
        deps_to_add.append(GitDependency(
            parent=self,
            name=s['name'],
            url=s['url'],
            managed=s.get('managed', True),
            custom_deps=s.get('custom_deps', {}),
            custom_vars=s.get('custom_vars', {}),
            custom_hooks=s.get('custom_hooks', []),
            deps_file=s.get('deps_file', 'DEPS'),
            should_process=True,
            should_recurse=True,
            relative=None,
            condition=None,
            print_outbuf=True))
      except KeyError:
        raise gclient_utils.Error('Invalid .gclient file. Solution is '
                                  'incomplete: %s' % s)
    metrics.collector.add(
        'project_urls',
        [
            dep.url if not dep.url.endswith('.git') else dep.url[:-len('.git')]
            for dep in deps_to_add
            if dep.FuzzyMatchUrl(metrics_utils.KNOWN_PROJECT_URLS)
        ]
    )

    self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', []))
    logging.info('SetConfig() done')

  def SaveConfig(self):
    gclient_utils.FileWrite(os.path.join(self.root_dir,
                                         self._options.config_filename),
                            self.config_content)

  @staticmethod
  def LoadCurrentConfig(options):
    """Searches for and loads a .gclient file relative to the current working
    dir. Returns a GClient object."""
    if options.spec:
      client = GClient('.', options)
      client.SetConfig(options.spec)
    else:
      if options.verbose:
        print('Looking for %s starting from %s\n' % (
            options.config_filename, os.getcwd()))
      path = gclient_utils.FindGclientRoot(os.getcwd(), options.config_filename)
      if not path:
        if options.verbose:
          print('Couldn\'t find configuration file.')
        return None
      client = GClient(path, options)
      client.SetConfig(gclient_utils.FileRead(
          os.path.join(path, options.config_filename)))

    if (options.revisions and
        len(client.dependencies) > 1 and
        any('@' not in r for r in options.revisions)):
      print(
          ('You must specify the full solution name like --revision %s@%s\n'
           'when you have multiple solutions setup in your .gclient file.\n'
           'Other solutions present are: %s.') % (
              client.dependencies[0].name,
              options.revisions[0],
              ', '.join(s.name for s in client.dependencies[1:])),
          file=sys.stderr)
    return client

  def SetDefaultConfig(self, solution_name, deps_file, solution_url,
                       managed=True, cache_dir=UNSET_CACHE_DIR,
                       custom_vars=None):
    text = self.DEFAULT_CLIENT_FILE_TEXT
    format_dict = {
      'solution_name': solution_name,
      'solution_url': solution_url,
      'deps_file': deps_file,
      'managed': managed,
      'custom_vars': custom_vars or {},
    }

    if cache_dir is not UNSET_CACHE_DIR:
      text += self.DEFAULT_CLIENT_CACHE_DIR_TEXT
      format_dict['cache_dir'] = cache_dir

    self.SetConfig(text % format_dict)

  def _SaveEntries(self):
    """Creates a .gclient_entries file to record the list of unique checkouts.

    The .gclient_entries file lives in the same directory as .gclient.
    """
    # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It
    # makes testing a bit too fun.
    result = 'entries = {\n'
    for entry in self.root.subtree(False):
      result += '  %s: %s,\n' % (pprint.pformat(entry.name),
          pprint.pformat(entry.url))
    result += '}\n'
    file_path = os.path.join(self.root_dir, self._options.entries_filename)
    logging.debug(result)
    gclient_utils.FileWrite(file_path, result)

  def _ReadEntries(self):
    """Read the .gclient_entries file for the given client.

    Returns:
      A sequence of solution names, which will be empty if there is the
      entries file hasn't been created yet.
    """
    scope = {}
    filename = os.path.join(self.root_dir, self._options.entries_filename)
    if not os.path.exists(filename):
      return {}
    try:
      exec(gclient_utils.FileRead(filename), scope)
    except SyntaxError as e:
      gclient_utils.SyntaxErrorToError(filename, e)
    return scope.get('entries', {})

  def _EnforceRevisions(self):
    """Checks for revision overrides."""
    revision_overrides = {}
    if self._options.head:
      return revision_overrides
    if not self._options.revisions:
      return revision_overrides
    solutions_names = [s.name for s in self.dependencies]
    index = 0
    for revision in self._options.revisions:
      if not '@' in revision:
        # Support for --revision 123
        revision = '%s@%s' % (solutions_names[index], revision)
      name, rev = revision.split('@', 1)
      revision_overrides[name] = rev
      index += 1
    return revision_overrides

  def _EnforcePatchRefsAndBranches(self):
    """Checks for patch refs."""
    patch_refs = {}
    target_branches = {}
    if not self._options.patch_refs:
      return patch_refs, target_branches
    for given_patch_ref in self._options.patch_refs:
      patch_repo, _, patch_ref = given_patch_ref.partition('@')
      if not patch_repo or not patch_ref:
        raise gclient_utils.Error(
            'Wrong revision format: %s should be of the form '
            'patch_repo@[target_branch:]patch_ref.' % given_patch_ref)
      if ':' in patch_ref:
        target_branch, _, patch_ref = patch_ref.partition(':')
        target_branches[patch_repo] = target_branch
      patch_refs[patch_repo] = patch_ref
    return patch_refs, target_branches

  def _RemoveUnversionedGitDirs(self):
    """Remove directories that are no longer part of the checkout.

    Notify the user if there is an orphaned entry in their working copy.
    Only delete the directory if there are no changes in it, and
    delete_unversioned_trees is set to true.
    """

    entries = [i.name for i in self.root.subtree(False) if i.url]
    full_entries = [os.path.join(self.root_dir, e.replace('/', os.path.sep))
                    for e in entries]

    for entry, prev_url in self._ReadEntries().iteritems():
      if not prev_url:
        # entry must have been overridden via .gclient custom_deps
        continue
      # Fix path separator on Windows.
      entry_fixed = entry.replace('/', os.path.sep)
      e_dir = os.path.join(self.root_dir, entry_fixed)
      # Use entry and not entry_fixed there.
      if (entry not in entries and
          (not any(path.startswith(entry + '/') for path in entries)) and
          os.path.exists(e_dir)):
        # The entry has been removed from DEPS.
        scm = gclient_scm.GitWrapper(
            prev_url, self.root_dir, entry_fixed, self.outbuf)

        # Check to see if this directory is now part of a higher-up checkout.
        scm_root = None
        try:
          scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(scm.checkout_path)
        except subprocess2.CalledProcessError:
          pass
        if not scm_root:
          logging.warning('Could not find checkout root for %s. Unable to '
                          'determine whether it is part of a higher-level '
                          'checkout, so not removing.' % entry)
          continue

        # This is to handle the case of third_party/WebKit migrating from
        # being a DEPS entry to being part of the main project.
        # If the subproject is a Git project, we need to remove its .git
        # folder. Otherwise git operations on that folder will have different
        # effects depending on the current working directory.
        if os.path.abspath(scm_root) == os.path.abspath(e_dir):
          e_par_dir = os.path.join(e_dir, os.pardir)
          if gclient_scm.scm.GIT.IsInsideWorkTree(e_par_dir):
            par_scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(e_par_dir)
            # rel_e_dir : relative path of entry w.r.t. its parent repo.
            rel_e_dir = os.path.relpath(e_dir, par_scm_root)
            if gclient_scm.scm.GIT.IsDirectoryVersioned(
                par_scm_root, rel_e_dir):
              save_dir = scm.GetGitBackupDirPath()
              # Remove any eventual stale backup dir for the same project.
              if os.path.exists(save_dir):
                gclient_utils.rmtree(save_dir)
              os.rename(os.path.join(e_dir, '.git'), save_dir)
              # When switching between the two states (entry/ is a subproject
              # -> entry/ is part of the outer project), it is very likely
              # that some files are changed in the checkout, unless we are
              # jumping *exactly* across the commit which changed just DEPS.
              # In such case we want to cleanup any eventual stale files
              # (coming from the old subproject) in order to end up with a
              # clean checkout.
              gclient_scm.scm.GIT.CleanupDir(par_scm_root, rel_e_dir)
              assert not os.path.exists(os.path.join(e_dir, '.git'))
              print(('\nWARNING: \'%s\' has been moved from DEPS to a higher '
                     'level checkout. The git folder containing all the local'
                     ' branches has been saved to %s.\n'
                     'If you don\'t care about its state you can safely '
                     'remove that folder to free up space.') %
                    (entry, save_dir))
              continue

        if scm_root in full_entries:
          logging.info('%s is part of a higher level checkout, not removing',
                       scm.GetCheckoutRoot())
          continue

        file_list = []
        scm.status(self._options, [], file_list)
        modified_files = file_list != []
        if (not self._options.delete_unversioned_trees or
            (modified_files and not self._options.force)):
          # There are modified files in this entry. Keep warning until
          # removed.
          print(('\nWARNING: \'%s\' is no longer part of this client.  '
                 'It is recommended that you manually remove it.\n') %
                    entry_fixed)
        else:
          # Delete the entry
          print('\n________ deleting \'%s\' in \'%s\'' % (
              entry_fixed, self.root_dir))
          gclient_utils.rmtree(e_dir)
    # record the current list of entries for next time
    self._SaveEntries()

  def RunOnDeps(self, command, args, ignore_requirements=False, progress=True):
    """Runs a command on each dependency in a client and its dependencies.

    Args:
      command: The command to use (e.g., 'status' or 'diff')
      args: list of str - extra arguments to add to the command line.
    """
    if not self.dependencies:
      raise gclient_utils.Error('No solution specified')

    revision_overrides = {}
    patch_refs = {}
    target_branches = {}
    # It's unnecessary to check for revision overrides for 'recurse'.
    # Save a few seconds by not calling _EnforceRevisions() in that case.
    if command not in ('diff', 'recurse', 'runhooks', 'status', 'revert',
                       'validate'):
      self._CheckConfig()
      revision_overrides = self._EnforceRevisions()

    if command == 'update':
      patch_refs, target_branches = self._EnforcePatchRefsAndBranches()
    # Disable progress for non-tty stdout.
    should_show_progress = (
        setup_color.IS_TTY and not self._options.verbose and progress)
    pm = None
    if should_show_progress:
      if command in ('update', 'revert'):
        pm = Progress('Syncing projects', 1)
      elif command in ('recurse', 'validate'):
        pm = Progress(' '.join(args), 1)
    work_queue = gclient_utils.ExecutionQueue(
        self._options.jobs, pm, ignore_requirements=ignore_requirements,
        verbose=self._options.verbose)
    for s in self.dependencies:
      if s.should_process:
        work_queue.enqueue(s)
    work_queue.flush(revision_overrides, command, args, options=self._options,
                     patch_refs=patch_refs, target_branches=target_branches)

    if revision_overrides:
      print('Please fix your script, having invalid --revision flags will soon '
            'be considered an error.', file=sys.stderr)

    if patch_refs:
      raise gclient_utils.Error(
          'The following --patch-ref flags were not used. Please fix it:\n%s' %
          ('\n'.join(
              patch_repo + '@' + patch_ref
              for patch_repo, patch_ref in patch_refs.iteritems())))

    # Once all the dependencies have been processed, it's now safe to write
    # out the gn_args_file and run the hooks.
    if command == 'update':
      gn_args_dep = self.dependencies[0]
      if gn_args_dep._gn_args_from:
        deps_map = dict([(dep.name, dep) for dep in gn_args_dep.dependencies])
        gn_args_dep = deps_map.get(gn_args_dep._gn_args_from)
      if gn_args_dep and gn_args_dep.HasGNArgsFile():
        gn_args_dep.WriteGNArgsFile()

      self._RemoveUnversionedGitDirs()

    # Sync CIPD dependencies once removed deps are deleted. In case a git
    # dependency was moved to CIPD, we want to remove the old git directory
    # first and then sync the CIPD dep.
    if self._cipd_root:
      self._cipd_root.run(command)

    if not self._options.nohooks:
      if should_show_progress:
        pm = Progress('Running hooks', 1)
      self.RunHooksRecursively(self._options, pm)


    return 0

  def PrintRevInfo(self):
    if not self.dependencies:
      raise gclient_utils.Error('No solution specified')
    # Load all the settings.
    work_queue = gclient_utils.ExecutionQueue(
        self._options.jobs, None, False, verbose=self._options.verbose)
    for s in self.dependencies:
      if s.should_process:
        work_queue.enqueue(s)
    work_queue.flush({}, None, [], options=self._options, patch_refs=None,
                     target_branches=None)

    def ShouldPrintRevision(dep):
      return (not self._options.filter
              or dep.FuzzyMatchUrl(self._options.filter))

    if self._options.snapshot:
      json_output = []
      # First level at .gclient
      for d in self.dependencies:
        entries = {}
        def GrabDeps(dep):
          """Recursively grab dependencies."""
          for d in dep.dependencies:
            d.PinToActualRevision()
            if ShouldPrintRevision(d):
              entries[d.name] = d.url
            GrabDeps(d)
        GrabDeps(d)
        json_output.append({
            'name': d.name,
            'solution_url': d.url,
            'deps_file': d.deps_file,
            'managed': d.managed,
            'custom_deps': entries,
        })
      if self._options.output_json == '-':
        print(json.dumps(json_output, indent=2, separators=(',', ': ')))
      elif self._options.output_json:
        with open(self._options.output_json, 'w') as f:
          json.dump(json_output, f)
      else:
        # Print the snapshot configuration file
        print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {
            'solution_list': pprint.pformat(json_output, indent=2),
        })
    else:
      entries = {}
      for d in self.root.subtree(False):
        if self._options.actual:
          d.PinToActualRevision()
        if ShouldPrintRevision(d):
          entries[d.name] = d.url
      if self._options.output_json:
        json_output = {
            name: {
                'url': rev.split('@')[0] if rev else None,
                'rev': rev.split('@')[1] if rev and '@' in rev else None,
            }
            for name, rev in entries.iteritems()
        }
        if self._options.output_json == '-':
          print(json.dumps(json_output, indent=2, separators=(',', ': ')))
        else:
          with open(self._options.output_json, 'w') as f:
            json.dump(json_output, f)
      else:
        keys = sorted(entries.keys())
        for x in keys:
          print('%s: %s' % (x, entries[x]))
    logging.info(str(self))

  def ParseDepsFile(self):
    """No DEPS to parse for a .gclient file."""
    raise gclient_utils.Error('Internal error')

  def PrintLocationAndContents(self):
    # 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.
    print('Loaded .gclient config in %s:\n%s' % (
        self.root_dir, self.config_content))

  def GetCipdRoot(self):
    if not self._cipd_root:
      self._cipd_root = gclient_scm.CipdRoot(
          self.root_dir,
          # TODO(jbudorick): Support other service URLs as necessary.
          # Service URLs should be constant over the scope of a cipd
          # root, so a var per DEPS file specifying the service URL
          # should suffice.
          'https://chrome-infra-packages.appspot.com')
    return self._cipd_root

  @property
  def root_dir(self):
    """Root directory of gclient checkout."""
    return self._root_dir

  @property
  def enforced_os(self):
    """What deps_os entries that are to be parsed."""
    return self._enforced_os

  @property
  def target_os(self):
    return self._enforced_os

  @property
  def target_cpu(self):
    return self._enforced_cpu


class CipdDependency(Dependency):
  """A Dependency object that represents a single CIPD package."""

  def __init__(
      self, parent, name, dep_value, cipd_root,
      custom_vars, should_process, relative, condition):
    package = dep_value['package']
    version = dep_value['version']
    url = urlparse.urljoin(
        cipd_root.service_url, '%s@%s' % (package, version))
    super(CipdDependency, self).__init__(
        parent=parent,
        name=name + ':' + package,
        url=url,
        managed=None,
        custom_deps=None,
        custom_vars=custom_vars,
        custom_hooks=None,
        deps_file=None,
        should_process=should_process,
        should_recurse=False,
        relative=relative,
        condition=condition)
    if relative:
      # TODO(jbudorick): Implement relative if necessary.
      raise gclient_utils.Error(
          'Relative CIPD dependencies are not currently supported.')
    self._cipd_package = None
    self._cipd_root = cipd_root
    # CIPD wants /-separated paths, even on Windows.
    native_subdir_path = os.path.relpath(
        os.path.join(self.root.root_dir, name), cipd_root.root_dir)
    self._cipd_subdir = posixpath.join(*native_subdir_path.split(os.sep))
    self._package_name = package
    self._package_version = version

  #override
  def run(self, revision_overrides, command, args, work_queue, options,
          patch_refs, target_branches):
    """Runs |command| then parse the DEPS file."""
    logging.info('CipdDependency(%s).run()' % self.name)
    if not self.should_process:
      return
    self._CreatePackageIfNecessary()
    super(CipdDependency, self).run(revision_overrides, command, args,
                                    work_queue, options, patch_refs,
                                    target_branches)

  def _CreatePackageIfNecessary(self):
    # We lazily create the CIPD package to make sure that only packages
    # that we want (as opposed to all packages defined in all DEPS files
    # we parse) get added to the root and subsequently ensured.
    if not self._cipd_package:
      self._cipd_package = self._cipd_root.add_package(
          self._cipd_subdir, self._package_name, self._package_version)

  def ParseDepsFile(self):
    """CIPD dependencies are not currently allowed to have nested deps."""
    self.add_dependencies_and_close([], [])

  #override
  def verify_validity(self):
    """CIPD dependencies allow duplicate name for packages in same directory."""
    logging.info('Dependency(%s).verify_validity()' % self.name)
    return True

  #override
  def GetScmName(self):
    """Always 'cipd'."""
    return 'cipd'

  #override
  def CreateSCM(self, out_cb=None):
    """Create a Wrapper instance suitable for handling this CIPD dependency."""
    self._CreatePackageIfNecessary()
    return gclient_scm.CipdWrapper(
        self.url, self.root.root_dir, self.name, self.outbuf, out_cb,
        root=self._cipd_root, package=self._cipd_package)

  def hierarchy(self, include_url=False):
    return self.parent.hierarchy(include_url) + ' -> ' + self._cipd_subdir

  def ToLines(self):
    """Return a list of lines representing this in a DEPS file."""
    def escape_cipd_var(package):
      return package.replace('{', '{{').replace('}', '}}')

    s = []
    self._CreatePackageIfNecessary()
    if self._cipd_package.authority_for_subdir:
      condition_part = (['    "condition": %r,' % self.condition]
                        if self.condition else [])
      s.extend([
          '  # %s' % self.hierarchy(include_url=False),
          '  "%s": {' % (self.name.split(':')[0],),
          '    "packages": [',
      ])
      for p in sorted(
          self._cipd_root.packages(self._cipd_subdir),
          cmp=lambda x, y: cmp(x.name, y.name)):
        s.extend([
            '      {',
            '        "package": "%s",' % escape_cipd_var(p.name),
            '        "version": "%s",' % p.version,
            '      },',
        ])

      s.extend([
          '    ],',
          '    "dep_type": "cipd",',
      ] + condition_part + [
          '  },',
          '',
      ])
    return s


#### gclient commands.


@subcommand.usage('[command] [args ...]')
@metrics.collector.collect_metrics('gclient recurse')
def CMDrecurse(parser, args):
  """Operates [command args ...] on all the dependencies.

  Runs a shell command on all entries.
  Sets GCLIENT_DEP_PATH environment variable as the dep's relative location to
  root directory of the checkout.
  """
  # Stop parsing at the first non-arg so that these go through to the command
  parser.disable_interspersed_args()
  parser.add_option('-s', '--scm', action='append', default=[],
                    help='Choose scm types to operate upon.')
  parser.add_option('-i', '--ignore', action='store_true',
                    help='Ignore non-zero return codes from subcommands.')
  parser.add_option('--prepend-dir', action='store_true',
                    help='Prepend relative dir for use with git <cmd> --null.')
  parser.add_option('--no-progress', action='store_true',
                    help='Disable progress bar that shows sub-command updates')
  options, args = parser.parse_args(args)
  if not args:
    print('Need to supply a command!', file=sys.stderr)
    return 1
  root_and_entries = gclient_utils.GetGClientRootAndEntries()
  if not root_and_entries:
    print(
        'You need to run gclient sync at least once to use \'recurse\'.\n'
        'This is because .gclient_entries needs to exist and be up to date.',
        file=sys.stderr)
    return 1

  # Normalize options.scm to a set()
  scm_set = set()
  for scm in options.scm:
    scm_set.update(scm.split(','))
  options.scm = scm_set

  options.nohooks = True
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  return client.RunOnDeps('recurse', args, ignore_requirements=True,
                          progress=not options.no_progress)


@subcommand.usage('[args ...]')
@metrics.collector.collect_metrics('gclient fetch')
def CMDfetch(parser, args):
  """Fetches upstream commits for all modules.

  Completely git-specific. Simply runs 'git fetch [args ...]' for each module.
  """
  (options, args) = parser.parse_args(args)
  return CMDrecurse(OptionParser(), [
      '--jobs=%d' % options.jobs, '--scm=git', 'git', 'fetch'] + args)


class Flattener(object):
  """Flattens a gclient solution."""

  def __init__(self, client, pin_all_deps=False):
    """Constructor.

    Arguments:
      client (GClient): client to flatten
      pin_all_deps (bool): whether to pin all deps, even if they're not pinned
          in DEPS
    """
    self._client = client

    self._deps_string = None
    self._deps_files = set()

    self._allowed_hosts = set()
    self._deps = {}
    self._hooks = []
    self._pre_deps_hooks = []
    self._vars = {}

    self._flatten(pin_all_deps=pin_all_deps)

  @property
  def deps_string(self):
    assert self._deps_string is not None
    return self._deps_string

  @property
  def deps_files(self):
    return self._deps_files

  def _pin_dep(self, dep):
    """Pins a dependency to specific full revision sha.

    Arguments:
      dep (Dependency): dependency to process
    """
    if dep.url is None:
      return

    # Make sure the revision is always fully specified (a hash),
    # as opposed to refs or tags which might change. Similarly,
    # shortened shas might become ambiguous; make sure to always
    # use full one for pinning.
    revision = gclient_utils.SplitUrlRevision(dep.url)[1]
    if not revision or not gclient_utils.IsFullGitSha(revision):
      dep.PinToActualRevision()

  def _flatten(self, pin_all_deps=False):
    """Runs the flattener. Saves resulting DEPS string.

    Arguments:
      pin_all_deps (bool): whether to pin all deps, even if they're not pinned
          in DEPS
    """
    for solution in self._client.dependencies:
      self._add_dep(solution)
      self._flatten_dep(solution)

    if pin_all_deps:
      for dep in self._deps.itervalues():
        self._pin_dep(dep)

    def add_deps_file(dep):
      # Only include DEPS files referenced by recursedeps.
      if not dep.should_recurse:
        return
      deps_file = dep.deps_file
      deps_path = os.path.join(self._client.root_dir, dep.name, deps_file)
      if not os.path.exists(deps_path):
        # gclient has a fallback that if deps_file doesn't exist, it'll try
        # DEPS. Do the same here.
        deps_file = 'DEPS'
        deps_path = os.path.join(self._client.root_dir, dep.name, deps_file)
        if not os.path.exists(deps_path):
          return
      assert dep.url
      self._deps_files.add((dep.url, deps_file, dep.hierarchy_data()))
    for dep in self._deps.itervalues():
      add_deps_file(dep)

    gn_args_dep = self._deps.get(self._client.dependencies[0]._gn_args_from,
                                 self._client.dependencies[0])
    self._deps_string = '\n'.join(
        _GNSettingsToLines(gn_args_dep._gn_args_file, gn_args_dep._gn_args) +
        _AllowedHostsToLines(self._allowed_hosts) +
        _DepsToLines(self._deps) +
        _HooksToLines('hooks', self._hooks) +
        _HooksToLines('pre_deps_hooks', self._pre_deps_hooks) +
        _VarsToLines(self._vars) +
        ['# %s, %s' % (url, deps_file)
         for url, deps_file, _ in sorted(self._deps_files)] +
        [''])  # Ensure newline at end of file.

  def _add_dep(self, dep):
    """Helper to add a dependency to flattened DEPS.

    Arguments:
      dep (Dependency): dependency to add
    """
    assert dep.name not in self._deps or self._deps.get(dep.name) == dep, (
        dep.name, self._deps.get(dep.name))
    if dep.url:
      self._deps[dep.name] = dep

  def _flatten_dep(self, dep):
    """Visits a dependency in order to flatten it (see CMDflatten).

    Arguments:
      dep (Dependency): dependency to process
    """
    logging.debug('_flatten_dep(%s)', dep.name)

    assert dep.deps_parsed, (
        "Attempted to flatten %s but it has not been processed." % dep.name)

    self._allowed_hosts.update(dep.allowed_hosts)

    # Only include vars explicitly listed in the DEPS files or gclient solution,
    # not automatic, local overrides (i.e. not all of dep.get_vars()).
    hierarchy = dep.hierarchy(include_url=False)
    for key, value in dep._vars.iteritems():
      # Make sure there are no conflicting variables. It is fine however
      # to use same variable name, as long as the value is consistent.
      assert key not in self._vars or self._vars[key][1] == value
      self._vars[key] = (hierarchy, value)
    # Override explicit custom variables.
    for key, value in dep.custom_vars.iteritems():
      # Do custom_vars that don't correspond to DEPS vars ever make sense? DEPS
      # conditionals shouldn't be using vars that aren't also defined in the
      # DEPS (presubmit actually disallows this), so any new custom_var must be
      # unused in the DEPS, so no need to add it to the flattened output either.
      if key not in self._vars:
        continue
      # Don't "override" existing vars if it's actually the same value.
      elif self._vars[key][1] == value:
        continue
      # Anything else is overriding a default value from the DEPS.
      self._vars[key] = (hierarchy + ' [custom_var override]', value)

    self._pre_deps_hooks.extend([(dep, hook) for hook in dep.pre_deps_hooks])
    self._hooks.extend([(dep, hook) for hook in dep.deps_hooks])

    for sub_dep in dep.dependencies:
      self._add_dep(sub_dep)

    for d in dep.dependencies:
      if d.should_recurse:
        self._flatten_dep(d)


@metrics.collector.collect_metrics('gclient flatten')
def CMDflatten(parser, args):
  """Flattens the solutions into a single DEPS file."""
  parser.add_option('--output-deps', help='Path to the output DEPS file')
  parser.add_option(
      '--output-deps-files',
      help=('Path to the output metadata about DEPS files referenced by '
            'recursedeps.'))
  parser.add_option(
      '--pin-all-deps', action='store_true',
      help=('Pin all deps, even if not pinned in DEPS. CAVEAT: only does so '
            'for checked out deps, NOT deps_os.'))
  options, args = parser.parse_args(args)

  options.nohooks = True
  options.process_all_deps = True
  client = GClient.LoadCurrentConfig(options)

  # Only print progress if we're writing to a file. Otherwise, progress updates
  # could obscure intended output.
  code = client.RunOnDeps('flatten', args, progress=options.output_deps)
  if code != 0:
    return code

  flattener = Flattener(client, pin_all_deps=options.pin_all_deps)

  if options.output_deps:
    with open(options.output_deps, 'w') as f:
      f.write(flattener.deps_string)
  else:
    print(flattener.deps_string)

  deps_files = [{'url': d[0], 'deps_file': d[1], 'hierarchy': d[2]}
                for d in sorted(flattener.deps_files)]
  if options.output_deps_files:
    with open(options.output_deps_files, 'w') as f:
      json.dump(deps_files, f)

  return 0


def _GNSettingsToLines(gn_args_file, gn_args):
  s = []
  if gn_args_file:
    s.extend([
        'gclient_gn_args_file = "%s"' % gn_args_file,
        'gclient_gn_args = %r' % gn_args,
    ])
  return s


def _AllowedHostsToLines(allowed_hosts):
  """Converts |allowed_hosts| set to list of lines for output."""
  if not allowed_hosts:
    return []
  s = ['allowed_hosts = [']
  for h in sorted(allowed_hosts):
    s.append('  "%s",' % h)
  s.extend([']', ''])
  return s


def _DepsToLines(deps):
  """Converts |deps| dict to list of lines for output."""
  if not deps:
    return []
  s = ['deps = {']
  for _, dep in sorted(deps.iteritems()):
    s.extend(dep.ToLines())
  s.extend(['}', ''])
  return s


def _DepsOsToLines(deps_os):
  """Converts |deps_os| dict to list of lines for output."""
  if not deps_os:
    return []
  s = ['deps_os = {']
  for dep_os, os_deps in sorted(deps_os.iteritems()):
    s.append('  "%s": {' % dep_os)
    for name, dep in sorted(os_deps.iteritems()):
      condition_part = (['      "condition": %r,' % dep.condition]
                        if dep.condition else [])
      s.extend([
          '    # %s' % dep.hierarchy(include_url=False),
          '    "%s": {' % (name,),
          '      "url": "%s",' % (dep.url,),
      ] + condition_part + [
          '    },',
          '',
      ])
    s.extend(['  },', ''])
  s.extend(['}', ''])
  return s


def _HooksToLines(name, hooks):
  """Converts |hooks| list to list of lines for output."""
  if not hooks:
    return []
  s = ['%s = [' % name]
  for dep, hook in hooks:
    s.extend([
        '  # %s' % dep.hierarchy(include_url=False),
        '  {',
    ])
    if hook.name is not None:
      s.append('    "name": "%s",' % hook.name)
    if hook.pattern is not None:
      s.append('    "pattern": "%s",' % hook.pattern)
    if hook.condition is not None:
      s.append('    "condition": %r,' % hook.condition)
    # Flattened hooks need to be written relative to the root gclient dir
    cwd = os.path.relpath(os.path.normpath(hook.effective_cwd))
    s.extend(
        ['    "cwd": "%s",' % cwd] +
        ['    "action": ['] +
        ['        "%s",' % arg for arg in hook.action] +
        ['    ]', '  },', '']
    )
  s.extend([']', ''])
  return s


def _HooksOsToLines(hooks_os):
  """Converts |hooks| list to list of lines for output."""
  if not hooks_os:
    return []
  s = ['hooks_os = {']
  for hook_os, os_hooks in hooks_os.iteritems():
    s.append('  "%s": [' % hook_os)
    for dep, hook in os_hooks:
      s.extend([
          '    # %s' % dep.hierarchy(include_url=False),
          '    {',
      ])
      if hook.name is not None:
        s.append('      "name": "%s",' % hook.name)
      if hook.pattern is not None:
        s.append('      "pattern": "%s",' % hook.pattern)
      if hook.condition is not None:
        s.append('    "condition": %r,' % hook.condition)
      # Flattened hooks need to be written relative to the root gclient dir
      cwd = os.path.relpath(os.path.normpath(hook.effective_cwd))
      s.extend(
          ['    "cwd": "%s",' % cwd] +
          ['      "action": ['] +
          ['          "%s",' % arg for arg in hook.action] +
          ['      ]', '    },', '']
      )
    s.extend(['  ],', ''])
  s.extend(['}', ''])
  return s


def _VarsToLines(variables):
  """Converts |variables| dict to list of lines for output."""
  if not variables:
    return []
  s = ['vars = {']
  for key, tup in sorted(variables.iteritems()):
    hierarchy, value = tup
    s.extend([
        '  # %s' % hierarchy,
        '  "%s": %r,' % (key, value),
        '',
    ])
  s.extend(['}', ''])
  return s


@metrics.collector.collect_metrics('gclient grep')
def CMDgrep(parser, args):
  """Greps through git repos managed by gclient.

  Runs 'git grep [args...]' for each module.
  """
  # We can't use optparse because it will try to parse arguments sent
  # to git grep and throw an error. :-(
  if not args or re.match('(-h|--help)$', args[0]):
    print(
        'Usage: gclient grep [-j <N>] git-grep-args...\n\n'
        'Example: "gclient grep -j10 -A2 RefCountedBase" runs\n"git grep '
        '-A2 RefCountedBase" on each of gclient\'s git\nrepos with up to '
        '10 jobs.\n\nBonus: page output by appending "|& less -FRSX" to the'
        ' end of your query.',
        file=sys.stderr)
    return 1

  jobs_arg = ['--jobs=1']
  if re.match(r'(-j|--jobs=)\d+$', args[0]):
    jobs_arg, args = args[:1], args[1:]
  elif re.match(r'(-j|--jobs)$', args[0]):
    jobs_arg, args = args[:2], args[2:]

  return CMDrecurse(
      parser,
      jobs_arg + ['--ignore', '--prepend-dir', '--no-progress', '--scm=git',
                  'git', 'grep', '--null', '--color=Always'] + args)


@metrics.collector.collect_metrics('gclient root')
def CMDroot(parser, args):
  """Outputs the solution root (or current dir if there isn't one)."""
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)
  if client:
    print(os.path.abspath(client.root_dir))
  else:
    print(os.path.abspath('.'))


@subcommand.usage('[url]')
@metrics.collector.collect_metrics('gclient config')
def CMDconfig(parser, args):
  """Creates 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.
  """
  # We do a little dance with the --gclientfile option.  'gclient config' is the
  # only command where it's acceptable to have both '--gclientfile' and '--spec'
  # arguments.  So, we temporarily stash any --gclientfile parameter into
  # options.output_config_file until after the (gclientfile xor spec) error
  # check.
  parser.remove_option('--gclientfile')
  parser.add_option('--gclientfile', dest='output_config_file',
                    help='Specify an alternate .gclient file')
  parser.add_option('--name',
                    help='overrides the default name for the solution')
  parser.add_option('--deps-file', default='DEPS',
                    help='overrides the default name for the DEPS file for the '
                         'main solutions and all sub-dependencies')
  parser.add_option('--unmanaged', action='store_true', default=False,
                    help='overrides the default behavior to make it possible '
                         'to have the main solution untouched by gclient '
                         '(gclient will check out unmanaged dependencies but '
                         'will never sync them)')
  parser.add_option('--cache-dir', default=UNSET_CACHE_DIR,
                    help='Cache all git repos into this dir and do shared '
                         'clones from the cache, instead of cloning directly '
                         'from the remote. Pass "None" to disable cache, even '
                         'if globally enabled due to $GIT_CACHE_PATH.')
  parser.add_option('--custom-var', action='append', dest='custom_vars',
                    default=[],
                    help='overrides variables; key=value syntax')
  parser.set_defaults(config_filename=None)
  (options, args) = parser.parse_args(args)
  if options.output_config_file:
    setattr(options, 'config_filename', getattr(options, 'output_config_file'))
  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 (options.cache_dir is not UNSET_CACHE_DIR
      and options.cache_dir.lower() == 'none'):
    options.cache_dir = None

  custom_vars = {}
  for arg in options.custom_vars:
    kv = arg.split('=', 1)
    if len(kv) != 2:
      parser.error('Invalid --custom-var argument: %r' % arg)
    custom_vars[kv[0]] = gclient_eval.EvaluateCondition(kv[1], {})

  client = GClient('.', options)
  if options.spec:
    client.SetConfig(options.spec)
  else:
    base_url = args[0].rstrip('/')
    if not options.name:
      name = base_url.split('/')[-1]
      if name.endswith('.git'):
        name = name[:-4]
    else:
      # specify an alternate relpath for the given URL.
      name = options.name
      if not os.path.abspath(os.path.join(os.getcwd(), name)).startswith(
          os.getcwd()):
        parser.error('Do not pass a relative path for --name.')
      if any(x in ('..', '.', '/', '\\') for x in name.split(os.sep)):
        parser.error('Do not include relative path components in --name.')

    deps_file = options.deps_file
    client.SetDefaultConfig(name, deps_file, base_url,
                            managed=not options.unmanaged,
                            cache_dir=options.cache_dir,
                            custom_vars=custom_vars)
  client.SaveConfig()
  return 0


@subcommand.epilog("""Example:
  gclient pack > patch.txt
    generate simple patch for configured client and dependences
""")
@metrics.collector.collect_metrics('gclient pack')
def CMDpack(parser, args):
  """Generates a patch which can be applied at the root of the tree.

  Internally, runs 'git 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'.
  """
  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.remove_option('--jobs')
  (options, args) = parser.parse_args(args)
  # Force jobs to 1 so the stdout is not annotated with the thread ids
  options.jobs = 1
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  if options.verbose:
    client.PrintLocationAndContents()
  return client.RunOnDeps('pack', args)


@metrics.collector.collect_metrics('gclient status')
def CMDstatus(parser, args):
  """Shows 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')
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  if options.verbose:
    client.PrintLocationAndContents()
  return client.RunOnDeps('status', args)


@subcommand.epilog("""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

JSON output format:
If the --output-json option is specified, the following document structure will
be emitted to the provided file. 'null' entries may occur for subprojects which
are present in the gclient solution, but were not processed (due to custom_deps,
os_deps, etc.)

{
  "solutions" : {
    "<name>": {  # <name> is the posix-normalized path to the solution.
      "revision": [<git id hex string>|null],
      "scm": ["git"|null],
    }
  }
}
""")
@metrics.collector.collect_metrics('gclient sync')
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('-p', '--noprehooks', action='store_true',
                    help='don\'t run pre-DEPS hooks', default=False)
  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. You can also specify URLs instead of paths '
                         'and gclient will find the solution corresponding to '
                         'the given URL. If a path is also specified, the URL '
                         'takes precedence. -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('--patch-ref', action='append',
                    dest='patch_refs', metavar='GERRIT_REF', default=[],
                    help='Patches the given reference with the format '
                         'dep@[target-ref:]patch-ref. '
                         'For |dep|, you can specify URLs as well as paths, '
                         'with URLs taking preference. '
                         '|patch-ref| will be applied to |dep|, rebased on top '
                         'of what |dep| was synced to, and a soft reset will '
                         'be done. Use --no-rebase-patch-ref and '
                         '--no-reset-patch-ref to disable this behavior. '
                         '|target-ref| is the target branch against which a '
                         'patch was created, it is used to determine which '
                         'commits from the |patch-ref| actually constitute a '
                         'patch. If not given, we will iterate over all remote '
                         'branches and select one that contains the revision '
                         '|dep| is synced at. '
                         'WARNING: |target-ref| will be mandatory soon.')
  parser.add_option('--with_branch_heads', action='store_true',
                    help='Clone git "branch_heads" refspecs in addition to '
                         'the default refspecs. This adds about 1/2GB to a '
                         'full checkout. (git only)')
  parser.add_option('--with_tags', action='store_true',
                    help='Clone git tags in addition to the default refspecs.')
  parser.add_option('-H', '--head', action='store_true',
                    help='DEPRECATED: only made sense with safesync urls.')
  parser.add_option('-D', '--delete_unversioned_trees', action='store_true',
                    help='Deletes from the working copy any dependencies that '
                         'have been removed since the last sync, as long as '
                         'there are no local modifications. When used with '
                         '--force, such dependencies are removed even if they '
                         'have local modifications. When used with --reset, '
                         'all untracked directories are removed from the '
                         'working copy, excluding those which are explicitly '
                         'ignored in the repository.')
  parser.add_option('-R', '--reset', action='store_true',
                    help='resets any local changes before updating (git only)')
  parser.add_option('-M', '--merge', action='store_true',
                    help='merge upstream changes instead of trying to '
                         'fast-forward or rebase')
  parser.add_option('-A', '--auto_rebase', action='store_true',
                    help='Automatically rebase repositories against local '
                         'checkout during update (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('--process-all-deps', action='store_true',
                    help='Check out all deps, even for different OS-es, '
                         'or with conditions evaluating to false')
  parser.add_option('--upstream', action='store_true',
                    help='Make repo state match upstream branch.')
  parser.add_option('--output-json',
                    help='Output a json document to this path containing '
                         'summary information about the sync.')
  parser.add_option('--no-history', action='store_true',
                    help='GIT ONLY - Reduces the size/time of the checkout at '
                    'the cost of no history. Requires Git 1.9+')
  parser.add_option('--shallow', action='store_true',
                    help='GIT ONLY - Do a shallow clone into the cache dir. '
                         'Requires Git 1.9+')
  parser.add_option('--no_bootstrap', '--no-bootstrap',
                    action='store_true',
                    help='Don\'t bootstrap from Google Storage.')
  parser.add_option('--ignore_locks', action='store_true',
                    help='GIT ONLY - Ignore cache locks.')
  parser.add_option('--break_repo_locks', action='store_true',
                    help='GIT ONLY - Forcibly remove repo locks (e.g. '
                      'index.lock). This should only be used if you know for '
                      'certain that this invocation of gclient is the only '
                      'thing operating on the git repos (e.g. on a bot).')
  parser.add_option('--lock_timeout', type='int', default=5000,
                    help='GIT ONLY - Deadline (in seconds) to wait for git '
                         'cache lock to become available. Default is %default.')
  # TODO(agable): Remove these when the oldest CrOS release milestone is M56.
  parser.add_option('-t', '--transitive', action='store_true',
                    help='DEPRECATED: This is a no-op.')
  parser.add_option('-m', '--manually_grab_svn_rev', action='store_true',
                    help='DEPRECATED: This is a no-op.')
  # TODO(phajdan.jr): Remove validation options once default (crbug/570091).
  parser.add_option('--validate-syntax', action='store_true', default=True,
                    help='Validate the .gclient and DEPS syntax')
  parser.add_option('--disable-syntax-validation', action='store_false',
                    dest='validate_syntax',
                    help='Disable validation of .gclient and DEPS syntax.')
  parser.add_option('--no-rebase-patch-ref', action='store_false',
                    dest='rebase_patch_ref', default=True,
                    help='Bypass rebase of the patch ref after checkout.')
  parser.add_option('--no-reset-patch-ref', action='store_false',
                    dest='reset_patch_ref', default=True,
                    help='Bypass calling reset after patching the ref.')
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)

  if not client:
    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')

  if options.verbose:
    client.PrintLocationAndContents()
  ret = client.RunOnDeps('update', args)
  if options.output_json:
    slns = {}
    for d in client.subtree(True):
      normed = d.name.replace('\\', '/').rstrip('/') + '/'
      slns[normed] = {
          'revision': d.got_revision,
          'scm': d.used_scm.name if d.used_scm else None,
          'url': str(d.url) if d.url else None,
          'was_processed': d.should_process,
      }
    with open(options.output_json, 'wb') as f:
      json.dump({'solutions': slns}, f)
  return ret


CMDupdate = CMDsync


@metrics.collector.collect_metrics('gclient validate')
def CMDvalidate(parser, args):
  """Validates the .gclient and DEPS syntax."""
  options, args = parser.parse_args(args)
  options.validate_syntax = True
  client = GClient.LoadCurrentConfig(options)
  rv = client.RunOnDeps('validate', args)
  if rv == 0:
    print('validate: SUCCESS')
  else:
    print('validate: FAILURE')
  return rv


@metrics.collector.collect_metrics('gclient diff')
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')
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  if options.verbose:
    client.PrintLocationAndContents()
  return client.RunOnDeps('diff', args)


@metrics.collector.collect_metrics('gclient revert')
def CMDrevert(parser, args):
  """Reverts all modifications in every dependencies.

  That's the nuclear option to get back to a 'clean' state. It removes anything
  that shows up in git status."""
  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('-p', '--noprehooks', action='store_true',
                    help='don\'t run pre-DEPS hooks', default=False)
  parser.add_option('--upstream', action='store_true',
                    help='Make repo state match upstream branch.')
  parser.add_option('--break_repo_locks', action='store_true',
                    help='GIT ONLY - Forcibly remove repo locks (e.g. '
                      'index.lock). This should only be used if you know for '
                      'certain that this invocation of gclient is the only '
                      'thing operating on the git repos (e.g. on a bot).')
  (options, args) = parser.parse_args(args)
  # --force is implied.
  options.force = True
  options.reset = False
  options.delete_unversioned_trees = False
  options.merge = False
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  return client.RunOnDeps('revert', args)


@metrics.collector.collect_metrics('gclient runhooks')
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.')
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  if options.verbose:
    client.PrintLocationAndContents()
  options.force = True
  options.nohooks = False
  return client.RunOnDeps('runhooks', args)


@metrics.collector.collect_metrics('gclient revinfo')
def CMDrevinfo(parser, args):
  """Outputs revision info mapping for the client and its dependencies.

  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 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',
                    help='override deps for the specified (comma-separated) '
                         'platform(s); \'all\' will process all deps_os '
                         'references')
  parser.add_option('-a', '--actual', action='store_true',
                    help='gets the actual checked out revisions instead of the '
                         'ones specified in the DEPS and .gclient files')
  parser.add_option('-s', '--snapshot', action='store_true',
                    help='creates a snapshot .gclient file of the current '
                         'version of all repositories to reproduce the tree, '
                         'implies -a')
  parser.add_option('--filter', action='append', dest='filter',
                     help='Display revision information only for the specified '
                          'dependencies (filtered by URL or path).')
  parser.add_option('--output-json',
                    help='Output a json document to this path containing '
                         'information about the revisions.')
  parser.add_option('--ignore-dep-type', choices=['git', 'cipd'],
                    help='Specify to skip processing of a certain type of dep.')
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  client.PrintRevInfo()
  return 0


@metrics.collector.collect_metrics('gclient getdep')
def CMDgetdep(parser, args):
  """Gets revision information and variable values from a DEPS file."""
  parser.add_option('--var', action='append',
                    dest='vars', metavar='VAR', default=[],
                    help='Gets the value of a given variable.')
  parser.add_option('-r', '--revision', action='append',
                    dest='getdep_revisions', metavar='DEP', default=[],
                    help='Gets the revision/version for the given dependency. '
                         'If it is a git dependency, dep must be a path. If it '
                         'is a CIPD dependency, dep must be of the form '
                         'path:package.')
  parser.add_option('--deps-file', default='DEPS',
                    # TODO(ehmaldonado): Try to find the DEPS file pointed by
                    # .gclient first.
                    help='The DEPS file to be edited. Defaults to the DEPS '
                         'file in the current directory.')
  (options, args) = parser.parse_args(args)

  if not os.path.isfile(options.deps_file):
    raise gclient_utils.Error(
        'DEPS file %s does not exist.' % options.deps_file)
  with open(options.deps_file) as f:
    contents = f.read()
  client = GClient.LoadCurrentConfig(options)
  if client is not None:
    builtin_vars = client.get_builtin_vars()
  else:
    logging.warn(
        'Couldn\'t find a valid gclient config. Will attempt to parse the DEPS '
        'file without support for built-in variables.')
    builtin_vars = None
  local_scope = gclient_eval.Exec(contents, options.deps_file,
                                  builtin_vars=builtin_vars)

  for var in options.vars:
    print(gclient_eval.GetVar(local_scope, var))

  for name in options.getdep_revisions:
    if ':' in name:
      name, _, package = name.partition(':')
      if not name or not package:
        parser.error(
            'Wrong CIPD format: %s:%s should be of the form path:pkg.'
            % (name, package))
      print(gclient_eval.GetCIPD(local_scope, name, package))
    else:
      print(gclient_eval.GetRevision(local_scope, name))


@metrics.collector.collect_metrics('gclient setdep')
def CMDsetdep(parser, args):
  """Modifies dependency revisions and variable values in a DEPS file"""
  parser.add_option('--var', action='append',
                    dest='vars', metavar='VAR=VAL', default=[],
                    help='Sets a variable to the given value with the format '
                         'name=value.')
  parser.add_option('-r', '--revision', action='append',
                    dest='setdep_revisions', metavar='DEP@REV', default=[],
                    help='Sets the revision/version for the dependency with '
                         'the format dep@rev. If it is a git dependency, dep '
                         'must be a path and rev must be a git hash or '
                         'reference (e.g. src/dep@deadbeef). If it is a CIPD '
                         'dependency, dep must be of the form path:package and '
                         'rev must be the package version '
                         '(e.g. src/pkg:chromium/pkg@2.1-cr0).')
  parser.add_option('--deps-file', default='DEPS',
                    # TODO(ehmaldonado): Try to find the DEPS file pointed by
                    # .gclient first.
                    help='The DEPS file to be edited. Defaults to the DEPS '
                         'file in the current directory.')
  (options, args) = parser.parse_args(args)
  if args:
    parser.error('Unused arguments: "%s"' % '" "'.join(args))
  if not options.setdep_revisions and not options.vars:
    parser.error(
        'You must specify at least one variable or revision to modify.')

  if not os.path.isfile(options.deps_file):
    raise gclient_utils.Error(
        'DEPS file %s does not exist.' % options.deps_file)
  with open(options.deps_file) as f:
    contents = f.read()

  client = GClient.LoadCurrentConfig(options)
  if client is not None:
    builtin_vars = client.get_builtin_vars()
  else:
    logging.warn(
        'Couldn\'t find a valid gclient config. Will attempt to parse the DEPS '
        'file without support for built-in variables.')
    builtin_vars = None

  local_scope = gclient_eval.Exec(contents, options.deps_file,
                                  builtin_vars=builtin_vars)

  for var in options.vars:
    name, _, value = var.partition('=')
    if not name or not value:
      parser.error(
          'Wrong var format: %s should be of the form name=value.' % var)
    if name in local_scope['vars']:
      gclient_eval.SetVar(local_scope, name, value)
    else:
      gclient_eval.AddVar(local_scope, name, value)

  for revision in options.setdep_revisions:
    name, _, value = revision.partition('@')
    if not name or not value:
      parser.error(
          'Wrong dep format: %s should be of the form dep@rev.' % revision)
    if ':' in name:
      name, _, package = name.partition(':')
      if not name or not package:
        parser.error(
            'Wrong CIPD format: %s:%s should be of the form path:pkg@version.'
            % (name, package))
      gclient_eval.SetCIPD(local_scope, name, package, value)
    else:
      gclient_eval.SetRevision(local_scope, name, value)

  with open(options.deps_file, 'w') as f:
    f.write(gclient_eval.RenderDEPSFile(local_scope))


@metrics.collector.collect_metrics('gclient verify')
def CMDverify(parser, args):
  """Verifies the DEPS file deps are only from allowed_hosts."""
  (options, args) = parser.parse_args(args)
  client = GClient.LoadCurrentConfig(options)
  if not client:
    raise gclient_utils.Error('client not configured; see \'gclient config\'')
  client.RunOnDeps(None, [])
  # Look at each first-level dependency of this gclient only.
  for dep in client.dependencies:
    bad_deps = dep.findDepsFromNotAllowedHosts()
    if not bad_deps:
      continue
    print("There are deps from not allowed hosts in file %s" % dep.deps_file)
    for bad_dep in bad_deps:
      print("\t%s at %s" % (bad_dep.name, bad_dep.url))
    print("allowed_hosts:", ', '.join(dep.allowed_hosts))
    sys.stdout.flush()
    raise gclient_utils.Error(
        'dependencies from disallowed hosts; check your DEPS file.')
  return 0


@subcommand.epilog("""For more information on what metrics are we collecting and
why, please read metrics.README.md or visit https://bit.ly/2ufRS4p""")
@metrics.collector.collect_metrics('gclient metrics')
def CMDmetrics(parser, args):
  """Reports, and optionally modifies, the status of metric collection."""
  parser.add_option('--opt-in', action='store_true', dest='enable_metrics',
                    help='Opt-in to metrics collection.',
                    default=None)
  parser.add_option('--opt-out', action='store_false', dest='enable_metrics',
                    help='Opt-out of metrics collection.')
  options, args = parser.parse_args(args)
  if args:
    parser.error('Unused arguments: "%s"' % '" "'.join(args))
  if not metrics.collector.config.is_googler:
    print("You're not a Googler. Metrics collection is disabled for you.")
    return 0

  if options.enable_metrics is not None:
    metrics.collector.config.opted_in = options.enable_metrics

  if metrics.collector.config.opted_in is None:
    print("You haven't opted in or out of metrics collection.")
  elif metrics.collector.config.opted_in:
    print("You have opted in. Thanks!")
  else:
    print("You have opted out. Please consider opting in.")
  return 0


class OptionParser(optparse.OptionParser):
  gclientfile_default = os.environ.get('GCLIENT_FILE', '.gclient')

  def __init__(self, **kwargs):
    optparse.OptionParser.__init__(
        self, version='%prog ' + __version__, **kwargs)

    # Some arm boards have issues with parallel sync.
    if platform.machine().startswith('arm'):
      jobs = 1
    else:
      jobs = max(8, gclient_utils.NumLocalCpus())

    self.add_option(
        '-j', '--jobs', default=jobs, type='int',
        help='Specify how many SCM commands can run in parallel; defaults to '
             '%default on this machine')
    self.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.')
    self.add_option(
        '--gclientfile', dest='config_filename',
        help='Specify an alternate %s file' % self.gclientfile_default)
    self.add_option(
        '--spec',
        help='create a gclient file containing the provided string. Due to '
            'Cygwin/Python brokenness, it can\'t contain any newlines.')
    self.add_option(
        '--no-nag-max', default=False, action='store_true',
        help='Ignored for backwards compatibility.')

  def parse_args(self, args=None, _values=None):
    """Integrates standard options processing."""
    # Create an optparse.Values object that will store only the actual passed
    # options, without the defaults.
    actual_options = optparse.Values()
    _, args = optparse.OptionParser.parse_args(self, args, actual_options)
    # Create an optparse.Values object with the default options.
    options = optparse.Values(self.get_default_values().__dict__)
    # Update it with the options passed by the user.
    options._update_careful(actual_options.__dict__)
    # Store the options passed by the user in an _actual_options attribute.
    # We store only the keys, and not the values, since the values can contain
    # arbitrary information, which might be PII.
    metrics.collector.add('arguments', actual_options.__dict__.keys())

    levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
    logging.basicConfig(
        level=levels[min(options.verbose, len(levels) - 1)],
        format='%(module)s(%(lineno)d) %(funcName)s:%(message)s')
    if options.config_filename and options.spec:
      self.error('Cannot specifiy both --gclientfile and --spec')
    if (options.config_filename and
        options.config_filename != os.path.basename(options.config_filename)):
      self.error('--gclientfile target must be a filename, not a path')
    if not options.config_filename:
      options.config_filename = self.gclientfile_default
    options.entries_filename = options.config_filename + '_entries'
    if options.jobs < 1:
      self.error('--jobs must be 1 or higher')

    # These hacks need to die.
    if not hasattr(options, 'revisions'):
      # GClient.RunOnDeps expects it even if not applicable.
      options.revisions = []
    if not hasattr(options, 'head'):
      options.head = None
    if not hasattr(options, 'nohooks'):
      options.nohooks = True
    if not hasattr(options, 'noprehooks'):
      options.noprehooks = True
    if not hasattr(options, 'deps_os'):
      options.deps_os = None
    if not hasattr(options, 'force'):
      options.force = None
    return (options, args)


def disable_buffering():
  # Make stdout auto-flush so buildbot doesn't kill us during lengthy
  # operations. Python as a strong tendency to buffer sys.stdout.
  sys.stdout = gclient_utils.MakeFileAutoFlush(sys.stdout)
  # Make stdout annotated with the thread ids.
  sys.stdout = gclient_utils.MakeFileAnnotated(sys.stdout)


def main(argv):
  """Doesn't parse the arguments here, just find the right subcommand to
  execute."""
  if sys.hexversion < 0x02060000:
    print(
        '\nYour python version %s is unsupported, please upgrade.\n' %
        sys.version.split(' ', 1)[0],
        file=sys.stderr)
    return 2
  if not sys.executable:
    print(
        '\nPython cannot find the location of it\'s own executable.\n',
        file=sys.stderr)
    return 2
  fix_encoding.fix_encoding()
  disable_buffering()
  setup_color.init()
  dispatcher = subcommand.CommandDispatcher(__name__)
  try:
    return dispatcher.execute(OptionParser(), argv)
  except KeyboardInterrupt:
    gclient_utils.GClientChildren.KillAllRemainingChildren()
    raise
  except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
    print('Error: %s' % str(e), file=sys.stderr)
    return 1
  finally:
    gclient_utils.PrintWarnings()
  return 0


if '__main__' == __name__:
  with metrics.collector.print_notice_and_exit():
    sys.exit(main(sys.argv[1:]))

# vim: ts=2:sw=2:tw=80:et:
