Use cleanup with retry on Windows for all scripts.

Make use of the helper function added in
https://codereview.chromium.org/1514533002/
in more places, in particular in the copy_apprtc.py script.

BUG=567538
TESTED=Ran a local gclient sync on Mac without any failures.
TBR=phoglund@chromium.org

Review URL: https://codereview.chromium.org/1566963004 .
diff --git a/build_apprtc_appengine_app.py b/build_apprtc_appengine_app.py
index 9d15b75..32f9853 100755
--- a/build_apprtc_appengine_app.py
+++ b/build_apprtc_appengine_app.py
@@ -35,7 +35,7 @@
   print 'Wiping .npm folder and trying again...'
   npm_storage = os.path.expanduser('~/.npm')
   assert npm_storage.endswith('.npm')
-  shutil.rmtree(npm_storage, ignore_errors=True)
+  utils.RemoveDirectory(npm_storage)
   utils.RunSubprocessWithRetry(command)
 
 
@@ -49,7 +49,7 @@
 
   _WorkaroundPhantomJsOnWin(apprtc_path)
   os.chdir(apprtc_path)
-  
+
   if utils.GetPlatform() is 'win':
     npm_bin = os.path.join(node_path, 'npm.cmd')
     node_bin = os.path.join(node_path, 'node.exe')
diff --git a/build_apprtc_collider.py b/build_apprtc_collider.py
index c9873a7..f9ce9aa 100755
--- a/build_apprtc_collider.py
+++ b/build_apprtc_collider.py
@@ -13,52 +13,14 @@
 import shutil
 import subprocess
 import sys
-import time
 
 import utils
 
 
-# Code partially copied from
-# https://cs.chromium.org#chromium/build/scripts/common/chromium_utils.py
-def RemoveDirectory(*path):
-  """Recursively removes a directory, even if it's marked read-only.
-
-  Remove the directory located at *path, if it exists.
-
-  shutil.rmtree() doesn't work on Windows if any of the files or directories
-  are read-only, which svn repositories and some .svn files are.  We need to
-  be able to force the files to be writable (i.e., deletable) as we traverse
-  the tree.
-
-  Even with all this, Windows still sometimes fails to delete a file, citing
-  a permission error (maybe something to do with antivirus scans or disk
-  indexing).  The best suggestion any of the user forums had was to wait a
-  bit and try again, so we do that too.  It's hand-waving, but sometimes it
-  works. :/
-  """
-  file_path = os.path.join(*path)
-  if not os.path.exists(file_path):
-    return
-
-  if sys.platform == 'win32':
-    # Give up and use cmd.exe's rd command.
-    file_path = os.path.normcase(file_path)
-    for _ in xrange(3):
-      print 'RemoveDirectory running %s' % (' '.join(
-          ['cmd.exe', '/c', 'rd', '/q', '/s', file_path]))
-      if not subprocess.call(['cmd.exe', '/c', 'rd', '/q', '/s', file_path]):
-        break
-      print '  Failed'
-      time.sleep(3)
-    return
-  else:
-    shutil.rmtree(file_path, ignore_errors=True)
-
-
 def main():
   apprtc_dir = os.path.join('apprtc', 'src')
   golang_workspace = os.path.join('src', 'out', 'go-workspace')
-  RemoveDirectory(golang_workspace)
+  utils.RemoveDirectory(golang_workspace)
 
   golang_workspace_src = os.path.join(golang_workspace, 'src')
 
diff --git a/copy_apprtc.py b/copy_apprtc.py
index 8cc40b1..ca4750e 100755
--- a/copy_apprtc.py
+++ b/copy_apprtc.py
@@ -27,12 +27,7 @@
 
 def main():
   target_dir = os.path.join('src', 'out', 'apprtc')
-  if utils.GetPlatform() is 'win':
-    # Windows shutil can't handle the long node.js paths when deleting;
-    # work around the problem.
-    os.system('rmdir /s /q %s' % target_dir)
-  else:
-    shutil.rmtree(target_dir, ignore_errors=True)
+  utils.RemoveDirectory(target_dir)
   shutil.copytree('apprtc',
                   target_dir, ignore=shutil.ignore_patterns('.svn', '.git'))
 
diff --git a/utils.py b/utils.py
index b32af09..5813271 100755
--- a/utils.py
+++ b/utils.py
@@ -25,7 +25,7 @@
       backoff = pow(2, i)
       print 'Got %s, retrying in %d seconds...' % (exception, backoff)
       time.sleep(backoff)
-  
+
   print 'Giving up.'
   raise exception
 
@@ -56,12 +56,49 @@
   return sha1.hexdigest()
 
 
+# Code partially copied from
+# https://cs.chromium.org#chromium/build/scripts/common/chromium_utils.py
+def RemoveDirectory(*path):
+  """Recursively removes a directory, even if it's marked read-only.
+
+  Remove the directory located at *path, if it exists.
+
+  shutil.rmtree() doesn't work on Windows if any of the files or directories
+  are read-only, which svn repositories and some .svn files are.  We need to
+  be able to force the files to be writable (i.e., deletable) as we traverse
+  the tree.
+
+  Even with all this, Windows still sometimes fails to delete a file, citing
+  a permission error (maybe something to do with antivirus scans or disk
+  indexing).  The best suggestion any of the user forums had was to wait a
+  bit and try again, so we do that too.  It's hand-waving, but sometimes it
+  works. :/
+  """
+  file_path = os.path.join(*path)
+  if not os.path.exists(file_path):
+    return
+
+  if sys.platform == 'win32':
+    # Give up and use cmd.exe's rd command.
+    file_path = os.path.normcase(file_path)
+    for _ in xrange(3):
+      print 'RemoveDirectory running %s' % (' '.join(
+          ['cmd.exe', '/c', 'rd', '/q', '/s', file_path]))
+      if not subprocess.call(['cmd.exe', '/c', 'rd', '/q', '/s', file_path]):
+        break
+      print '  Failed'
+      time.sleep(3)
+    return
+  else:
+    shutil.rmtree(file_path, ignore_errors=True)
+
+
 def DeleteDirNextToGclient(directory):
   # Sanity check to avoid nuking the wrong dirs.
   if not os.path.exists('.gclient'):
     raise Exception('Invoked from wrong dir; invoke from dir with .gclient')
   print 'Deleting %s in %s...' % (directory, os.getcwd())
-  shutil.rmtree(directory, ignore_errors=True)
+  RemoveDirectory(directory)
 
 
 def UnpackToWorkingDir(archive_path):