url stats: add --show-issues option (#25792)

* tests: make `spack url [stats|summary]` work on mock packages

Mock packages have historically had mock hashes, but this means they're also invalid
as far as Spack's hash detection is concerned.

- [x] convert all hashes in mock package to md5 or sha256
- [x] ensure that all mock packages have a URL
- [x] ignore some special cases with multiple VCS fetchers

* url stats: add `--show-issues` option

`spack url stats` tells us how many URLs are using what protocol, type of checksum,
etc., but it previously did not tell us which packages and URLs had the issues. This
adds a `--show-issues` option to show URLs with insecure (`http`) URLs or `md5` hashes
(which are now deprecated by NIST).
This commit is contained in:
Todd Gamblin 2021-09-08 07:59:06 -07:00 committed by GitHub
parent c2a6ccbea8
commit c309adb4b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 266 additions and 169 deletions

View File

@ -9,6 +9,7 @@
import six.moves.urllib.parse as urllib_parse
import llnl.util.tty.color as color
from llnl.util import tty
import spack.fetch_strategy as fs
@ -80,9 +81,13 @@ def setup_parser(subparser):
help='print a summary of how well we are parsing package urls')
# Stats
sp.add_parser(
stats_parser = sp.add_parser(
'stats',
help='print statistics on versions and checksums for all packages')
stats_parser.add_argument(
"--show-issues", action="store_true",
help="show packages with issues (md5 hashes, http urls)"
)
def url(parser, args):
@ -262,6 +267,9 @@ def url_summary(args):
def url_stats(args):
# dictionary of issue type -> package -> descriptions
issues = defaultdict(lambda: defaultdict(lambda: []))
class UrlStats(object):
def __init__(self):
self.total = 0
@ -270,7 +278,7 @@ def __init__(self):
self.url_type = defaultdict(lambda: 0)
self.git_type = defaultdict(lambda: 0)
def add(self, fetcher):
def add(self, pkg_name, fetcher):
self.total += 1
url_type = fetcher.url_attr
@ -284,10 +292,18 @@ def add(self, fetcher):
algo = 'no checksum'
self.checksums[algo] += 1
if algo == "md5":
md5_hashes = issues["md5 hashes"]
md5_hashes[pkg_name].append(fetcher.url)
# parse out the URL scheme (https/http/ftp/etc.)
urlinfo = urllib_parse.urlparse(fetcher.url)
self.schemes[urlinfo.scheme] += 1
if urlinfo.scheme == "http":
http_urls = issues["http urls"]
http_urls[pkg_name].append(fetcher.url)
elif url_type == 'git':
if getattr(fetcher, 'commit', None):
self.git_type['commit'] += 1
@ -305,13 +321,16 @@ def add(self, fetcher):
for pkg in spack.repo.path.all_packages():
npkgs += 1
for v, args in pkg.versions.items():
fetcher = fs.for_package_version(pkg, v)
version_stats.add(fetcher)
for v in pkg.versions:
try:
fetcher = fs.for_package_version(pkg, v)
except (fs.InvalidArgsError, fs.FetcherConflict):
continue
version_stats.add(pkg.name, fetcher)
for _, resources in pkg.resources.items():
for resource in resources:
resource_stats.add(resource.fetcher)
resource_stats.add(pkg.name, resource.fetcher)
# print a nice summary table
tty.msg("URL stats for %d packages:" % npkgs)
@ -361,6 +380,21 @@ def print_stat(indent, name, stat_name=None):
print_stat(4, git_type, "git_type")
print_line()
if args.show_issues:
total_issues = sum(
len(issues)
for _, pkg_issues in issues.items()
for _, issues in pkg_issues.items()
)
print()
tty.msg("Found %d issues." % total_issues)
for issue_type, pkgs in issues.items():
tty.msg("Package URLs with %s" % issue_type)
for pkg, pkg_issues in pkgs.items():
color.cprint(" @*C{%s}" % pkg)
for issue in pkg_issues:
print(" %s" % issue)
def print_name_and_version(url):
"""Prints a URL. Underlines the detected name with dashes and

View File

@ -69,13 +69,15 @@ def test_url_with_no_version_fails():
url('parse', 'http://www.netlib.org/voronoi/triangle.zip')
@pytest.mark.maybeslow
@pytest.mark.skipif(
skip_python_26 = pytest.mark.skipif(
sys.version_info < (2, 7),
reason="Python 2.6 tests are run in a container, where "
"networking is super slow"
)
def test_url_list():
@skip_python_26
def test_url_list(mock_packages):
out = url('list')
total_urls = len(out.split('\n'))
@ -104,13 +106,8 @@ def test_url_list():
assert 0 < correct_version_urls < total_urls
@pytest.mark.maybeslow
@pytest.mark.skipif(
sys.version_info < (2, 7),
reason="Python 2.6 tests are run in a container, where "
"networking is super slow"
)
def test_url_summary():
@skip_python_26
def test_url_summary(mock_packages):
"""Test the URL summary command."""
# test url_summary, the internal function that does the work
(total_urls, correct_names, correct_versions,
@ -136,12 +133,8 @@ def test_url_summary():
assert out_correct_versions == correct_versions
@pytest.mark.skipif(
sys.version_info < (2, 7),
reason="Python 2.6 tests are run in a container, where "
"networking is super slow"
)
def test_url_stats(capfd):
@skip_python_26
def test_url_stats(capfd, mock_packages):
with capfd.disabled():
output = url('stats')
npkgs = '%d packages' % len(spack.repo.all_package_names())
@ -151,3 +144,20 @@ def test_url_stats(capfd):
assert 'schemes' in output
assert 'versions' in output
assert 'resources' in output
output = url('stats', '--show-issues')
npkgs = '%d packages' % len(spack.repo.all_package_names())
assert npkgs in output
assert 'url' in output
assert 'git' in output
assert 'schemes' in output
assert 'versions' in output
assert 'resources' in output
assert 'Package URLs with md5 hashes' in output
assert 'needs-relocation' in output
assert 'https://cmake.org/files/v3.4/cmake-0.0.0.tar.gz' in output
assert 'Package URLs with http urls' in output
assert 'zmpi' in output
assert 'http://www.spack-fake-zmpi.org/downloads/zmpi-1.0.tar.gz' in output

View File

@ -281,25 +281,28 @@ def test_git_url_top_level_url_versions(mock_packages, config):
pkg = spack.repo.get('git-url-top-level')
# leading 62 zeros of sha256 hash
leading_zeros = '0' * 62
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.0')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://example.com/some/tarball-2.0.tar.gz'
assert fetcher.digest == 'abc20'
assert fetcher.digest == leading_zeros + '20'
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.1')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://example.com/some/tarball-2.1.tar.gz'
assert fetcher.digest == 'abc21'
assert fetcher.digest == leading_zeros + '21'
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.2')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://www.example.com/foo2.2.tar.gz'
assert fetcher.digest == 'abc22'
assert fetcher.digest == leading_zeros + '22'
fetcher = spack.fetch_strategy.for_package_version(pkg, '2.3')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.url == 'https://www.example.com/foo2.3.tar.gz'
assert fetcher.digest == 'abc23'
assert fetcher.digest == leading_zeros + '23'
def test_git_url_top_level_git_versions(mock_packages, config):
@ -409,15 +412,15 @@ def test_fetch_options(mock_packages, config):
fetcher = spack.fetch_strategy.for_package_version(pkg, '1.0')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.digest == 'abc10'
assert fetcher.digest == '00000000000000000000000000000010'
assert fetcher.extra_options == {'timeout': 42, 'cookie': 'foobar'}
fetcher = spack.fetch_strategy.for_package_version(pkg, '1.1')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.digest == 'abc11'
assert fetcher.digest == '00000000000000000000000000000011'
assert fetcher.extra_options == {'timeout': 65}
fetcher = spack.fetch_strategy.for_package_version(pkg, '1.2')
assert isinstance(fetcher, spack.fetch_strategy.URLFetchStrategy)
assert fetcher.digest == 'abc12'
assert fetcher.digest == '00000000000000000000000000000012'
assert fetcher.extra_options == {'cookie': 'baz'}

View File

@ -160,13 +160,21 @@ def test_fetch(
@pytest.mark.parametrize('spec,url,digest', [
('url-list-test @0.0.0', 'foo-0.0.0.tar.gz', 'abc000'),
('url-list-test @1.0.0', 'foo-1.0.0.tar.gz', 'abc100'),
('url-list-test @3.0', 'foo-3.0.tar.gz', 'abc30'),
('url-list-test @4.5', 'foo-4.5.tar.gz', 'abc45'),
('url-list-test @2.0.0b2', 'foo-2.0.0b2.tar.gz', 'abc200b2'),
('url-list-test @3.0a1', 'foo-3.0a1.tar.gz', 'abc30a1'),
('url-list-test @4.5-rc5', 'foo-4.5-rc5.tar.gz', 'abc45rc5'),
('url-list-test @0.0.0', 'foo-0.0.0.tar.gz', '00000000000000000000000000000000'),
('url-list-test @1.0.0', 'foo-1.0.0.tar.gz', '00000000000000000000000000000100'),
('url-list-test @3.0', 'foo-3.0.tar.gz', '00000000000000000000000000000030'),
('url-list-test @4.5', 'foo-4.5.tar.gz', '00000000000000000000000000000450'),
(
'url-list-test @2.0.0b2',
'foo-2.0.0b2.tar.gz',
'000000000000000000000000000200b2'
),
('url-list-test @3.0a1', 'foo-3.0a1.tar.gz', '000000000000000000000000000030a1'),
(
'url-list-test @4.5-rc5',
'foo-4.5-rc5.tar.gz',
'000000000000000000000000000045c5'
),
])
@pytest.mark.parametrize('_fetch_method', ['curl', 'urllib'])
def test_from_list_url(mock_packages, config, spec, url, digest, _fetch_method):

View File

@ -1798,7 +1798,7 @@ _spack_url_summary() {
}
_spack_url_stats() {
SPACK_COMPREPLY="-h --help"
SPACK_COMPREPLY="-h --help --show-issues"
}
_spack_verify() {

View File

@ -13,7 +13,7 @@ class A(AutotoolsPackage):
url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash')
version('2.0', 'abcdef0123456789abcdef0123456789')
variant(
'foo', description='',

View File

@ -13,7 +13,7 @@ class ArchiveFiles(AutotoolsPackage):
url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash')
version('2.0', 'abcdef0123456789abcdef0123456789')
@property
def archive_files(self):

View File

@ -12,7 +12,7 @@ class BuildError(Package):
homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
with open('configure', 'w') as f:

View File

@ -12,7 +12,7 @@ class BuildWarnings(Package):
homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
with open('configure', 'w') as f:

View File

@ -10,9 +10,9 @@ class Callpath(Package):
homepage = "https://github.com/tgamblin/callpath"
url = "http://github.com/tgamblin/callpath-1.0.tar.gz"
version(0.8, 'foobarbaz')
version(0.9, 'foobarbaz')
version(1.0, 'foobarbaz')
version(0.8, '0123456789abcdef0123456789abcdef')
version(0.9, '0123456789abcdef0123456789abcdef')
version(1.0, '0123456789abcdef0123456789abcdef')
depends_on("dyninst")
depends_on("mpi")

View File

@ -10,9 +10,9 @@ class ConflictParent(Package):
homepage = 'https://github.com/tgamblin/callpath'
url = 'http://github.com/tgamblin/callpath-1.0.tar.gz'
version(0.8, 'foobarbaz')
version(0.9, 'foobarbaz')
version(1.0, 'foobarbaz')
version(0.8, '0123456789abcdef0123456789abcdef')
version(0.9, '0123456789abcdef0123456789abcdef')
version(1.0, '0123456789abcdef0123456789abcdef')
depends_on('conflict')

View File

@ -10,9 +10,9 @@ class Conflict(Package):
homepage = 'https://github.com/tgamblin/callpath'
url = 'http://github.com/tgamblin/callpath-1.0.tar.gz'
version(0.8, 'foobarbaz')
version(0.9, 'foobarbaz')
version(1.0, 'foobarbaz')
version(0.8, '0123456789abcdef0123456789abcdef')
version(0.9, '0123456789abcdef0123456789abcdef')
version(1.0, '0123456789abcdef0123456789abcdef')
variant('foo', default=True, description='')

View File

@ -12,8 +12,8 @@ class DependencyInstall(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', 'hash1.0')
version('2.0', 'hash2.0')
version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', 'abcdef0123456789abcdef0123456789')
def install(self, spec, prefix):
touch(join_path(prefix, 'an_installation_file'))

View File

@ -8,7 +8,7 @@ class DependentOfDevBuild(Package):
homepage = "example.com"
url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh')
version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
depends_on('dev-build-test-install')

View File

@ -8,7 +8,7 @@ class DevBuildTestDependent(Package):
homepage = "example.com"
url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh')
version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
phases = ['edit', 'install']

View File

@ -10,7 +10,7 @@ class DevBuildTestInstallPhases(Package):
homepage = "example.com"
url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh')
version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
phases = ['one', 'two', 'three', 'install']

View File

@ -8,7 +8,7 @@ class DevBuildTestInstall(Package):
homepage = "example.com"
url = "fake.com"
version('0.0.0', sha256='0123456789abcdefgh')
version('0.0.0', sha256='0123456789abcdef0123456789abcdef')
phases = ['edit', 'install']

View File

@ -10,6 +10,6 @@ class DirectMpich(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/direct_mpich-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
depends_on('mpich')

View File

@ -10,11 +10,11 @@ class Dyninst(Package):
homepage = "https://paradyn.org"
url = "http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz"
version('8.2', 'cxyzab',
version('8.2', '0123456789abcdef0123456789abcdef',
url='http://www.paradyn.org/release8.2/DyninstAPI-8.2.tgz')
version('8.1.2', 'bcxyza',
version('8.1.2', 'fedcba9876543210fedcba9876543210',
url='http://www.paradyn.org/release8.1.2/DyninstAPI-8.1.2.tgz')
version('8.1.1', 'abcxyz',
version('8.1.1', '123456789abcdef0123456789abcdef0',
url='http://www.paradyn.org/release8.1/DyninstAPI-8.1.1.tgz')
depends_on("libelf")

View File

@ -14,7 +14,7 @@ class Extendee(Package):
extendable = True
version('1.0', 'hash-extendee-1.0')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -16,8 +16,8 @@ class Extension1(Package):
extends('extendee')
version('1.0', 'hash-extension1-1.0')
version('2.0', 'hash-extension1-2.0')
version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', 'abcdef0123456789abcdef0123456789')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -18,7 +18,7 @@ class Extension2(Package):
extends('extendee')
depends_on('extension1', type=('build', 'run'))
version('1.0', 'hash-extension2-1.0')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -12,7 +12,7 @@ class FailingBuild(Package):
homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
raise InstallError("Expected failure.")

View File

@ -10,4 +10,4 @@ class Fake(Package):
homepage = "http://www.fake-spack-example.org"
url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')

View File

@ -17,6 +17,6 @@ class FetchOptions(Package):
timeout = {'timeout': 65}
cookie = {'cookie': 'baz'}
version('1.2', 'abc12', fetch_options=cookie)
version('1.1', 'abc11', fetch_options=timeout)
version('1.0', 'abc10')
version('1.2', '00000000000000000000000000000012', fetch_options=cookie)
version('1.1', '00000000000000000000000000000011', fetch_options=timeout)
version('1.0', '00000000000000000000000000000010')

View File

@ -10,8 +10,8 @@ class Fftw(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/fftw-1.0.tar.gz"
version(2.0, 'foobar')
version(1.0, 'foobar')
version(2.0, 'abcdef1234567890abcdef1234567890')
version(1.0, '1234567890abcdef1234567890abcdef')
variant('mpi', default=False, description='Enable MPI')

View File

@ -13,7 +13,7 @@ class FindExternals1(AutotoolsPackage):
url = "http://www.example.com/find-externals-1.0.tar.gz"
version('1.0', 'hash-1.0')
version('1.0', 'abcdef1234567890abcdef1234567890')
@classmethod
def determine_spec_details(cls, prefix, exes_in_prefix):

View File

@ -13,8 +13,8 @@ class Gcc(Package):
url = "http://www.example.com/gcc-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash')
version('3.0', '3.0_a_hash')
version('2.0', 'abcdef0123456789abcdef0123456789')
version('3.0', 'def0123456789abcdef0123456789abc')
depends_on('conflict', when='@3.0')

View File

@ -28,13 +28,35 @@ class GitUrlTopLevel(Package):
version('3.0', tag='v3.0')
# These resolve to URL fetchers
version('2.3', 'abc23', url='https://www.example.com/foo2.3.tar.gz')
version('2.2', sha256='abc22', url='https://www.example.com/foo2.2.tar.gz')
version('2.1', sha256='abc21')
version('2.0', 'abc20')
version(
'2.3', '0000000000000000000000000000000000000000000000000000000000000023',
url='https://www.example.com/foo2.3.tar.gz',
)
version(
'2.2',
sha256='0000000000000000000000000000000000000000000000000000000000000022',
url='https://www.example.com/foo2.2.tar.gz',
)
version(
'2.1',
sha256='0000000000000000000000000000000000000000000000000000000000000021',
)
version(
'2.0',
'0000000000000000000000000000000000000000000000000000000000000020',
)
# These result in a FetcherConflict b/c we can't tell what to use
version('1.3', sha256='abc13', commit='abc13')
version('1.2', sha512='abc12', branch='releases/v1.2')
version('1.1', md5='abc11', tag='v1.1')
version('1.0', 'abc11', tag='abc123')
version(
'1.3',
sha256='f66bbef3ccb8b06542c57d69804c5b0aba72051f693c17761ad8525786d259fa',
commit='abc13'
)
version(
'1.2',
sha512='f66bbef3ccb8b06542c57d69804c5b0aba72051f693c17761ad8525786d259fa'
'9ed8f2e950a4fb8a4b936f33e689187784699357bc16e49f33dfcda8ab8b00e4',
branch='releases/v1.2'
)
version('1.1', md5='00000000000000000000000000000011', tag='v1.1')
version('1.0', '00000000000000000000000000000011', tag='abc123')

View File

@ -3,8 +3,10 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class Gmt(Package):
url = "http://www.example.com/"
url = "http://www.example.com/2.0.tar.gz"
version('2.0', 'abcdef')
version('1.0', 'abcdef')
version('2.0', 'abcdef1234567890abcdef1234567890')
version('1.0', 'abcdef1234567890abcdef1234567890')
depends_on('mvdefaults', when='@1.0')

View File

@ -8,7 +8,7 @@ class Hdf5(Package):
homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/hdf5-1.0.tar.gz"
version(2.3, 'foobarbaz')
version(2.3, '0123456789abcdef0123456789abcdef')
variant('mpi', default=True, description='Enable mpi')

View File

@ -10,6 +10,6 @@ class ImpossibleConcretization(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/example-1.0.tar.gz"
version(1.0, 'foobarbaz')
version(1.0, '0123456789abcdef0123456789abcdef')
conflicts('target=x86_64:')

View File

@ -14,7 +14,7 @@ class IndirectMpich(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/indirect_mpich-1.0.tar.gz"
version(1.0, 'foobarbaz')
version(1.0, '0123456789abcdef0123456789abcdef')
depends_on('mpi')
depends_on('direct-mpich')

View File

@ -3,7 +3,10 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class LeafAddsVirtual(Package):
version('2.0', sha256='abcde')
version('1.0', sha256='abcde')
url = "http://www.example.com/"
url = "http://www.example.com/2.0.tar.gz"
version('2.0', 'abcdef1234567890abcdef1234567890')
version('1.0', 'abcdef1234567890abcdef1234567890')
depends_on('blas', when='@2.0')

View File

@ -15,9 +15,9 @@ class Libdwarf(Package):
list_url = homepage
version(20130729, "64b42692e947d5180e162e46c689dfbf")
version(20130207, 'foobarbaz')
version(20111030, 'foobarbaz')
version(20070703, 'foobarbaz')
version(20130207, '0123456789abcdef0123456789abcdef')
version(20111030, '0123456789abcdef0123456789abcdef')
version(20070703, '0123456789abcdef0123456789abcdef')
depends_on("libelf")

View File

@ -3,5 +3,9 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class MiddleAddsVirtual(Package):
version('1.0', sha256='abcde')
url = "http://www.example.com/"
url = "http://www.example.com/2.0.tar.gz"
version('1.0', 'abcdef1234567890abcdef1234567890')
depends_on('leaf-adds-virtual')

View File

@ -9,6 +9,6 @@
class Mixedversions(Package):
url = "http://www.fake-mixedversions.org/downloads/mixedversions-1.0.tar.gz"
version('2.0.1', 'hashc')
version('2.0', 'hashb')
version('1.0.1', 'hasha')
version('2.0.1', '0000000000000000000000000000000c')
version('2.0', '0000000000000000000000000000000b')
version('1.0.1', '0000000000000000000000000000000a')

View File

@ -10,7 +10,7 @@ class ModulePathSeparator(Package):
homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/module-path-separator-1.0.tar.gz"
version(1.0, 'foobarbaz')
version(1.0, '0123456789abcdef0123456789abcdef')
def setup_environment(self, senv, renv):
renv.append_path("COLON", "foo")

View File

@ -18,11 +18,11 @@ class Mpich(Package):
description="Compile MPICH with debug flags.")
version('3.0.4', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
version('3.0.3', 'foobarbaz')
version('3.0.2', 'foobarbaz')
version('3.0.1', 'foobarbaz')
version('3.0', 'foobarbaz')
version('1.0', 'foobarbas')
version('3.0.3', '0123456789abcdef0123456789abcdef')
version('3.0.2', '0123456789abcdef0123456789abcdef')
version('3.0.1', '0123456789abcdef0123456789abcdef')
version('3.0', '0123456789abcdef0123456789abcdef')
version('1.0', '0123456789abcdef0123456789abcdef')
provides('mpi@:3', when='@3:')
provides('mpi@:1', when='@:1')

View File

@ -15,11 +15,11 @@ class Mpich2(Package):
tags = ['tag1', 'tag3']
version('1.5', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
version('1.4', 'foobarbaz')
version('1.3', 'foobarbaz')
version('1.2', 'foobarbaz')
version('1.1', 'foobarbaz')
version('1.0', 'foobarbaz')
version('1.4', '0123456789abcdef0123456789abcdef')
version('1.3', '0123456789abcdef0123456789abcdef')
version('1.2', '0123456789abcdef0123456789abcdef')
version('1.1', '0123456789abcdef0123456789abcdef')
version('1.0', '0123456789abcdef0123456789abcdef')
provides('mpi@:2.0')
provides('mpi@:2.1', when='@1.1:')

View File

@ -10,10 +10,10 @@ class Mpileaks(Package):
homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz')
version(2.1, 'foobarbaz')
version(2.2, 'foobarbaz')
version(2.3, 'foobarbaz')
version(1.0, '0123456789abcdef0123456789abcdef')
version(2.1, '0123456789abcdef0123456789abcdef')
version(2.2, '0123456789abcdef0123456789abcdef')
version(2.3, '0123456789abcdef0123456789abcdef')
variant('debug', default=False, description='Debug variant')
variant('opt', default=False, description='Optimized variant')

View File

@ -12,13 +12,13 @@ class MultiProviderMpi(Package):
homepage = "http://www.spack-fake-mpi.org"
url = "http://www.spack-fake-mpi.org/downloads/multi-mpi-1.0.tar.gz"
version('2.0.0', 'foobarbaz')
version('1.10.3', 'foobarbaz')
version('1.10.2', 'foobarbaz')
version('1.10.1', 'foobarbaz')
version('1.10.0', 'foobarbaz')
version('1.8.8', 'foobarbaz')
version('1.6.5', 'foobarbaz')
version('2.0.0', '0123456789abcdef0123456789abcdef')
version('1.10.3', '0123456789abcdef0123456789abcdef')
version('1.10.2', '0123456789abcdef0123456789abcdef')
version('1.10.1', '0123456789abcdef0123456789abcdef')
version('1.10.0', '0123456789abcdef0123456789abcdef')
version('1.8.8', '0123456789abcdef0123456789abcdef')
version('1.6.5', '0123456789abcdef0123456789abcdef')
provides('mpi@3.1', when='@2.0.0')
provides('mpi@3.0', when='@1.10.3')

View File

@ -10,10 +10,10 @@ class MultivalueVariant(Package):
homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz')
version(2.1, 'foobarbaz')
version(2.2, 'foobarbaz')
version(2.3, 'foobarbaz')
version(1.0, '0123456789abcdef0123456789abcdef')
version(2.1, '0123456789abcdef0123456789abcdef')
version(2.2, '0123456789abcdef0123456789abcdef')
version(2.3, '0123456789abcdef0123456789abcdef')
variant('debug', default=False, description='Debug variant')
variant(

View File

@ -3,8 +3,10 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class Mvdefaults(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/mvdefaults-1.0.tar.gz"
version('1.0', 'abcdef')
version('1.0', 'abcdef1234567890abcdef1234567890')
variant('foo', values=('a', 'b', 'c'), default=('a', 'b', 'c'),
multi=True, description='')

View File

@ -14,7 +14,7 @@ class OverrideContextTemplates(Package):
homepage = "http://www.fake-spack-example.org"
url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
tcl_template = 'extension.tcl'
tcl_context = {'sentence': "sentence from package"}

View File

@ -10,7 +10,7 @@ class OverrideModuleTemplates(Package):
homepage = "http://www.fake-spack-example.org"
url = "http://www.fake-spack-example.org/downloads/fake-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
tcl_template = 'override.txt'
lmod_template = 'override.txt'

View File

@ -13,8 +13,8 @@ class PerlExtension(PerlPackage):
homepage = "http://www.example.com"
url = "http://www.example.com/extension1-1.0.tar.gz"
version('1.0', 'hash-extension-1.0')
version('2.0', 'hash-extension-2.0')
version('1.0', '00000000000000000000000000000010')
version('2.0', '00000000000000000000000000000020')
extends("perl")

View File

@ -12,4 +12,4 @@ class Perl(Package):
extendable = True
version('0.0.0', 'hash')
version('0.0.0', 'abcdef1234567890abcdef1234567890')

View File

@ -14,7 +14,7 @@ class PrintingPackage(Package):
homepage = "http://www.example.com/printing_package"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
print("BEFORE INSTALL")

View File

@ -16,8 +16,8 @@ class PyExtension1(PythonPackage):
# Override settings in base class
maintainers = []
version('1.0', 'hash-extension1-1.0')
version('2.0', 'hash-extension1-2.0')
version('1.0', '00000000000000000000000000000110')
version('2.0', '00000000000000000000000000000120')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -20,7 +20,7 @@ class PyExtension2(PythonPackage):
extends("python")
depends_on('py-extension1', type=('build', 'run'))
version('1.0', 'hash-extension2-1.0')
version('1.0', '00000000000000000000000000000210')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -16,6 +16,6 @@ class PyExtension3(Package):
depends_on('patchelf@0.9', when='@1.0:1.1 ^python@:2')
depends_on('patchelf@0.10', when='@1.0:1.1 ^python@3:')
version('2.0', 'hash-extension3-1.0')
version('1.1', 'hash-extension3-1.0')
version('1.0', 'hash-extension3-1.0')
version('2.0', '00000000000000000000000000000320')
version('1.1', '00000000000000000000000000000311')
version('1.0', '00000000000000000000000000000310')

View File

@ -10,7 +10,7 @@ class QuantumEspresso(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/qe-1.0.tar.gz"
version(1.0, 'foobar')
version(1.0, '1234567890abcdef1234567890abcdef')
variant('invino', default=True, description='?')
variant('veritas', default=True, description='?')

View File

@ -17,7 +17,7 @@ class Raiser(Package):
url = "http://www.example.com/a-1.0.tar.gz"
version('1.0', '0123456789abcdef0123456789abcdef')
version('2.0', '2.0_a_hash')
version('2.0', 'abcdef0123456789abcdef0123456789')
variant(
'exc_type',

View File

@ -11,6 +11,6 @@ class RequiresVirtual(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/a-1.0.tar.gz"
version('2.0', '2.0_a_hash')
version('2.0', 'abcdef0123456789abcdef0123456789')
depends_on('stuff')

View File

@ -3,6 +3,9 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class RootAddsVirtual(Package):
version('1.0', sha256='abcde')
homepage = "http://www.example.com"
url = "http://www.example.com/root-adds-virtual-1.0.tar.gz"
version('1.0', sha256='abcdef0123456789abcdef0123456789')
depends_on('middle-adds-virtual')

View File

@ -3,6 +3,9 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
class Root(Package):
version('1.0', 'abcdef')
homepage = "http://www.example.com"
url = "http://www.example.com/root-1.0.tar.gz"
version('1.0', 'abcdef0123456789abcdef0123456789')
depends_on('gmt')

View File

@ -8,7 +8,7 @@ class SinglevalueVariant(Package):
homepage = "http://www.llnl.gov"
url = "http://www.llnl.gov/mpileaks-1.0.tar.gz"
version(1.0, 'foobarbaz')
version(1.0, '0123456789abcdef0123456789abcdef')
variant(
'fum',

View File

@ -12,7 +12,7 @@ class TestError(Package):
homepage = "http://www.example.com/test-failure"
url = "http://www.test-failure.test/test-failure-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -12,7 +12,7 @@ class TestFail(Package):
homepage = "http://www.example.com/test-failure"
url = "http://www.test-failure.test/test-failure-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
mkdirp(prefix.bin)

View File

@ -7,6 +7,6 @@ class TriggerExternalNonDefaultVariant(Package):
homepage = "http://www.example.com"
url = "http://www.someurl.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
depends_on('external-non-default-variant')

View File

@ -12,7 +12,7 @@ class TrivialInstallTestPackage(Package):
homepage = "http://www.example.com/trivial_install"
url = "http://www.unit-test-should-replace-this-url/trivial_install-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
def install(self, spec, prefix):
configure('--prefix=%s' % prefix)

View File

@ -11,7 +11,7 @@ class TrivialSmokeTest(Package):
homepage = "http://www.example.com/trivial_test"
url = "http://www.unit-test-should-replace-this-url/trivial_test-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
test_source_filename = 'cached_file.in'

View File

@ -7,7 +7,7 @@ class UnsatProvider(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/v1.0.tgz"
version('1.0', sha256='foobarbaz')
version('1.0', sha256='0123456789abcdef0123456789abcdef')
variant('foo', default=True, description='')

View File

@ -7,6 +7,6 @@ class UnsatVirtualDependency(Package):
homepage = "http://www.example.com"
url = "http://www.example.com/v1.0.tgz"
version('1.0', sha256='foobarbaz')
version('1.0', sha256='0123456789abcdef0123456789abcdef')
depends_on('unsatvdep')

View File

@ -16,10 +16,10 @@ class UrlListTest(Package):
list_url = 'file://' + web_data_path + '/index.html'
list_depth = 3
version('0.0.0', 'abc000')
version('1.0.0', 'abc100')
version('3.0', 'abc30')
version('4.5', 'abc45')
version('2.0.0b2', 'abc200b2')
version('3.0a1', 'abc30a1')
version('4.5-rc5', 'abc45rc5')
version('0.0.0', '00000000000000000000000000000000')
version('1.0.0', '00000000000000000000000000000100')
version('3.0', '00000000000000000000000000000030')
version('4.5', '00000000000000000000000000000450')
version('2.0.0b2', '000000000000000000000000000200b2')
version('3.0a1', '000000000000000000000000000030a1')
version('4.5-rc5', '000000000000000000000000000045c5')

View File

@ -9,10 +9,13 @@
class UrlOnlyOverrideWithGaps(Package):
homepage = 'http://www.example.com'
version('1.0.5', 'abcdef0')
version('1.0.0', 'bcdef0a', url='http://a.example.com/url_override-1.0.0.tar.gz')
version('0.9.5', 'cdef0ab')
version('0.9.0', 'def0abc', url='http://b.example.com/url_override-0.9.0.tar.gz')
version('0.8.5', 'ef0abcd')
version('0.8.1', 'f0abcde', url='http://c.example.com/url_override-0.8.1.tar.gz')
version('0.7.0', '0abcdef')
version('1.0.5', 'abcdef0123456789abcdef0123456789')
version('1.0.0', 'bcdef0123456789abcdef0123456789a',
url='http://a.example.com/url_override-1.0.0.tar.gz')
version('0.9.5', 'cdef0123456789abcdef0123456789ab')
version('0.9.0', 'def0123456789abcdef0123456789abc',
url='http://b.example.com/url_override-0.9.0.tar.gz')
version('0.8.5', 'ef0123456789abcdef0123456789abcd')
version('0.8.1', 'f0123456789abcdef0123456789abcde',
url='http://c.example.com/url_override-0.8.1.tar.gz')
version('0.7.0', '0123456789abcdef0123456789abcdef')

View File

@ -9,6 +9,6 @@
class UrlOnlyOverride(Package):
homepage = 'http://www.example.com'
version('1.0.0', 'cxyzab', url='http://a.example.com/url_override-1.0.0.tar.gz')
version('0.9.0', 'bcxyza', url='http://b.example.com/url_override-0.9.0.tar.gz')
version('0.8.1', 'cxyzab', url='http://c.example.com/url_override-0.8.1.tar.gz')
version('1.0.0', '0123456789abcdef0123456789abcdef', url='http://a.example.com/url_override-1.0.0.tar.gz')
version('0.9.0', 'fedcba9876543210fedcba9876543210', url='http://b.example.com/url_override-0.9.0.tar.gz')
version('0.8.1', '0123456789abcdef0123456789abcdef', url='http://c.example.com/url_override-0.8.1.tar.gz')

View File

@ -10,6 +10,6 @@ class UrlOverride(Package):
homepage = 'http://www.doesnotexist.org'
url = 'http://www.doesnotexist.org/url_override-1.0.0.tar.gz'
version('1.0.0', 'cxyzab')
version('0.9.0', 'bcxyza', url='http://www.anothersite.org/uo-0.9.0.tgz')
version('0.8.1', 'cxyzab')
version('1.0.0', '0123456789abcdef0123456789abcdef')
version('0.9.0', 'fedcba9876543210fedcba9876543210', url='http://www.anothersite.org/uo-0.9.0.tgz')
version('0.8.1', '0123456789abcdef0123456789abcdef')

View File

@ -12,7 +12,7 @@ class Zmpi(Package):
homepage = "http://www.spack-fake-zmpi.org"
url = "http://www.spack-fake-zmpi.org/downloads/zmpi-1.0.tar.gz"
version('1.0', 'foobarbaz')
version('1.0', '0123456789abcdef0123456789abcdef')
provides('mpi@:10.0')
depends_on('fake')