Reset the fetch config in the bots before each run.

If a ref is incorrectly set, it will affect later runs.
For example, [1] caused a bad refspec to be added to the fetch config,
(+refs/branch-heads/refs/branch-heads/6.7:refs/branch-heads/refs/branch-heads/6.7)
which affects all subsequent runs in the same bot: [2], [3].

This makes bot_update clear the fetch config before each run, so it is more
robust against these kind of failures.

[1] https://logs.chromium.org/v/?s=v8%2Fbuildbucket%2Fcr-buildbucket.appspot.com%2F8942033142534034848%2F%2B%2Fsteps%2Fbot_update%2F0%2Fstdout
[2] https://logs.chromium.org/v/?s=v8%2Fbuildbucket%2Fcr-buildbucket.appspot.com%2F8941307871443322944%2F%2B%2Fsteps%2Fbot_update%2F0%2Fstdout
[3] https://logs.chromium.org/v/?s=v8%2Fbuildbucket%2Fcr-buildbucket.appspot.com%2F8941333453153279680%2F%2B%2Fsteps%2Fbot_update%2F0%2Fstdout

Bug: 862547
Change-Id: I2f849c604656e81ebd7377465d287226b8bdea1a
Reviewed-on: https://chromium-review.googlesource.com/1135645
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: Aaron Gable <agable@chromium.org>
Reviewed-by: Robbie Iannucci <iannucci@chromium.org>
diff --git a/git_cache.py b/git_cache.py
index 02f8209..16b49cb 100755
--- a/git_cache.py
+++ b/git_cache.py
@@ -311,10 +311,13 @@
     self.print('running "git %s" in "%s"' % (' '.join(cmd), cwd))
     gclient_utils.CheckCallAndFilter([self.git_exe] + cmd, **kwargs)
 
-  def config(self, cwd=None):
+  def config(self, cwd=None, reset_fetch_config=False):
     if cwd is None:
       cwd = self.mirror_path
 
+    if reset_fetch_config:
+      self.RunGit(['config', '--unset-all', 'remote.origin.fetch'], cwd=cwd)
+
     # Don't run git-gc in a daemon.  Bad things can happen if it gets killed.
     try:
       self.RunGit(['config', 'gc.autodetach', '0'], cwd=cwd)
@@ -508,8 +511,8 @@
             'Shallow fetch requested, but repo cache already exists.')
     return tempdir
 
-  def _fetch(self, rundir, verbose, depth):
-    self.config(rundir)
+  def _fetch(self, rundir, verbose, depth, reset_fetch_config):
+    self.config(rundir, reset_fetch_config)
     v = []
     d = []
     if verbose:
@@ -531,7 +534,8 @@
         logging.warn('Fetch of %s failed' % spec)
 
   def populate(self, depth=None, shallow=False, bootstrap=False,
-               verbose=False, ignore_lock=False, lock_timeout=0):
+               verbose=False, ignore_lock=False, lock_timeout=0,
+               reset_fetch_config=False):
     assert self.GetCachePath()
     if shallow and not depth:
       depth = 10000
@@ -545,14 +549,14 @@
     try:
       tempdir = self._ensure_bootstrapped(depth, bootstrap)
       rundir = tempdir or self.mirror_path
-      self._fetch(rundir, verbose, depth)
+      self._fetch(rundir, verbose, depth, reset_fetch_config)
     except ClobberNeeded:
       # This is a major failure, we need to clean and force a bootstrap.
       gclient_utils.rmtree(rundir)
       self.print(GIT_CACHE_CORRUPT_MESSAGE)
       tempdir = self._ensure_bootstrapped(depth, bootstrap, force=True)
       assert tempdir
-      self._fetch(tempdir, verbose, depth)
+      self._fetch(tempdir, verbose, depth, reset_fetch_config)
     finally:
       if tempdir:
         if os.path.exists(self.mirror_path):
@@ -693,6 +697,8 @@
   parser.add_option('--ignore_locks', '--ignore-locks',
                     action='store_true',
                     help='Don\'t try to lock repository')
+  parser.add_option('--reset-fetch-config', action='store_true', default=False,
+                    help='Reset the fetch config before populating the cache.')
 
   options, args = parser.parse_args(args)
   if not len(args) == 1:
@@ -706,6 +712,7 @@
       'bootstrap': not options.no_bootstrap,
       'ignore_lock': options.ignore_locks,
       'lock_timeout': options.timeout,
+      'reset_fetch_config': options.reset_fetch_config,
   }
   if options.depth:
     kwargs['depth'] = options.depth