Bug 1323901 - Force `which` to use lowercase extensions on Windows. r=chmanchester
--- 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):