module files: system paths are excluded from path inspection (#5460)
closes #5201 Currently, if a user sets an external package to have a prefix that is one of the system paths (like '/usr') the module files that are generated will prepend '/usr/bin' to 'PATH', etc. This is particularly nasty at the time when a module file is unloaded, and e.g. paths like '/usr/bin' will be discarded from PATH. This PR solves the issue skipping system paths when a prefix inspection is made to generate module files.
This commit is contained in:
parent
64311e8510
commit
8864d145e9
@ -502,25 +502,56 @@ def filter_environment_blacklist(env, variables):
|
||||
yield item
|
||||
|
||||
|
||||
def inspect_path(root, inspections):
|
||||
"""Inspects a path to search for the subdirectories specified in the
|
||||
inspection dictionary. Return a list of commands that will modify the
|
||||
environment accordingly.
|
||||
def inspect_path(root, inspections, exclude=None):
|
||||
"""Inspects ``root`` to search for the subdirectories in ``inspections``.
|
||||
Adds every path found to a list of prepend-path commands and returns it.
|
||||
|
||||
Args:
|
||||
root: path where to search for subdirectories
|
||||
inspections: dictionary that maps subdirectories to a list of
|
||||
variables that we want to pre-pend with a path, if found
|
||||
root (str): absolute path where to search for subdirectories
|
||||
|
||||
inspections (dict): maps relative paths to a list of environment
|
||||
variables that will be modified if the path exists. The
|
||||
modifications are not performed immediately, but stored in a
|
||||
command object that is returned to client
|
||||
|
||||
exclude (callable): optional callable. If present it must accept an
|
||||
absolute path and return True if it should be excluded from the
|
||||
inspection
|
||||
|
||||
Examples:
|
||||
|
||||
The following lines execute an inspection in ``/usr`` to search for
|
||||
``/usr/include`` and ``/usr/lib64``. If found we want to prepend
|
||||
``/usr/include`` to ``CPATH`` and ``/usr/lib64`` to ``MY_LIB64_PATH``.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Set up the dictionary containing the inspection
|
||||
inspections = {
|
||||
'include': ['CPATH'],
|
||||
'lib64': ['MY_LIB64_PATH']
|
||||
}
|
||||
|
||||
# Get back the list of command needed to modify the environment
|
||||
env = inspect_path('/usr', inspections)
|
||||
|
||||
# Eventually execute the commands
|
||||
env.apply_modifications()
|
||||
|
||||
Returns:
|
||||
instance of EnvironmentModifications containing the requested
|
||||
modifications
|
||||
"""
|
||||
if exclude is None:
|
||||
exclude = lambda x: False
|
||||
|
||||
env = EnvironmentModifications()
|
||||
# Inspect the prefix to check for the existence of common directories
|
||||
for relative_path, variables in inspections.items():
|
||||
expected = os.path.join(root, relative_path)
|
||||
if os.path.isdir(expected):
|
||||
|
||||
if os.path.isdir(expected) and not exclude(expected):
|
||||
for variable in variables:
|
||||
env.prepend_path(variable, expected)
|
||||
|
||||
return env
|
||||
|
@ -61,6 +61,7 @@
|
||||
import spack.environment
|
||||
import spack.tengine as tengine
|
||||
import spack.util.path
|
||||
import spack.util.environment
|
||||
import spack.error
|
||||
|
||||
#: Root folders where the various module files should be written
|
||||
@ -473,7 +474,9 @@ def environment_modifications(self):
|
||||
"""List of environment modifications to be processed."""
|
||||
# Modifications guessed inspecting the spec prefix
|
||||
env = spack.environment.inspect_path(
|
||||
self.spec.prefix, prefix_inspections
|
||||
self.spec.prefix,
|
||||
prefix_inspections,
|
||||
exclude=spack.util.environment.is_system_path
|
||||
)
|
||||
|
||||
# Modifications that are coded at package level
|
||||
|
@ -30,7 +30,7 @@
|
||||
from spack.environment import EnvironmentModifications
|
||||
from spack.environment import RemovePath, PrependPath, AppendPath
|
||||
from spack.environment import SetEnv, UnsetEnv
|
||||
from spack.util.environment import filter_system_paths
|
||||
from spack.util.environment import filter_system_paths, is_system_path
|
||||
|
||||
|
||||
def test_inspect_path(tmpdir):
|
||||
@ -60,6 +60,20 @@ def test_inspect_path(tmpdir):
|
||||
assert 'CPATH' in names
|
||||
|
||||
|
||||
def test_exclude_paths_from_inspection():
|
||||
inspections = {
|
||||
'lib': ['LIBRARY_PATH', 'LD_LIBRARY_PATH'],
|
||||
'lib64': ['LIBRARY_PATH', 'LD_LIBRARY_PATH'],
|
||||
'include': ['CPATH']
|
||||
}
|
||||
|
||||
env = environment.inspect_path(
|
||||
'/usr', inspections, exclude=is_system_path
|
||||
)
|
||||
|
||||
assert len(env) == 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def prepare_environment_for_tests():
|
||||
"""Sets a few dummy variables in the current environment, that will be
|
||||
|
@ -30,8 +30,21 @@
|
||||
system_paths
|
||||
|
||||
|
||||
def is_system_path(path):
|
||||
"""Predicate that given a path returns True if it is a system path,
|
||||
False otherwise.
|
||||
|
||||
Args:
|
||||
path (str): path to a directory
|
||||
|
||||
Returns:
|
||||
True or False
|
||||
"""
|
||||
return os.path.normpath(path) in system_dirs
|
||||
|
||||
|
||||
def filter_system_paths(paths):
|
||||
return [p for p in paths if os.path.normpath(p) not in system_dirs]
|
||||
return [p for p in paths if not is_system_path(p)]
|
||||
|
||||
|
||||
def get_path(name):
|
||||
|
Loading…
Reference in New Issue
Block a user