servo: Merge #20244 - Ensure readonly files can be removed on Windows (from servo:jdm-patch-10); r=SimonSapin
authorJosh Matthews <josh@joshmatthews.net>
Thu, 08 Mar 2018 15:01:36 -0500
changeset 462261 5330f4f93f271daefae6db0df8612a291c377659
parent 462260 3836a743ba539056cb8b38240861e339cad579c3
child 462262 cdf8e9c396b9d8a3a1fb77d8c72dfde43e978c3e
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersSimonSapin
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #20244 - Ensure readonly files can be removed on Windows (from servo:jdm-patch-10); r=SimonSapin This is based off of https://bugs.python.org/issue19643. At worst, it makes our deletion function more robust and doesn't help with the ongoing windows CI problems. Source-Repo: https://github.com/servo/servo Source-Revision: f1338d3df8d76f821353686efe2d6a0a4691da02
servo/python/servo/bootstrap_commands.py
servo/python/servo/util.py
--- a/servo/python/servo/bootstrap_commands.py
+++ b/servo/python/servo/bootstrap_commands.py
@@ -11,16 +11,17 @@ from __future__ import absolute_import, 
 
 import base64
 import json
 import os
 import os.path as path
 import re
 import subprocess
 import sys
+import traceback
 import urllib2
 import glob
 
 from mach.decorators import (
     CommandArgument,
     CommandProvider,
     Command,
 )
@@ -313,16 +314,17 @@ class MachCommands(CommandBase):
                             print_msg = (exist_name, " ({}MB)".format(round(size, 2)) if show_size else "", cargo_dir)
                             if force:
                                 print("Removing `{}`{} package from {}".format(*print_msg))
                                 for crate_path in crate_paths:
                                     if os.path.exists(crate_path):
                                         try:
                                             delete(crate_path)
                                         except:
+                                            print(traceback.format_exc())
                                             print("Delete %s failed!" % crate_path)
                             else:
                                 print("Would remove `{}`{} package from {}".format(*print_msg))
 
         if removing_anything and show_size:
             print("\nTotal size of {} MB".format(round(total_size, 2)))
 
         if not removing_anything:
--- a/servo/python/servo/util.py
+++ b/servo/python/servo/util.py
@@ -9,16 +9,17 @@
 
 from __future__ import absolute_import, print_function, unicode_literals
 
 import os
 import os.path
 import platform
 import shutil
 from socket import error as socket_error
+import stat
 import StringIO
 import sys
 import zipfile
 import urllib2
 import certifi
 
 
 try:
@@ -30,19 +31,25 @@ except ImportError:
 if HAS_SNI and sys.version_info >= (2, 7, 9):
     STATIC_RUST_LANG_ORG_DIST = "https://static.rust-lang.org/dist"
     URLOPEN_KWARGS = {"cafile": certifi.where()}
 else:
     STATIC_RUST_LANG_ORG_DIST = "https://static-rust-lang-org.s3.amazonaws.com/dist"
     URLOPEN_KWARGS = {}
 
 
+def remove_readonly(func, path, _):
+    "Clear the readonly bit and reattempt the removal"
+    os.chmod(path, stat.S_IWRITE)
+    func(path)
+
+
 def delete(path):
     if os.path.isdir(path) and not os.path.islink(path):
-        shutil.rmtree(path)
+        shutil.rmtree(path, onerror=remove_readonly)
     else:
         os.remove(path)
 
 
 def host_platform():
     os_type = platform.system().lower()
     if os_type == "linux":
         os_type = "unknown-linux-gnu"