patching: do strict version range checking (#13989)

* apply strict constraint checks for patches, otherwise Spack may incorrectly treat a version range constraint as satisfied when mixing x.y and x.y.z versions
* add mixed version checks to version comparison tests
This commit is contained in:
Peter Scheibel 2019-12-04 23:27:08 -07:00 committed by Todd Gamblin
parent 55ee2aecdf
commit e9ee9eaf50
5 changed files with 23 additions and 2 deletions

View file

@ -2182,7 +2182,7 @@ def concretize(self, tests=False):
# Add any patches from the package to the spec. # Add any patches from the package to the spec.
patches = [] patches = []
for cond, patch_list in s.package_class.patches.items(): for cond, patch_list in s.package_class.patches.items():
if s.satisfies(cond): if s.satisfies(cond, strict=True):
for patch in patch_list: for patch in patch_list:
patches.append(patch) patches.append(patch)
if patches: if patches:
@ -2201,7 +2201,7 @@ def concretize(self, tests=False):
patches = [] patches = []
for cond, dependency in pkg_deps[dspec.spec.name].items(): for cond, dependency in pkg_deps[dspec.spec.name].items():
if dspec.parent.satisfies(cond): if dspec.parent.satisfies(cond, strict=True):
for pcond, patch_list in dependency.patches.items(): for pcond, patch_list in dependency.patches.items():
if dspec.spec.satisfies(pcond): if dspec.spec.satisfies(pcond):
for patch in patch_list: for patch in patch_list:

View file

@ -24,6 +24,7 @@
foo_sha256 = 'b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c' foo_sha256 = 'b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c'
bar_sha256 = '7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730' bar_sha256 = '7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730'
baz_sha256 = 'bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c' baz_sha256 = 'bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c'
biz_sha256 = 'a69b288d7393261e613c276c6d38a01461028291f6e381623acc58139d01f54d'
# url patches # url patches
url1_sha256 = 'abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234' url1_sha256 = 'abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234'
@ -105,6 +106,20 @@ def test_patch_in_spec(mock_packages, config):
tuple(spec.variants['patches']._patches_in_order_of_appearance)) tuple(spec.variants['patches']._patches_in_order_of_appearance))
def test_patch_mixed_versions_subset_constraint(mock_packages, config):
"""If we have a package with mixed x.y and x.y.z versions, make sure that
a patch applied to a version range of x.y.z versions is not applied to
an x.y version.
"""
spec1 = Spec('patch@1.0.1')
spec1.concretize()
assert biz_sha256 in spec1.variants['patches'].value
spec2 = Spec('patch@1.0')
spec2.concretize()
assert biz_sha256 not in spec2.variants['patches'].value
def test_patch_order(mock_packages, config): def test_patch_order(mock_packages, config):
spec = Spec('dep-diamond-patch-top') spec = Spec('dep-diamond-patch-top')
spec.concretize() spec.concretize()

View file

@ -266,6 +266,8 @@ def test_contains():
assert_in('1.3.5-7', '1.2:1.4') assert_in('1.3.5-7', '1.2:1.4')
assert_not_in('1.1', '1.2:1.4') assert_not_in('1.1', '1.2:1.4')
assert_not_in('1.5', '1.2:1.4') assert_not_in('1.5', '1.2:1.4')
assert_not_in('1.5', '1.5.1:1.6')
assert_not_in('1.5', '1.5.1:')
assert_in('1.4.2', '1.2:1.4') assert_in('1.4.2', '1.2:1.4')
assert_not_in('1.4.2', '1.2:1.4.0') assert_not_in('1.4.2', '1.2:1.4.0')

View file

@ -0,0 +1 @@
this patch is never applied, it is used to check spec semantics on when the concretizer chooses to include a patch

View file

@ -13,11 +13,14 @@ class Patch(Package):
url = "http://www.example.com/patch-1.0.tar.gz" url = "http://www.example.com/patch-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef') version('1.0', '0123456789abcdef0123456789abcdef')
version('1.0.1')
version('1.0.2')
version('2.0', '0123456789abcdef0123456789abcdef') version('2.0', '0123456789abcdef0123456789abcdef')
patch('foo.patch') patch('foo.patch')
patch('bar.patch', when='@2:') patch('bar.patch', when='@2:')
patch('baz.patch') patch('baz.patch')
patch('biz.patch', when='@1.0.1:1.0.2')
def install(self, spec, prefix): def install(self, spec, prefix):
pass pass