Refactor cache-updating code to eliminate unnecessary fetches.

This is an update of the following reverted change:

https://codereview.chromium.org/344443002/

R=hinoka@chromium.org,agable@chromium.org
BUG=

Review URL: https://codereview.chromium.org/343523002

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@277931 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gclient_scm.py b/gclient_scm.py
index 26d9658..67d6867 100644
--- a/gclient_scm.py
+++ b/gclient_scm.py
@@ -356,8 +356,6 @@
       verbose = ['--verbose']
       printed_path = True
 
-    url = self._CreateOrUpdateCache(url, options)
-
     if revision.startswith('refs/'):
       rev_type = "branch"
     elif revision.startswith(self.remote + '/'):
@@ -368,9 +366,15 @@
       # hash is also a tag, only make a distinction at checkout
       rev_type = "hash"
 
+    mirror = self._GetMirror(url, options)
+    if mirror:
+      url = mirror.mirror_path
+
     if (not os.path.exists(self.checkout_path) or
         (os.path.isdir(self.checkout_path) and
          not os.path.exists(os.path.join(self.checkout_path, '.git')))):
+      if mirror:
+        self._UpdateMirror(mirror, options)
       try:
         self._Clone(revision, url, options)
       except subprocess2.CalledProcessError:
@@ -394,6 +398,9 @@
       self.Print('________ unmanaged solution; skipping %s' % self.relpath)
       return self._Capture(['rev-parse', '--verify', 'HEAD'])
 
+    if mirror:
+      self._UpdateMirror(mirror, options)
+
     # See if the url has changed (the unittests use git://foo for the url, let
     # that through).
     current_url = self._Capture(['config', 'remote.%s.url' % self.remote])
@@ -745,14 +752,10 @@
     base_url = self.url
     return base_url[:base_url.rfind('/')] + url
 
-  def _CreateOrUpdateCache(self, url, options):
-    """Make a new git mirror or update existing mirror for |url|, and return the
-    mirror URI to clone from.
-
-    If no cache-dir is specified, just return |url| unchanged.
-    """
-    if not self.cache_dir:
-      return url
+  def _GetMirror(self, url, options):
+    """Get a git_cache.Mirror object for the argument url."""
+    if not git_cache.Mirror.GetCachePath():
+      return None
     mirror_kwargs = {
         'print_func': self.filter,
         'refs': []
@@ -765,10 +768,14 @@
     #  mirror_kwargs['refs'].extend(['refs/tags/lkgr', 'refs/tags/lkcr'])
     if hasattr(options, 'with_branch_heads') and options.with_branch_heads:
       mirror_kwargs['refs'].append('refs/branch-heads/*')
-    mirror = git_cache.Mirror(url, **mirror_kwargs)
+    return git_cache.Mirror(url, **mirror_kwargs)
+
+  @staticmethod
+  def _UpdateMirror(mirror, options):
+    """Update a git mirror by fetching the latest commits from the remote."""
     if options.shallow:
       # HACK(hinoka): These repositories should be super shallow.
-      if 'flash' in url:
+      if 'flash' in mirror.url:
         depth = 10
       else:
         depth = 10000
@@ -776,7 +783,6 @@
       depth = None
     mirror.populate(verbose=options.verbose, bootstrap=True, depth=depth)
     mirror.unlock()
-    return mirror.mirror_path if mirror.exists() else None
 
   def _Clone(self, revision, url, options):
     """Clone a git repository from the given URL.
diff --git a/git_cache.py b/git_cache.py
index 686d0e1..ca21a3c 100755
--- a/git_cache.py
+++ b/git_cache.py
@@ -318,6 +318,7 @@
 
   def populate(self, depth=None, shallow=False, bootstrap=False,
                verbose=False):
+    assert self.GetCachePath()
     if shallow and not depth:
       depth = 10000
     gclient_utils.safe_makedirs(self.GetCachePath())
@@ -429,6 +430,8 @@
   @classmethod
   def UnlockAll(cls):
     cachepath = cls.GetCachePath()
+    if not cachepath:
+      return
     dirlist = os.listdir(cachepath)
     repo_dirs = set([os.path.join(cachepath, path) for path in dirlist
                      if os.path.isdir(os.path.join(cachepath, path))])
diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py
index 0341229..55bc9c3 100755
--- a/tests/gclient_scm_test.py
+++ b/tests/gclient_scm_test.py
@@ -24,8 +24,12 @@
 from testing_support.super_mox import TestCaseUtils
 
 import gclient_scm
+import git_cache
 import subprocess2
 
+# Disable global git cache
+git_cache.Mirror.SetCachePath(None)
+
 # Shortcut since this function is used often
 join = gclient_scm.os.path.join
 
@@ -1571,11 +1575,11 @@
 
 
 if __name__ == '__main__':
-  if '-v' in sys.argv:
-    logging.basicConfig(
-        level=logging.DEBUG,
-        format='%(asctime).19s %(levelname)s %(filename)s:'
-               '%(lineno)s %(message)s')
+  level = logging.DEBUG if '-v' in sys.argv else logging.FATAL
+  logging.basicConfig(
+      level=level,
+      format='%(asctime).19s %(levelname)s %(filename)s:'
+             '%(lineno)s %(message)s')
   unittest.main()
 
 # vim: ts=2:sw=2:tw=80:et: