spack env create <env>: dir if dir-like (#44024)
				
					
				
			A named env cannot contain `.` and `/`. So when a user runs `spack env create ./here` do not error but treat it as `spack env create -d ./here`. Also fix help string of `spack env create`, which seems to have been copied from `activate` incorrectly.
This commit is contained in:
		@@ -142,12 +142,8 @@ user's prompt to begin with the environment name in brackets.
 | 
			
		||||
   $ spack env activate -p myenv
 | 
			
		||||
   [myenv] $ ...
 | 
			
		||||
 | 
			
		||||
The ``activate`` command can also be used to create a new environment, if it is
 | 
			
		||||
not already defined, by adding the ``--create`` flag. Managed and anonymous
 | 
			
		||||
environments, anonymous environments are explained in the next section,
 | 
			
		||||
can both be created using the same flags that `spack env create` accepts.
 | 
			
		||||
If an environment already exists then spack will simply activate it and ignore the
 | 
			
		||||
create specific flags.
 | 
			
		||||
The ``activate`` command can also be used to create a new environment if it does not already
 | 
			
		||||
exist.
 | 
			
		||||
 | 
			
		||||
.. code-block:: console
 | 
			
		||||
   
 | 
			
		||||
@@ -176,21 +172,36 @@ environment will remove the view from the user environment.
 | 
			
		||||
Anonymous Environments
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^^^^
 | 
			
		||||
 | 
			
		||||
Any directory can be treated as an environment if it contains a file
 | 
			
		||||
``spack.yaml``. To load an anonymous environment, use:
 | 
			
		||||
Apart from managed environments, Spack also supports anonymous environments.
 | 
			
		||||
 | 
			
		||||
Anonymous environments can be placed in any directory of choice.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
   When uninstalling packages, Spack asks the user to confirm the removal of packages
 | 
			
		||||
   that are still used in a managed environment. This is not the case for anonymous
 | 
			
		||||
   environments.
 | 
			
		||||
 | 
			
		||||
To create an anonymous environment, use one of the following commands:
 | 
			
		||||
 | 
			
		||||
.. code-block:: console
 | 
			
		||||
 | 
			
		||||
   $ spack env activate -d /path/to/directory
 | 
			
		||||
   $ spack env create --dir my_env
 | 
			
		||||
   $ spack env create ./my_env
 | 
			
		||||
 | 
			
		||||
Anonymous specs can be created in place using the command:
 | 
			
		||||
As a shorthand, you can also create an anonymous environment upon activation if it does not
 | 
			
		||||
already exist:
 | 
			
		||||
 | 
			
		||||
.. code-block:: console
 | 
			
		||||
 | 
			
		||||
   $ spack env create -d .
 | 
			
		||||
   $ spack env activate --create ./my_env
 | 
			
		||||
 | 
			
		||||
For convenience, Spack can also place an anonymous environment in a temporary directory for you:
 | 
			
		||||
 | 
			
		||||
.. code-block:: console
 | 
			
		||||
 | 
			
		||||
   $ spack env activate --temp
 | 
			
		||||
 | 
			
		||||
In this case Spack simply creates a ``spack.yaml`` file in the requested
 | 
			
		||||
directory.
 | 
			
		||||
 | 
			
		||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | 
			
		||||
Environment Sensitive Commands
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
import llnl.util.filesystem as fs
 | 
			
		||||
import llnl.util.tty as tty
 | 
			
		||||
from llnl.util.tty.colify import colify
 | 
			
		||||
from llnl.util.tty.color import colorize
 | 
			
		||||
from llnl.util.tty.color import cescape, colorize
 | 
			
		||||
 | 
			
		||||
import spack.cmd
 | 
			
		||||
import spack.cmd.common
 | 
			
		||||
@@ -61,14 +61,7 @@
 | 
			
		||||
#
 | 
			
		||||
def env_create_setup_parser(subparser):
 | 
			
		||||
    """create a new environment"""
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        "env_name",
 | 
			
		||||
        metavar="env",
 | 
			
		||||
        help=(
 | 
			
		||||
            "name of managed environment or directory of the anonymous env "
 | 
			
		||||
            "(when using --dir/-d) to activate"
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    subparser.add_argument("env_name", metavar="env", help="name or directory of environment")
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        "-d", "--dir", action="store_true", help="create an environment in a specific directory"
 | 
			
		||||
    )
 | 
			
		||||
@@ -114,7 +107,7 @@ def env_create(args):
 | 
			
		||||
    env = _env_create(
 | 
			
		||||
        args.env_name,
 | 
			
		||||
        init_file=args.envfile,
 | 
			
		||||
        dir=args.dir,
 | 
			
		||||
        dir=args.dir or os.path.sep in args.env_name or args.env_name in (".", ".."),
 | 
			
		||||
        with_view=with_view,
 | 
			
		||||
        keep_relative=args.keep_relative,
 | 
			
		||||
    )
 | 
			
		||||
@@ -123,34 +116,39 @@ def env_create(args):
 | 
			
		||||
    env.regenerate_views()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _env_create(name_or_path, *, init_file=None, dir=False, with_view=None, keep_relative=False):
 | 
			
		||||
def _env_create(
 | 
			
		||||
    name_or_path: str,
 | 
			
		||||
    *,
 | 
			
		||||
    init_file: Optional[str] = None,
 | 
			
		||||
    dir: bool = False,
 | 
			
		||||
    with_view: Optional[str] = None,
 | 
			
		||||
    keep_relative: bool = False,
 | 
			
		||||
):
 | 
			
		||||
    """Create a new environment, with an optional yaml description.
 | 
			
		||||
 | 
			
		||||
    Arguments:
 | 
			
		||||
        name_or_path (str): name of the environment to create, or path to it
 | 
			
		||||
        init_file (str or file): optional initialization file -- can be
 | 
			
		||||
            a JSON lockfile (*.lock, *.json) or YAML manifest file
 | 
			
		||||
        dir (bool): if True, create an environment in a directory instead
 | 
			
		||||
            of a named environment
 | 
			
		||||
        keep_relative (bool): if True, develop paths are copied verbatim into
 | 
			
		||||
            the new environment file, otherwise they may be made absolute if the
 | 
			
		||||
            new environment is in a different location
 | 
			
		||||
        name_or_path: name of the environment to create, or path to it
 | 
			
		||||
        init_file: optional initialization file -- can be a JSON lockfile (*.lock, *.json) or YAML
 | 
			
		||||
            manifest file
 | 
			
		||||
        dir: if True, create an environment in a directory instead of a managed environment
 | 
			
		||||
        keep_relative: if True, develop paths are copied verbatim into the new environment file,
 | 
			
		||||
            otherwise they may be made absolute if the new environment is in a different location
 | 
			
		||||
    """
 | 
			
		||||
    if not dir:
 | 
			
		||||
        env = ev.create(
 | 
			
		||||
            name_or_path, init_file=init_file, with_view=with_view, keep_relative=keep_relative
 | 
			
		||||
        )
 | 
			
		||||
        tty.msg("Created environment '%s' in %s" % (name_or_path, env.path))
 | 
			
		||||
        tty.msg("You can activate this environment with:")
 | 
			
		||||
        tty.msg("  spack env activate %s" % (name_or_path))
 | 
			
		||||
        return env
 | 
			
		||||
 | 
			
		||||
    env = ev.create_in_dir(
 | 
			
		||||
        name_or_path, init_file=init_file, with_view=with_view, keep_relative=keep_relative
 | 
			
		||||
    )
 | 
			
		||||
    tty.msg("Created environment in %s" % env.path)
 | 
			
		||||
    tty.msg("You can activate this environment with:")
 | 
			
		||||
    tty.msg("  spack env activate %s" % env.path)
 | 
			
		||||
        tty.msg(
 | 
			
		||||
            colorize(
 | 
			
		||||
                f"Created environment @c{{{cescape(env.name)}}} in: @c{{{cescape(env.path)}}}"
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    else:
 | 
			
		||||
        env = ev.create_in_dir(
 | 
			
		||||
            name_or_path, init_file=init_file, with_view=with_view, keep_relative=keep_relative
 | 
			
		||||
        )
 | 
			
		||||
        tty.msg(colorize(f"Created anonymous environment in: @c{{{cescape(env.path)}}}"))
 | 
			
		||||
    tty.msg(f"Activate with: {colorize(f'@c{{spack env activate {cescape(name_or_path)}}}')}")
 | 
			
		||||
    return env
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3290,7 +3290,7 @@ def test_create_and_activate_managed(tmp_path):
 | 
			
		||||
def test_create_and_activate_anonymous(tmp_path):
 | 
			
		||||
    with fs.working_dir(str(tmp_path)):
 | 
			
		||||
        env_dir = os.path.join(str(tmp_path), "foo")
 | 
			
		||||
        shell = env("activate", "--without-view", "--create", "--sh", "-d", env_dir)
 | 
			
		||||
        shell = env("activate", "--without-view", "--create", "--sh", env_dir)
 | 
			
		||||
        active_env_var = next(line for line in shell.splitlines() if ev.spack_env_var in line)
 | 
			
		||||
        assert str(env_dir) in active_env_var
 | 
			
		||||
        assert ev.is_env_dir(env_dir)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user