Bug 1323901 - Force `which` to use lowercase extensions on Windows. r=chmanchester draft
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 23 Dec 2016 06:28:03 +0900
changeset 454136 0249e09e7569578ea73097a51a34242b3dfb2709
parent 454127 d7b6af32811bddcec10a47d24bd455a1ec1836fc
child 540625 3abdb222567393dc7e53824bace1dea05e144677
push id39841
push userbmo:mh+mozilla@glandium.org
push dateWed, 28 Dec 2016 07:49:21 +0000
reviewerschmanchester
bugs1323901
milestone53.0a1
Bug 1323901 - Force `which` to use lowercase extensions on Windows. r=chmanchester
build/moz.configure/util.configure
python/mozbuild/mozbuild/test/configure/common.py
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -135,29 +135,46 @@ normalize_path = normalize_path()
 
 # Locates the given program using which, or returns the given path if it
 # exists.
 # The `paths` parameter may be passed to search the given paths instead of
 # $PATH.
 @imports(_from='which', _import='which')
 @imports(_from='which', _import='WhichError')
 @imports('itertools')
+@imports('sys')
 @imports(_from='os', _import='pathsep')
+@imports(_from='os', _import='environ')
 def find_program(file, paths=None):
+    # The following snippet comes from `which` itself, with a slight
+    # modification to use lowercase extensions, because it's confusing rustup
+    # (on top of making results not really appealing to the eye).
+
+    # Windows has the concept of a list of extensions (PATHEXT env var).
+    if sys.platform.startswith("win"):
+        exts = [e.lower()
+                for e in environ.get("PATHEXT", "").split(pathsep)]
+        # If '.exe' is not in exts then obviously this is Win9x and
+        # or a bogus PATHEXT, then use a reasonable default.
+	if '.exe' not in exts:
+            exts = ['.com', '.exe', '.bat']
+    else:
+        exts = None
+
     try:
         if is_absolute_or_relative(file):
             return normalize_path(which(os.path.basename(file),
-                                        [os.path.dirname(file)]))
+                                        [os.path.dirname(file)], exts=exts))
         if paths:
             if not isinstance(paths, (list, tuple)):
                 die("Paths provided to find_program must be a list of strings, "
                     "not %r", paths)
             paths = list(itertools.chain(
                 *(p.split(pathsep) for p in paths if p)))
-        return normalize_path(which(file, path=paths))
+        return normalize_path(which(file, path=paths, exts=exts))
     except WhichError:
         return None
 
 
 @imports('os')
 @imports('subprocess')
 @imports(_from='mozbuild.configure.util', _import='LineIO')
 @imports(_from='tempfile', _import='mkstemp')
--- a/python/mozbuild/mozbuild/test/configure/common.py
+++ b/python/mozbuild/mozbuild/test/configure/common.py
@@ -170,17 +170,17 @@ class ConfigureTestSandbox(ConfigureSand
                 self.value = ''
 
         return Buffer()
 
     def GetShortPathNameW(self, path_in, path_out, length):
         path_out.value = fake_short_path(path_in)
         return length
 
-    def which(self, command, path=None):
+    def which(self, command, path=None, exts=None):
         for parent in (path or self._search_path):
             c = mozpath.abspath(mozpath.join(parent, command))
             for candidate in (c, ensure_exe_extension(c)):
                 if self.imported_os.path.exists(candidate):
                     return candidate
         raise WhichError()
 
     def Popen(self, args, stdin=None, stdout=None, stderr=None, **kargs):