Windows: shell variables are case-insensitive (#36813)
If we modify both Path and PATH, on Windows they will clobber one another. This PR updates the shell modification logic to automatically convert variable names to upper-case on Windows.
This commit is contained in:
parent
255c9ed5e9
commit
d8451b0c3f
@ -164,7 +164,7 @@ def setup_custom_environment(self, pkg, env):
|
|||||||
out = out.decode("utf-16le", errors="replace") # novermin
|
out = out.decode("utf-16le", errors="replace") # novermin
|
||||||
|
|
||||||
int_env = dict(
|
int_env = dict(
|
||||||
(key.lower(), value)
|
(key, value)
|
||||||
for key, _, value in (line.partition("=") for line in out.splitlines())
|
for key, _, value in (line.partition("=") for line in out.splitlines())
|
||||||
if key and value
|
if key and value
|
||||||
)
|
)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
from functools import wraps
|
||||||
from typing import Any, Callable, Dict, List, MutableMapping, Optional, Tuple, Union
|
from typing import Any, Callable, Dict, List, MutableMapping, Optional, Tuple, Union
|
||||||
|
|
||||||
from llnl.util import tty
|
from llnl.util import tty
|
||||||
@ -83,6 +84,28 @@ def double_quote_escape(s):
|
|||||||
return '"' + s.replace('"', r"\"") + '"'
|
return '"' + s.replace('"', r"\"") + '"'
|
||||||
|
|
||||||
|
|
||||||
|
def system_env_normalize(func):
|
||||||
|
"""Decorator wrapping calls to system env modifications,
|
||||||
|
converting all env variable names to all upper case on Windows, no-op
|
||||||
|
on other platforms before calling env modification method.
|
||||||
|
|
||||||
|
Windows, due to a DOS holdover, treats all env variable names case
|
||||||
|
insensitively, however Spack's env modification class does not,
|
||||||
|
meaning setting `Path` and `PATH` would be distinct env operations
|
||||||
|
for Spack, but would cause a collision when actually performing the
|
||||||
|
env modification operations on the env.
|
||||||
|
Normalize all env names to all caps to prevent this collision from the
|
||||||
|
Spack side."""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
def case_insensitive_modification(self, name: str, *args, **kwargs):
|
||||||
|
if sys.platform == "win32":
|
||||||
|
name = name.upper()
|
||||||
|
return func(self, name, *args, **kwargs)
|
||||||
|
|
||||||
|
return case_insensitive_modification
|
||||||
|
|
||||||
|
|
||||||
def is_system_path(path: Path) -> bool:
|
def is_system_path(path: Path) -> bool:
|
||||||
"""Returns True if the argument is a system path, False otherwise."""
|
"""Returns True if the argument is a system path, False otherwise."""
|
||||||
return bool(path) and (os.path.normpath(path) in SYSTEM_DIRS)
|
return bool(path) and (os.path.normpath(path) in SYSTEM_DIRS)
|
||||||
@ -466,6 +489,7 @@ def _trace(self) -> Optional[Trace]:
|
|||||||
|
|
||||||
return Trace(filename=filename, lineno=lineno, context=current_context)
|
return Trace(filename=filename, lineno=lineno, context=current_context)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def set(self, name: str, value: str, *, force: bool = False):
|
def set(self, name: str, value: str, *, force: bool = False):
|
||||||
"""Stores a request to set an environment variable.
|
"""Stores a request to set an environment variable.
|
||||||
|
|
||||||
@ -477,6 +501,7 @@ def set(self, name: str, value: str, *, force: bool = False):
|
|||||||
item = SetEnv(name, value, trace=self._trace(), force=force)
|
item = SetEnv(name, value, trace=self._trace(), force=force)
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def append_flags(self, name: str, value: str, sep: str = " "):
|
def append_flags(self, name: str, value: str, sep: str = " "):
|
||||||
"""Stores a request to append 'flags' to an environment variable.
|
"""Stores a request to append 'flags' to an environment variable.
|
||||||
|
|
||||||
@ -488,6 +513,7 @@ def append_flags(self, name: str, value: str, sep: str = " "):
|
|||||||
item = AppendFlagsEnv(name, value, separator=sep, trace=self._trace())
|
item = AppendFlagsEnv(name, value, separator=sep, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def unset(self, name: str):
|
def unset(self, name: str):
|
||||||
"""Stores a request to unset an environment variable.
|
"""Stores a request to unset an environment variable.
|
||||||
|
|
||||||
@ -497,6 +523,7 @@ def unset(self, name: str):
|
|||||||
item = UnsetEnv(name, trace=self._trace())
|
item = UnsetEnv(name, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def remove_flags(self, name: str, value: str, sep: str = " "):
|
def remove_flags(self, name: str, value: str, sep: str = " "):
|
||||||
"""Stores a request to remove flags from an environment variable
|
"""Stores a request to remove flags from an environment variable
|
||||||
|
|
||||||
@ -508,6 +535,7 @@ def remove_flags(self, name: str, value: str, sep: str = " "):
|
|||||||
item = RemoveFlagsEnv(name, value, separator=sep, trace=self._trace())
|
item = RemoveFlagsEnv(name, value, separator=sep, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def set_path(self, name: str, elements: List[str], separator: str = os.pathsep):
|
def set_path(self, name: str, elements: List[str], separator: str = os.pathsep):
|
||||||
"""Stores a request to set an environment variable to a list of paths,
|
"""Stores a request to set an environment variable to a list of paths,
|
||||||
separated by a character defined in input.
|
separated by a character defined in input.
|
||||||
@ -520,6 +548,7 @@ def set_path(self, name: str, elements: List[str], separator: str = os.pathsep):
|
|||||||
item = SetPath(name, elements, separator=separator, trace=self._trace())
|
item = SetPath(name, elements, separator=separator, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def append_path(self, name: str, path: str, separator: str = os.pathsep):
|
def append_path(self, name: str, path: str, separator: str = os.pathsep):
|
||||||
"""Stores a request to append a path to list of paths.
|
"""Stores a request to append a path to list of paths.
|
||||||
|
|
||||||
@ -531,6 +560,7 @@ def append_path(self, name: str, path: str, separator: str = os.pathsep):
|
|||||||
item = AppendPath(name, path, separator=separator, trace=self._trace())
|
item = AppendPath(name, path, separator=separator, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def prepend_path(self, name: str, path: str, separator: str = os.pathsep):
|
def prepend_path(self, name: str, path: str, separator: str = os.pathsep):
|
||||||
"""Stores a request to prepend a path to list of paths.
|
"""Stores a request to prepend a path to list of paths.
|
||||||
|
|
||||||
@ -542,6 +572,7 @@ def prepend_path(self, name: str, path: str, separator: str = os.pathsep):
|
|||||||
item = PrependPath(name, path, separator=separator, trace=self._trace())
|
item = PrependPath(name, path, separator=separator, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def remove_path(self, name: str, path: str, separator: str = os.pathsep):
|
def remove_path(self, name: str, path: str, separator: str = os.pathsep):
|
||||||
"""Stores a request to remove a path from a list of paths.
|
"""Stores a request to remove a path from a list of paths.
|
||||||
|
|
||||||
@ -553,6 +584,7 @@ def remove_path(self, name: str, path: str, separator: str = os.pathsep):
|
|||||||
item = RemovePath(name, path, separator=separator, trace=self._trace())
|
item = RemovePath(name, path, separator=separator, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def deprioritize_system_paths(self, name: str, separator: str = os.pathsep):
|
def deprioritize_system_paths(self, name: str, separator: str = os.pathsep):
|
||||||
"""Stores a request to deprioritize system paths in a path list,
|
"""Stores a request to deprioritize system paths in a path list,
|
||||||
otherwise preserving the order.
|
otherwise preserving the order.
|
||||||
@ -564,6 +596,7 @@ def deprioritize_system_paths(self, name: str, separator: str = os.pathsep):
|
|||||||
item = DeprioritizeSystemPaths(name, separator=separator, trace=self._trace())
|
item = DeprioritizeSystemPaths(name, separator=separator, trace=self._trace())
|
||||||
self.env_modifications.append(item)
|
self.env_modifications.append(item)
|
||||||
|
|
||||||
|
@system_env_normalize
|
||||||
def prune_duplicate_paths(self, name: str, separator: str = os.pathsep):
|
def prune_duplicate_paths(self, name: str, separator: str = os.pathsep):
|
||||||
"""Stores a request to remove duplicates from a path list, otherwise
|
"""Stores a request to remove duplicates from a path list, otherwise
|
||||||
preserving the order.
|
preserving the order.
|
||||||
|
Loading…
Reference in New Issue
Block a user