Skip to content

Commit 7cfdf61

Browse files
Fix location in spec.yaml where we look for full_hash (#19132)
When we attempt to determine whether a remote spec (in a binary mirror) is up-to-date or needs to be rebuilt, we compare the full_hash stored in the remote spec.yaml file against the full_hash computed from the local concrete spec. Since the full_hash moved into the spec (and is no longer at the top level of the spec.yaml), we need to look there for it. This oversight from #18359 was causing all specs to get rebuilt when the full_hash wasn't fouhd at the expected location.
1 parent 670f3a5 commit 7cfdf61

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

lib/spack/spack/binary_distribution.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,23 +1407,38 @@ def needs_rebuild(spec, mirror_url, rebuild_on_errors=False):
14071407

14081408
spec_yaml = syaml.load(yaml_contents)
14091409

1410+
yaml_spec = spec_yaml['spec']
1411+
name = spec.name
1412+
1413+
# The "spec" key in the yaml is a list of objects, each with a single
1414+
# key that is the package name. While the list usually just contains
1415+
# a single object, we iterate over the list looking for the object
1416+
# with the name of this concrete spec as a key, out of an abundance
1417+
# of caution.
1418+
cached_pkg_specs = [item[name] for item in yaml_spec if name in item]
1419+
cached_target = cached_pkg_specs[0] if cached_pkg_specs else None
1420+
14101421
# If either the full_hash didn't exist in the .spec.yaml file, or it
14111422
# did, but didn't match the one we computed locally, then we should
14121423
# just rebuild. This can be simplified once the dag_hash and the
14131424
# full_hash become the same thing.
1414-
if ('full_hash' not in spec_yaml or
1415-
spec_yaml['full_hash'] != pkg_full_hash):
1416-
if 'full_hash' in spec_yaml:
1425+
rebuild = False
1426+
if not cached_target or 'full_hash' not in cached_target:
1427+
reason = 'full_hash was missing from remote spec.yaml'
1428+
rebuild = True
1429+
else:
1430+
full_hash = cached_target['full_hash']
1431+
if full_hash != pkg_full_hash:
14171432
reason = 'hash mismatch, remote = {0}, local = {1}'.format(
1418-
spec_yaml['full_hash'], pkg_full_hash)
1419-
else:
1420-
reason = 'full_hash was missing from remote spec.yaml'
1433+
full_hash, pkg_full_hash)
1434+
rebuild = True
1435+
1436+
if rebuild:
14211437
tty.msg('Rebuilding {0}, reason: {1}'.format(
14221438
spec.short_spec, reason))
14231439
tty.msg(spec.tree())
1424-
return True
14251440

1426-
return False
1441+
return rebuild
14271442

14281443

14291444
def check_specs_against_mirrors(mirrors, specs, output_file=None,

lib/spack/spack/test/bindist.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import spack.cmd.install as install
2020
import spack.cmd.uninstall as uninstall
2121
import spack.cmd.mirror as mirror
22+
from spack.main import SpackCommand
2223
import spack.mirror
2324
import spack.util.gpg
2425
from spack.directory_layout import YamlDirectoryLayout
@@ -31,6 +32,11 @@
3132
mirror_path_def = None
3233
mirror_path_rel = None
3334

35+
mirror_cmd = SpackCommand('mirror')
36+
install_cmd = SpackCommand('install')
37+
uninstall_cmd = SpackCommand('uninstall')
38+
buildcache_cmd = SpackCommand('buildcache')
39+
3440

3541
@pytest.fixture(scope='function')
3642
def cache_directory(tmpdir):
@@ -569,3 +575,37 @@ def test_built_spec_cache(tmpdir,
569575
margs = mparser.parse_args(
570576
['rm', '--scope', 'site', 'test-mirror-rel'])
571577
mirror.mirror(mparser, margs)
578+
579+
580+
def test_spec_needs_rebuild(install_mockery_mutable_config, mock_packages,
581+
mock_fetch, monkeypatch, tmpdir):
582+
"""Make sure needs_rebuild properly comares remote full_hash
583+
against locally computed one, avoiding unnecessary rebuilds"""
584+
585+
# Create a temp mirror directory for buildcache usage
586+
mirror_dir = tmpdir.join('mirror_dir')
587+
mirror_url = 'file://{0}'.format(mirror_dir.strpath)
588+
589+
mirror_cmd('add', 'test-mirror', mirror_url)
590+
591+
s = Spec('libdwarf').concretized()
592+
593+
# Install a package
594+
install_cmd(s.name)
595+
596+
# Put installed package in the buildcache
597+
buildcache_cmd('create', '-u', '-a', '-d', mirror_dir.strpath, s.name)
598+
599+
rebuild = bindist.needs_rebuild(s, mirror_url, rebuild_on_errors=True)
600+
601+
assert not rebuild
602+
603+
# Now monkey patch Spec to change the full hash on the package
604+
def fake_full_hash(spec):
605+
print('fake_full_hash')
606+
return 'tal4c7h4z0gqmixb1eqa92mjoybxn5l6'
607+
monkeypatch.setattr(spack.spec.Spec, 'full_hash', fake_full_hash)
608+
609+
rebuild = bindist.needs_rebuild(s, mirror_url, rebuild_on_errors=True)
610+
611+
assert rebuild

0 commit comments

Comments
 (0)