core: add check for conflicting top-level fetch attributes in packages
- ensure that packages can't have more than one of git, hg, svn, or url
This commit is contained in:
parent
6837da2ad7
commit
04aec9d6f8
4 changed files with 35 additions and 6 deletions
|
@ -56,7 +56,7 @@
|
||||||
import spack.util.crypto as crypto
|
import spack.util.crypto as crypto
|
||||||
import spack.util.pattern as pattern
|
import spack.util.pattern as pattern
|
||||||
from spack.util.executable import which
|
from spack.util.executable import which
|
||||||
from spack.util.string import comma_or
|
from spack.util.string import comma_or, comma_and, quote
|
||||||
from spack.version import Version, ver
|
from spack.version import Version, ver
|
||||||
from spack.util.compression import decompressor_for, extension
|
from spack.util.compression import decompressor_for, extension
|
||||||
|
|
||||||
|
@ -968,9 +968,26 @@ def args_are_for(args, fetcher):
|
||||||
fetcher.matches(args)
|
fetcher.matches(args)
|
||||||
|
|
||||||
|
|
||||||
|
def check_attributes(pkg):
|
||||||
|
"""Find ambiguous top-level fetch attributes in a package."""
|
||||||
|
# a single package cannot have required attributes from multiple
|
||||||
|
# fetch strategies *unless* they are the same attribute.
|
||||||
|
conflicts = set(
|
||||||
|
sum([[a for a in s.required_attributes if hasattr(pkg, a)]
|
||||||
|
for s in all_strategies],
|
||||||
|
[]))
|
||||||
|
|
||||||
|
if len(conflicts) > 1:
|
||||||
|
raise FetcherConflict(
|
||||||
|
'Package %s cannot specify %s together. Must pick only one.'
|
||||||
|
% (pkg.name, comma_and(quote(conflicts))))
|
||||||
|
|
||||||
|
|
||||||
def for_package_version(pkg, version):
|
def for_package_version(pkg, version):
|
||||||
"""Determine a fetch strategy based on the arguments supplied to
|
"""Determine a fetch strategy based on the arguments supplied to
|
||||||
version() in the package description."""
|
version() in the package description."""
|
||||||
|
check_attributes(pkg)
|
||||||
|
|
||||||
if not isinstance(version, Version):
|
if not isinstance(version, Version):
|
||||||
version = Version(version)
|
version = Version(version)
|
||||||
|
|
||||||
|
@ -1094,6 +1111,10 @@ class ExtrapolationError(FetchError):
|
||||||
"""Raised when we can't extrapolate a version for a package."""
|
"""Raised when we can't extrapolate a version for a package."""
|
||||||
|
|
||||||
|
|
||||||
|
class FetcherConflict(FetchError):
|
||||||
|
"""Raised for packages with invalid fetch attributes."""
|
||||||
|
|
||||||
|
|
||||||
class InvalidArgsError(FetchError):
|
class InvalidArgsError(FetchError):
|
||||||
def __init__(self, pkg, version):
|
def __init__(self, pkg, version):
|
||||||
msg = ("Could not construct a fetch strategy for package %s at "
|
msg = ("Could not construct a fetch strategy for package %s at "
|
||||||
|
|
|
@ -831,7 +831,12 @@ def get(self, spec):
|
||||||
package_class = self.get_pkg_class(spec.name)
|
package_class = self.get_pkg_class(spec.name)
|
||||||
try:
|
try:
|
||||||
return package_class(spec)
|
return package_class(spec)
|
||||||
|
except spack.error.SpackError:
|
||||||
|
# pass these through as their error messages will be fine.
|
||||||
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
|
# make sure other errors in constructors hit the error
|
||||||
|
# handler by wrapping them
|
||||||
if spack.config.get('config:debug'):
|
if spack.config.get('config:debug'):
|
||||||
sys.excepthook(*sys.exc_info())
|
sys.excepthook(*sys.exc_info())
|
||||||
raise FailedConstructorError(spec.fullname, *sys.exc_info())
|
raise FailedConstructorError(spec.fullname, *sys.exc_info())
|
||||||
|
|
|
@ -264,9 +264,8 @@ def test_no_extrapolate_without_url(mock_packages, config):
|
||||||
|
|
||||||
|
|
||||||
def test_git_and_url_top_level(mock_packages, config):
|
def test_git_and_url_top_level(mock_packages, config):
|
||||||
"""Verify that URL takes precedence over other top-level attributes."""
|
"""Verify conflict when url and git are specified together."""
|
||||||
pkg = spack.repo.get('git-and-url-top-level')
|
|
||||||
|
|
||||||
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.0')
|
pkg = spack.repo.get('git-and-url-top-level')
|
||||||
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
|
with pytest.raises(spack.fetch_strategy.FetcherConflict):
|
||||||
assert fetcher.url == 'https://example.com/some/tarball-2.0.tar.gz'
|
spack.fetch_strategy.for_package_version(pkg, '1.0')
|
||||||
|
|
|
@ -49,3 +49,7 @@ def comma_or(sequence):
|
||||||
|
|
||||||
def comma_and(sequence):
|
def comma_and(sequence):
|
||||||
return comma_list(sequence, 'and')
|
return comma_list(sequence, 'and')
|
||||||
|
|
||||||
|
|
||||||
|
def quote(sequence, q="'"):
|
||||||
|
return ['%s%s%s' % (q, e, q) for e in sequence]
|
||||||
|
|
Loading…
Reference in a new issue