summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPeter Scheibel <scheibel1@llnl.gov>2023-07-18 00:53:33 -0700
committerGitHub <noreply@github.com>2023-07-18 09:53:33 +0200
commit10165397da8bf1b6cd478de752b79cf58ca2b1dc (patch)
tree514c6343bbf2d576a4c5fd25ee415f13c34bfc1f /lib
parentaf60b802f7d1b1bb1cce31fd76570d442493fddd (diff)
downloadspack-10165397da8bf1b6cd478de752b79cf58ca2b1dc.tar.gz
spack-10165397da8bf1b6cd478de752b79cf58ca2b1dc.tar.bz2
spack-10165397da8bf1b6cd478de752b79cf58ca2b1dc.tar.xz
spack-10165397da8bf1b6cd478de752b79cf58ca2b1dc.zip
"spack develop": always pull full history for git repos (#38343)
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/develop.py3
-rw-r--r--lib/spack/spack/environment/environment.py21
-rw-r--r--lib/spack/spack/stage.py6
-rw-r--r--lib/spack/spack/test/cmd/develop.py45
4 files changed, 66 insertions, 9 deletions
diff --git a/lib/spack/spack/cmd/develop.py b/lib/spack/spack/cmd/develop.py
index 5f59984182..ac7e89596f 100644
--- a/lib/spack/spack/cmd/develop.py
+++ b/lib/spack/spack/cmd/develop.py
@@ -66,8 +66,7 @@ def develop(parser, args):
# Both old syntax `spack develop pkg@x` and new syntax `spack develop pkg@=x`
# are currently supported.
spec = spack.spec.parse_with_version_concrete(entry["spec"])
- pkg_cls = spack.repo.path.get_pkg_class(spec.name)
- pkg_cls(spec).stage.steal_source(abspath)
+ env.develop(spec=spec, path=path, clone=True)
if not env.dev_specs:
tty.warn("No develop specs to download")
diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py
index 9d475973e8..1602e4369d 100644
--- a/lib/spack/spack/environment/environment.py
+++ b/lib/spack/spack/environment/environment.py
@@ -1256,16 +1256,23 @@ class Environment:
tty.msg("Configuring spec %s for development at path %s" % (spec, path))
if clone:
- # "steal" the source code via staging API
- abspath = spack.util.path.canonicalize_path(path, default_wd=self.path)
-
- # Stage, at the moment, requires a concrete Spec, since it needs the
- # dag_hash for the stage dir name. Below though we ask for a stage
- # to be created, to copy it afterwards somewhere else. It would be
+ # "steal" the source code via staging API. We ask for a stage
+ # to be created, then copy it afterwards somewhere else. It would be
# better if we can create the `source_path` directly into its final
# destination.
+ abspath = spack.util.path.canonicalize_path(path, default_wd=self.path)
pkg_cls = spack.repo.path.get_pkg_class(spec.name)
- pkg_cls(spec).stage.steal_source(abspath)
+ # We construct a package class ourselves, rather than asking for
+ # Spec.package, since Spec only allows this when it is concrete
+ package = pkg_cls(spec)
+ if isinstance(package.fetcher[0], spack.fetch_strategy.GitFetchStrategy):
+ package.fetcher[0].get_full_repo = True
+ # If we retrieved this version before and cached it, we may have
+ # done so without cloning the full git repo; likewise, any
+ # mirror might store an instance with truncated history.
+ package.stage[0].disable_mirrors()
+
+ package.stage.steal_source(abspath)
# If it wasn't already in the list, append it
entry = {"path": path, "spec": str(spec)}
diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py
index 6a5297dce2..5049312e47 100644
--- a/lib/spack/spack/stage.py
+++ b/lib/spack/spack/stage.py
@@ -429,6 +429,12 @@ class Stage:
"""Returns the well-known source directory path."""
return os.path.join(self.path, _source_path_subdir)
+ def disable_mirrors(self):
+ """The Stage will not attempt to look for the associated fetcher
+ target in any of Spack's mirrors (including the local download cache).
+ """
+ self.mirror_paths = []
+
def fetch(self, mirror_only=False, err_msg=None):
"""Retrieves the code or archive
diff --git a/lib/spack/spack/test/cmd/develop.py b/lib/spack/spack/test/cmd/develop.py
index 2d339f56a8..e9f496c021 100644
--- a/lib/spack/spack/test/cmd/develop.py
+++ b/lib/spack/spack/test/cmd/develop.py
@@ -146,3 +146,48 @@ class TestDevelop:
# Check modifications actually worked
assert spack.spec.Spec("mpich@1.0").concretized().satisfies("dev_path=%s" % abspath)
+
+
+def _git_commit_list(git_repo_dir):
+ git = spack.util.git.git()
+ with fs.working_dir(git_repo_dir):
+ output = git("log", "--pretty=format:%h", "-n", "20", output=str)
+ return output.strip().split()
+
+
+def test_develop_full_git_repo(
+ mutable_mock_env_path,
+ mock_git_version_info,
+ install_mockery,
+ mock_packages,
+ monkeypatch,
+ tmpdir,
+ mutable_config,
+ request,
+):
+ repo_path, filename, commits = mock_git_version_info
+ monkeypatch.setattr(
+ spack.package_base.PackageBase, "git", "file://%s" % repo_path, raising=False
+ )
+
+ spec = spack.spec.Spec("git-test-commit@1.2").concretized()
+ try:
+ spec.package.do_stage()
+ commits = _git_commit_list(spec.package.stage[0].source_path)
+ # Outside of "spack develop" Spack will only pull exactly the commit it
+ # needs, with no additional history
+ assert len(commits) == 1
+ finally:
+ spec.package.do_clean()
+
+ # Now use "spack develop": look at the resulting stage directory and make
+ # sure the git repo pulled includes the full branch history (or rather,
+ # more than just one commit).
+ env("create", "test")
+ with ev.read("test"):
+ develop("git-test-commit@1.2")
+
+ location = SpackCommand("location")
+ develop_stage_dir = location("git-test-commit").strip()
+ commits = _git_commit_list(develop_stage_dir)
+ assert len(commits) > 1