summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn W. Parent <45471568+johnwparent@users.noreply.github.com>2023-04-21 14:38:58 -0400
committerGitHub <noreply@github.com>2023-04-21 11:38:58 -0700
commitd8451b0c3f9ded4c7703fdefb102371138a4189c (patch)
tree9a0765916301249401e4c5568053375656ad55f7 /lib
parent255c9ed5e9febdcd5e7f774889e1b9690f3ec593 (diff)
downloadspack-d8451b0c3f9ded4c7703fdefb102371138a4189c.tar.gz
spack-d8451b0c3f9ded4c7703fdefb102371138a4189c.tar.bz2
spack-d8451b0c3f9ded4c7703fdefb102371138a4189c.tar.xz
spack-d8451b0c3f9ded4c7703fdefb102371138a4189c.zip
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/compilers/msvc.py2
-rw-r--r--lib/spack/spack/util/environment.py33
2 files changed, 34 insertions, 1 deletions
diff --git a/lib/spack/spack/compilers/msvc.py b/lib/spack/spack/compilers/msvc.py
index 061555a500..87e6e42af4 100644
--- a/lib/spack/spack/compilers/msvc.py
+++ b/lib/spack/spack/compilers/msvc.py
@@ -164,7 +164,7 @@ class Msvc(Compiler):
out = out.decode("utf-16le", errors="replace") # novermin
int_env = dict(
- (key.lower(), value)
+ (key, value)
for key, _, value in (line.partition("=") for line in out.splitlines())
if key and value
)
diff --git a/lib/spack/spack/util/environment.py b/lib/spack/spack/util/environment.py
index 64082ff313..0eed2726b4 100644
--- a/lib/spack/spack/util/environment.py
+++ b/lib/spack/spack/util/environment.py
@@ -14,6 +14,7 @@ import platform
import re
import socket
import sys
+from functools import wraps
from typing import Any, Callable, Dict, List, MutableMapping, Optional, Tuple, Union
from llnl.util import tty
@@ -83,6 +84,28 @@ def double_quote_escape(s):
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:
"""Returns True if the argument is a system path, False otherwise."""
return bool(path) and (os.path.normpath(path) in SYSTEM_DIRS)
@@ -466,6 +489,7 @@ class EnvironmentModifications:
return Trace(filename=filename, lineno=lineno, context=current_context)
+ @system_env_normalize
def set(self, name: str, value: str, *, force: bool = False):
"""Stores a request to set an environment variable.
@@ -477,6 +501,7 @@ class EnvironmentModifications:
item = SetEnv(name, value, trace=self._trace(), force=force)
self.env_modifications.append(item)
+ @system_env_normalize
def append_flags(self, name: str, value: str, sep: str = " "):
"""Stores a request to append 'flags' to an environment variable.
@@ -488,6 +513,7 @@ class EnvironmentModifications:
item = AppendFlagsEnv(name, value, separator=sep, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def unset(self, name: str):
"""Stores a request to unset an environment variable.
@@ -497,6 +523,7 @@ class EnvironmentModifications:
item = UnsetEnv(name, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def remove_flags(self, name: str, value: str, sep: str = " "):
"""Stores a request to remove flags from an environment variable
@@ -508,6 +535,7 @@ class EnvironmentModifications:
item = RemoveFlagsEnv(name, value, separator=sep, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
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,
separated by a character defined in input.
@@ -520,6 +548,7 @@ class EnvironmentModifications:
item = SetPath(name, elements, separator=separator, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def append_path(self, name: str, path: str, separator: str = os.pathsep):
"""Stores a request to append a path to list of paths.
@@ -531,6 +560,7 @@ class EnvironmentModifications:
item = AppendPath(name, path, separator=separator, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def prepend_path(self, name: str, path: str, separator: str = os.pathsep):
"""Stores a request to prepend a path to list of paths.
@@ -542,6 +572,7 @@ class EnvironmentModifications:
item = PrependPath(name, path, separator=separator, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def remove_path(self, name: str, path: str, separator: str = os.pathsep):
"""Stores a request to remove a path from a list of paths.
@@ -553,6 +584,7 @@ class EnvironmentModifications:
item = RemovePath(name, path, separator=separator, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def deprioritize_system_paths(self, name: str, separator: str = os.pathsep):
"""Stores a request to deprioritize system paths in a path list,
otherwise preserving the order.
@@ -564,6 +596,7 @@ class EnvironmentModifications:
item = DeprioritizeSystemPaths(name, separator=separator, trace=self._trace())
self.env_modifications.append(item)
+ @system_env_normalize
def prune_duplicate_paths(self, name: str, separator: str = os.pathsep):
"""Stores a request to remove duplicates from a path list, otherwise
preserving the order.