summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHarmen Stoppels <harmenstoppels@gmail.com>2023-05-04 10:09:22 +0200
committerGitHub <noreply@github.com>2023-05-04 10:09:22 +0200
commit84a70c26d90ff82bd3568682b1a5a3615829d11f (patch)
tree5da9383d7f2e8b4263d3b9408beebf52ddf1fe8f /lib
parent3bfd948ec84e320c1a06ab4af272c629fe0126de (diff)
downloadspack-84a70c26d90ff82bd3568682b1a5a3615829d11f.tar.gz
spack-84a70c26d90ff82bd3568682b1a5a3615829d11f.tar.bz2
spack-84a70c26d90ff82bd3568682b1a5a3615829d11f.tar.xz
spack-84a70c26d90ff82bd3568682b1a5a3615829d11f.zip
buildcache metadata: store hash -> prefix mapping (#37404)
This ensures that: a) no externals are added to the tarball metadata file b) no externals are added to the prefix to prefix map on install, also for old tarballs that did include externals c) ensure that the prefix -> prefix map is always string to string, and doesn't contain None in case for some reason a hash is missing
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/binary_distribution.py40
1 files changed, 22 insertions, 18 deletions
diff --git a/lib/spack/spack/binary_distribution.py b/lib/spack/spack/binary_distribution.py
index fa49f6b984..f486238037 100644
--- a/lib/spack/spack/binary_distribution.py
+++ b/lib/spack/spack/binary_distribution.py
@@ -744,12 +744,14 @@ def get_buildfile_manifest(spec):
return data
-def prefixes_to_hashes(spec):
+def hashes_to_prefixes(spec):
+ """Return a dictionary of hashes to prefixes for a spec and its deps, excluding externals"""
return {
- str(s.prefix): s.dag_hash()
+ s.dag_hash(): str(s.prefix)
for s in itertools.chain(
spec.traverse(root=True, deptype="link"), spec.dependencies(deptype="run")
)
+ if not s.external
}
@@ -767,7 +769,7 @@ def get_buildinfo_dict(spec, rel=False):
"relocate_binaries": manifest["binary_to_relocate"],
"relocate_links": manifest["link_to_relocate"],
"hardlinks_deduped": manifest["hardlinks_deduped"],
- "prefix_to_hash": prefixes_to_hashes(spec),
+ "hash_to_prefix": hashes_to_prefixes(spec),
}
@@ -1680,22 +1682,22 @@ def relocate_package(spec, allow_root):
old_rel_prefix = buildinfo.get("relative_prefix")
old_prefix = os.path.join(old_layout_root, old_rel_prefix)
rel = buildinfo.get("relative_rpaths")
- prefix_to_hash = buildinfo.get("prefix_to_hash", None)
- if old_rel_prefix != new_rel_prefix and not prefix_to_hash:
+
+ # In the past prefix_to_hash was the default and externals were not dropped, so prefixes
+ # were not unique.
+ if "hash_to_prefix" in buildinfo:
+ hash_to_old_prefix = buildinfo["hash_to_prefix"]
+ elif "prefix_to_hash" in buildinfo:
+ hash_to_old_prefix = dict((v, k) for (k, v) in buildinfo["prefix_to_hash"].items())
+ else:
+ hash_to_old_prefix = dict()
+
+ if old_rel_prefix != new_rel_prefix and not hash_to_old_prefix:
msg = "Package tarball was created from an install "
msg += "prefix with a different directory layout and an older "
msg += "buildcache create implementation. It cannot be relocated."
raise NewLayoutException(msg)
- # older buildcaches do not have the prefix_to_hash dictionary
- # need to set an empty dictionary and add one entry to
- # prefix_to_prefix to reproduce the old behavior
- if not prefix_to_hash:
- prefix_to_hash = dict()
- hash_to_prefix = dict()
- hash_to_prefix[spec.format("{hash}")] = str(spec.package.prefix)
- new_deps = spack.build_environment.get_rpath_deps(spec.package)
- for d in new_deps + spec.dependencies(deptype="run"):
- hash_to_prefix[d.format("{hash}")] = str(d.prefix)
+
# Spurious replacements (e.g. sbang) will cause issues with binaries
# For example, the new sbang can be longer than the old one.
# Hence 2 dictionaries are maintained here.
@@ -1709,9 +1711,11 @@ def relocate_package(spec, allow_root):
# First match specific prefix paths. Possibly the *local* install prefix
# of some dependency is in an upstream, so we cannot assume the original
# spack store root can be mapped uniformly to the new spack store root.
- for orig_prefix, hash in prefix_to_hash.items():
- prefix_to_prefix_text[orig_prefix] = hash_to_prefix.get(hash, None)
- prefix_to_prefix_bin[orig_prefix] = hash_to_prefix.get(hash, None)
+ for dag_hash, new_dep_prefix in hashes_to_prefixes(spec).items():
+ if dag_hash in hash_to_old_prefix:
+ old_dep_prefix = hash_to_old_prefix[dag_hash]
+ prefix_to_prefix_bin[old_dep_prefix] = new_dep_prefix
+ prefix_to_prefix_text[old_dep_prefix] = new_dep_prefix
# Only then add the generic fallback of install prefix -> install prefix.
prefix_to_prefix_text[old_prefix] = new_prefix