From 0c33133285465ee11fc3c2de148a0259c8e5da5f Mon Sep 17 00:00:00 2001 From: Jacob Healy Date: Wed, 15 Jan 2025 07:56:43 -0700 Subject: [PATCH] Fix additional location were dev_path was imporperly constructed The dev_path must be quoted to avoid parsing issues when paths contain '@' symbols. Also add tests to catch regression of this behavior --- lib/spack/spack/cmd/dev_build.py | 2 +- lib/spack/spack/test/cmd/dev_build.py | 13 ++++++++++++ lib/spack/spack/test/concretization/core.py | 23 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/spack/spack/cmd/dev_build.py b/lib/spack/spack/cmd/dev_build.py index 26bc011672f..429be35d595 100644 --- a/lib/spack/spack/cmd/dev_build.py +++ b/lib/spack/spack/cmd/dev_build.py @@ -113,7 +113,7 @@ def dev_build(self, args): source_path = os.path.abspath(source_path) # Forces the build to run out of the source directory. - spec.constrain("dev_path=%s" % source_path) + spec.constrain(f'dev_path="{source_path}"') spec.concretize() if spec.installed: diff --git a/lib/spack/spack/test/cmd/dev_build.py b/lib/spack/spack/test/cmd/dev_build.py index f5349e2015b..b68d1d1eb72 100644 --- a/lib/spack/spack/test/cmd/dev_build.py +++ b/lib/spack/spack/test/cmd/dev_build.py @@ -168,6 +168,19 @@ def test_dev_build_fails_no_version(mock_packages): assert "dev-build spec must have a single, concrete version" in output +def test_dev_build_can_parse_path_with_at_symbol(tmpdir, install_mockery): + special_char_dir = tmpdir.mkdir("tmp@place") + spec = spack.spec.Spec("dev-build-test-install@0.0.0") + spec.concretize() + + with special_char_dir.as_cwd(): + with open(spec.package.filename, "w", encoding="utf-8") as f: + f.write(spec.package.original_string) + + dev_build("dev-build-test-install@0.0.0") + assert spec.package.filename in os.listdir(spec.prefix) + + def test_dev_build_env(tmpdir, install_mockery, mutable_mock_env_path): """Test Spack does dev builds for packages in develop section of env.""" # setup dev-build-test-install package for dev build diff --git a/lib/spack/spack/test/concretization/core.py b/lib/spack/spack/test/concretization/core.py index 3f10a7e0eca..e372f3d3fd7 100644 --- a/lib/spack/spack/test/concretization/core.py +++ b/lib/spack/spack/test/concretization/core.py @@ -20,6 +20,7 @@ import spack.config import spack.deptypes as dt import spack.detection +import spack.environment as ev import spack.error import spack.hash_types as ht import spack.paths @@ -33,6 +34,7 @@ import spack.util.file_cache import spack.variant as vt from spack.installer import PackageInstaller +from spack.main import SpackCommand from spack.spec import CompilerSpec, Spec from spack.version import Version, VersionList, ver @@ -3218,3 +3220,24 @@ def test_spec_unification(unify, mutable_config, mock_packages): maybe_fails = pytest.raises if unify is True else llnl.util.lang.nullcontext with maybe_fails(spack.solver.asp.UnsatisfiableSpecError): _ = spack.cmd.parse_specs([a_restricted, b], concretize=True) + + +def test_concretize_dev_path_with_at_symbol_in_env(tmpdir, mock_packages): + spec_like = "zlib@2.0" + spec = Spec(spec_like) + add = SpackCommand("add") + develop = SpackCommand("develop") + + develop_dir = tmpdir.mkdir("build@location") + envdir = tmpdir.mkdir("env") + with ev.create_in_dir(envdir): + add(spec_like) + develop(f"--path={develop_dir}", spec_like) + solver = spack.solver.asp.Solver() + result = solver.solve([spec]) + + assert len(result.specs) == 1 + for spec in result.specs: + assert spec.satisfies(spec_like) + assert develop_dir in spec.variants["dev_path"] + assert not result.unsolved_specs