scripts: udpate_deps retry on clone or fetch failure

Duplicate change from commit b636386a7824eb4e6a0d99962e1491ac68d3a295
on KhronosGroup/Vulkan-ValidationLayers, to keep update_deps.py
in sync across all repos.  Original commit message is:

We see spurious failures to connect to github when trying to
run update_deps.py (up to 7% of runs, depending on the machine).
This is an annoyance when running by hand, but a headache and
a serious resource waste when running in automation (as a single
broken "git clone" or "git fetch" can cause the whole run to fail).

These changes allow update_deps.py to automatically retry
"git fetch" and "git clone" operations on failure.

These changes will be duplicated in follow-on PRs to the
other repositories that include "update_deps.py", to keep
them all in sync. These are KhronosGroup/Vulkan-Tools,
KhronosGroup/Vulkan-Loader, LunarG/VulkanSamples, and
LunarG/VulkanTools.

I'm also including a "technical debt" update here, because
VulkanTools/scripts/update_deps.py had diverged from the other
"update_deps.py" versions, to add a way to avoid building a
dependency if that dependency is not supported on the current
build platform. This should be harmless to the other
repositories (though potentially useful in the future). The
original commit was aaabc9df034f1fdf9a976a6293d0983b079143ee
with description:

    In update deps, this will check that a dependency is actually supported
    on the platform being built. This is needed because the loader is a
    dependency on all platforms other than Windows.
diff --git a/scripts/update_deps.py b/scripts/update_deps.py
index f1fe36d..658dcf5 100755
--- a/scripts/update_deps.py
+++ b/scripts/update_deps.py
@@ -2,7 +2,7 @@
 
 # Copyright 2017 The Glslang Authors. All rights reserved.
 # Copyright (c) 2018 Valve Corporation
-# Copyright (c) 2018 LunarG, Inc.
+# Copyright (c) 2018-2020 LunarG, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -250,6 +250,8 @@
 import multiprocessing
 import shlex
 import shutil
+import stat
+import time
 
 KNOWN_GOOD_FILE_NAME = 'known_good.json'
 
@@ -265,6 +267,14 @@
 DEVNULL = open(os.devnull, 'wb')
 
 
+def on_rm_error( func, path, exc_info):
+    """Error handler for recursively removing a directory. The
+    shutil.rmtree function can fail on Windows due to read-only files.
+    This handler will change the permissions for tha file and continue.
+    """
+    os.chmod( path, stat.S_IWRITE )
+    os.unlink( path )
+
 def command_output(cmd, directory, fail_ok=False):
     """Runs a command in a directory and returns its standard output stream.
 
@@ -333,17 +343,52 @@
         if self.build_platforms == [] or platform.system().lower() in self.build_platforms:
             self.on_build_platform = True
 
-    def Clone(self):
+    def Clone(self, retries=10, retry_seconds=60):
+        print('Cloning {n} into {d}'.format(n=self.name, d=self.repo_dir))
         distutils.dir_util.mkpath(self.repo_dir)
-        command_output(['git', 'clone', self.url, '.'], self.repo_dir)
+        for retry in range(retries):
+            try:
+                command_output(['git', 'clone', self.url, '.'], self.repo_dir)
+                # If we get here, we didn't raise an error
+                return
+            except RuntimeError as e:
+                print("Error cloning on iteration {}/{}: {}".format(retry + 1, retries, e))
+                if retry + 1 < retries:
+                    if retry_seconds > 0:
+                        print("Waiting {} seconds before trying again".format(retry_seconds))
+                        time.sleep(retry_seconds)
+                    if os.path.isdir(self.repo_dir):
+                        print("Removing old tree {}".format(self.repo_dir))
+                        shutil.rmtree(self.repo_dir, onerror=on_rm_error)
+                    continue
 
-    def Fetch(self):
-        command_output(['git', 'fetch', 'origin'], self.repo_dir)
+                # If we get here, we've exhausted our retries.
+                print("Failed to clone {} on all retries.".format(self.url))
+                raise e
+
+    def Fetch(self, retries=10, retry_seconds=60):
+        for retry in range(retries):
+            try:
+                command_output(['git', 'fetch', 'origin'], self.repo_dir)
+                # if we get here, we didn't raise an error, and we're done
+                return
+            except RuntimeError as e:
+                print("Error fetching on iteration {}/{}: {}".format(retry + 1, retries, e))
+                if retry + 1 < retries:
+                    if retry_seconds > 0:
+                        print("Waiting {} seconds before trying again".format(retry_seconds))
+                        time.sleep(retry_seconds)
+                    continue
+
+                # If we get here, we've exhausted our retries.
+                print("Failed to fetch {} on all retries.".format(self.url))
+                raise e
 
     def Checkout(self):
         print('Checking out {n} in {d}'.format(n=self.name, d=self.repo_dir))
         if self._args.do_clean_repo:
-            shutil.rmtree(self.repo_dir, ignore_errors=True)
+            if os.path.isdir(self.repo_dir):
+                shutil.rmtree(self.repo_dir, onerror = on_rm_error)
         if not os.path.exists(os.path.join(self.repo_dir, '.git')):
             self.Clone()
         self.Fetch()
@@ -394,7 +439,7 @@
         # repo's install dir.
         for d in self.deps:
             dep_commit = [r for r in repos if r.name == d['repo_name']]
-            if len(dep_commit):
+            if len(dep_commit) and dep_commit[0].on_build_platform:
                 cmake_cmd.append('-D{var_name}={install_dir}'.format(
                     var_name=d['var_name'],
                     install_dir=dep_commit[0].install_dir))
@@ -411,9 +456,12 @@
         # Use the CMake -A option to select the platform architecture
         # without needing a Visual Studio generator.
         if platform.system() == 'Windows':
-            if self._args.arch == '64' or self._args.arch == 'x64' or self._args.arch == 'win64':
+            if self._args.arch.lower() == '64' or self._args.arch == 'x64' or self._args.arch == 'win64':
                 cmake_cmd.append('-A')
                 cmake_cmd.append('x64')
+            else:
+                cmake_cmd.append('-A')
+                cmake_cmd.append('Win32')
 
         # Apply a generator, if one is specified.  This can be used to supply
         # a specific generator for the dependent repositories to match